[lib] check udev and netlink messages sender uid
authorChristophe Varoqui <christophe.varoqui@free.fr>
Sun, 19 Apr 2009 22:16:58 +0000 (00:16 +0200)
committerChristophe Varoqui <christophe.varoqui@free.fr>
Sun, 19 Apr 2009 22:16:58 +0000 (00:16 +0200)
Ignore if not 0.
This change was suggested by Kay Sievers. It required switching from
recv() to recvmsg().

libmultipath/uevent.c

index e18ec25..92bd978 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <unistd.h>
 #include <stdio.h>
+#include <errno.h>
 #include <stdlib.h>
 #include <stddef.h>
 #include <string.h>
@@ -204,22 +205,58 @@ int uevent_listen(int (*uev_trigger)(struct uevent *, void * trigger_data),
        }
 
        while (1) {
-               static char buff[HOTPLUG_BUFFER_SIZE + OBJECT_SIZE];
                int i;
                char *pos;
                size_t bufpos;
                ssize_t buflen;
                struct uevent *uev;
                char *buffer;
+               struct msghdr smsg;
+               struct iovec iov;
+               char cred_msg[CMSG_SPACE(sizeof(struct ucred))];
+               struct cmsghdr *cmsg;
+               struct ucred *cred;
+               static char buf[HOTPLUG_BUFFER_SIZE + OBJECT_SIZE];
+
+               memset(buf, 0x00, sizeof(buf));
+               iov.iov_base = &buf;
+               iov.iov_len = sizeof(buf);
+               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);
+
+               if (recvmsg(sock, &smsg, 0) < 0) {
+                       if (errno != EINTR)
+                               condlog(0, "error receiving message");
+                       continue;
+               }
 
-               buflen = recv(sock, &buff, sizeof(buff), 0);
-               if (buflen <  0) {
-                       condlog(0, "error receiving message");
+               cmsg = CMSG_FIRSTHDR(&smsg);
+               if (cmsg == NULL || cmsg->cmsg_type != SCM_CREDENTIALS) {
+                       condlog(3, "no sender credentials received, message ignored");
                        continue;
                }
 
-               if ((size_t)buflen > sizeof(buff)-1)
-                       buflen = sizeof(buff)-1;
+               cred = (struct ucred *)CMSG_DATA(cmsg);
+               if (cred->uid != 0) {
+                       condlog(3, "sender uid=%d, message ignored", cred->uid);
+                       continue;
+               }
+
+               /* skip header */
+               bufpos = strlen(buf) + 1;
+               if (bufpos < sizeof("a@/d") || bufpos >= sizeof(buf)) {
+                       condlog(3, "invalid message length");
+                       continue;
+               }
+
+               /* check message header */
+               if (strstr(buf, "@/") == NULL) {
+                       condlog(3, "unrecognized message header");
+                       continue;
+               }
 
                uev = alloc_uevent();
 
@@ -228,11 +265,14 @@ int uevent_listen(int (*uev_trigger)(struct uevent *, void * trigger_data),
                        continue;
                }
 
+               if ((size_t)buflen > sizeof(buf)-1)
+                       buflen = sizeof(buf)-1;
+
                /*
                 * Copy the shared receive buffer contents to buffer private
                 * to this uevent so we can immediately reuse the shared buffer.
                 */
-               memcpy(uev->buffer, buff, HOTPLUG_BUFFER_SIZE + OBJECT_SIZE);
+               memcpy(uev->buffer, buf, HOTPLUG_BUFFER_SIZE + OBJECT_SIZE);
                buffer = uev->buffer;
                buffer[buflen] = '\0';