chiark / gitweb /
[PATCH] deleted current extras/multipath directory
[elogind.git] / udevd.c
diff --git a/udevd.c b/udevd.c
index 8ba833186e100bb3958acb0d0c6b2ff6e81beae1..efcb65bb53f3d78da04a723d213f90e0e3332fd9 100644 (file)
--- a/udevd.c
+++ b/udevd.c
@@ -40,7 +40,6 @@
 #include "udevd.h"
 #include "logging.h"
 
-unsigned char logname[42];
 static int expected_seqnum = 0;
 volatile static int children_waiting;
 volatile static int msg_q_timeout;
@@ -52,6 +51,18 @@ LIST_HEAD(running_list);
 static void exec_queue_manager(void);
 static void msg_queue_manager(void);
 
+#ifdef LOG
+unsigned char logname[LOGNAME_SIZE];
+void log_message (int level, const char *format, ...)
+{
+       va_list args;
+
+       va_start(args, format);
+       vsyslog(level, format, args);
+       va_end(args);
+}
+#endif
+
 static void msg_dump_queue(void)
 {
        struct hotplug_msg *msg;
@@ -108,14 +119,18 @@ static void msg_queue_insert(struct hotplug_msg *msg)
 static void udev_run(struct hotplug_msg *msg)
 {
        pid_t pid;
-       setenv("ACTION", msg->action, 1);
-       setenv("DEVPATH", msg->devpath, 1);
+       char action[ACTION_SIZE];
+       char devpath[DEVPATH_SIZE];
+       char *env[] = { action, devpath, NULL };
+
+       snprintf(action, sizeof(action), "ACTION=%s", msg->action);
+       snprintf(devpath, sizeof(devpath), "DEVPATH=%s", msg->devpath);
 
        pid = fork();
        switch (pid) {
        case 0:
                /* child */
-               execl(UDEV_BIN, "udev", msg->subsystem, NULL);
+               execle(UDEV_BIN, "udev", msg->subsystem, NULL, env);
                dbg("exec of child failed");
                exit(1);
                break;
@@ -212,6 +227,11 @@ static void handle_msg(int sock)
 {
        struct hotplug_msg *msg;
        int retval;
+       struct msghdr smsg;
+       struct cmsghdr *cmsg;
+       struct iovec iov;
+       struct ucred *cred;
+       char cred_msg[CMSG_SPACE(sizeof(struct ucred))];
 
        msg = msg_create();
        if (msg == NULL) {
@@ -219,17 +239,37 @@ static void handle_msg(int sock)
                return;
        }
 
-       retval = recv(sock, msg, sizeof(struct hotplug_msg), 0);
+       iov.iov_base = msg;
+       iov.iov_len = sizeof(struct hotplug_msg);
+
+       memset(&smsg, 0x00, sizeof(struct msghdr));
+       smsg.msg_iov = &iov;
+       smsg.msg_iovlen = 1;
+       smsg.msg_control = cred_msg;
+       smsg.msg_controllen = sizeof(cred_msg);
+
+       retval = recvmsg(sock, &smsg, 0);
        if (retval <  0) {
                if (errno != EINTR)
                        dbg("unable to receive message");
                return;
        }
-       
+       cmsg = CMSG_FIRSTHDR(&smsg);
+       cred = (struct ucred *) CMSG_DATA(cmsg);
+
+       if (cmsg == NULL || cmsg->cmsg_type != SCM_CREDENTIALS) {
+               dbg("no sender credentials received, message ignored");
+               goto skip;
+       }
+
+       if (cred->uid != 0) {
+               dbg("sender uid=%i, message ignored", cred->uid);
+               goto skip;
+       }
+
        if (strncmp(msg->magic, UDEV_MAGIC, sizeof(UDEV_MAGIC)) != 0 ) {
                dbg("message magic '%s' doesn't match, ignore it", msg->magic);
-               free(msg);
-               return;
+               goto skip;
        }
 
        /* if no seqnum is given, we move straight to exec queue */
@@ -239,6 +279,11 @@ static void handle_msg(int sock)
        } else {
                msg_queue_insert(msg);
        }
+       return;
+
+skip:
+       free(msg);
+       return;
 }
 
 static void sig_handler(int signum)
@@ -279,17 +324,28 @@ int main(int argc, char *argv[])
        struct sockaddr_un saddr;
        socklen_t addrlen;
        int retval;
+       const int on = 1;
+       struct sigaction act;
 
        init_logging("udevd");
+       dbg("version %s", UDEV_VERSION);
 
-       signal(SIGINT, sig_handler);
-       signal(SIGTERM, sig_handler);
-       signal(SIGALRM, sig_handler);
-       signal(SIGCHLD, sig_handler);
+       if (getuid() != 0) {
+               dbg("need to be root, exit");
+               exit(1);
+       }
+
+       /* set signal handler */
+       act.sa_handler = sig_handler;
+       sigemptyset (&act.sa_mask);
+       act.sa_flags = SA_RESTART;
+       sigaction(SIGINT, &act, NULL);
+       sigaction(SIGTERM, &act, NULL);
 
        /* we want these two to interrupt system calls */
-       siginterrupt(SIGALRM, 1);
-       siginterrupt(SIGCHLD, 1);
+       act.sa_flags = 0;
+       sigaction(SIGALRM, &act, NULL);
+       sigaction(SIGCHLD, &act, NULL);
 
        memset(&saddr, 0x00, sizeof(saddr));
        saddr.sun_family = AF_LOCAL;
@@ -299,17 +355,20 @@ int main(int argc, char *argv[])
 
        ssock = socket(AF_LOCAL, SOCK_DGRAM, 0);
        if (ssock == -1) {
-               dbg("error getting socket");
+               dbg("error getting socket, exit");
                exit(1);
        }
 
        /* the bind takes care of ensuring only one copy running */
-       retval = bind(ssock, &saddr, addrlen);
+       retval = bind(ssock, (struct sockaddr *) &saddr, addrlen);
        if (retval < 0) {
-               dbg("bind failed\n");
+               dbg("bind failed, exit");
                goto exit;
        }
 
+       /* enable receiving of the sender credentials */
+       setsockopt(ssock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));
+
        while (1) {
                handle_msg(ssock);