passing access rights

Oliver Laumann net at tub.UUCP
Fri Oct 21 02:57:23 AEST 1988


Although this article contains a question, I think the matter
is `wizardry' enough to justify a posting to comp.unix.wizards.

What I would like to do is to pass a file descriptor from one
process to another one through a connection based on UNIX
domain sockets.  Although the demonstration program attached
to this article works fine under Integrated Solutions 4.3 BSD
and SunOS 4.0, the calls to `sendmsg' and `recvmsg' both
return "Bad address" under vanilla 4.3 BSD on a Microvax.
I can't find the bug; all fields of the message structures
passed to `sendmsg' and `recvmsg' are properly initialized.
Unfortunately, the manual entries for these system calls
do not indicate under what circumstances EFAULT is returned.

Note that the `msg' structures are declared as `static'.
And yes, I know, the programming style is sloppy (returning
no value from main; return values of sys-calls not checked,
etc.); my `real' programs certainly look differently.

Here comes the code; first the server which accepts a
connection on a UNIX domain socket and then opens /etc/passwd
and sends the file descriptor to the client process (note that
I don't want to send any data -- just the file descriptor).

------------------------------------------------------------
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/uio.h>

main () {
    int s, fd;
    struct sockaddr_un a;
    static struct msghdr msg;
    char *name = "foo";

    unlink (name);
    if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) == -1) {
	perror ("socket"); return;
    }
    a.sun_family = AF_UNIX;
    strcpy (a.sun_path, name);
    if (bind (s, (struct sockaddr *)&a, strlen (name)+2) == -1) {
	perror ("bind"); return;
    }
    listen (s, 1);
    s = accept (s, (struct sockaddr *)0, (int *)0);
    if ((fd = open ("/etc/passwd", 0)) == -1) {
	perror ("passwd"); return;
    }
    msg.msg_accrights = (caddr_t)&fd;
    msg.msg_accrightslen = sizeof (fd);
    if (sendmsg (s, &msg, 0) == -1)
	perror ("sendmsg");
}
------------------------------------------------------------

This is the client receiving the file descriptor:

------------------------------------------------------------
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/uio.h>

main () {
    int s, n, fd;
    struct sockaddr_un a;
    static struct msghdr msg;
    char *name = "foo";
    char buf[512];

    if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) == -1) {
	perror ("socket"); return;
    }
    a.sun_family = AF_UNIX;
    strcpy (a.sun_path, name);
    if (connect (s, (struct sockaddr *)&a, strlen (name)+2) == -1) {
	perror ("connect"); return;
    }
    msg.msg_accrights = (caddr_t)&fd;
    msg.msg_accrightslen = sizeof(fd);
    if ((n = recvmsg (s, &msg, 0)) == -1) {
	perror ("recvmsg"); return;
    }
    if ((n = read (fd, buf, 512)) == -1) {
	perror ("read"); return;
    }
    write (1, buf, n);
}
------------------------------------------------------------

Just compile the programs, start the server in the background,
then invoke the client and watch the error messages.

--
Regards,
    Oliver Laumann, Technical University of Berlin, Germany.
    ...!pyramid!tub!net   or   net at TUB.BITNET
    ...!mcvax!unido!tub!net



More information about the Comp.unix.wizards mailing list