diff options
-rw-r--r-- | init/devices.c | 36 |
1 files changed, 31 insertions, 5 deletions
diff --git a/init/devices.c b/init/devices.c index bde906bc6..530d6d79d 100644 --- a/init/devices.c +++ b/init/devices.c | |||
@@ -53,6 +53,7 @@ static int open_uevent_socket(void) | |||
53 | { | 53 | { |
54 | struct sockaddr_nl addr; | 54 | struct sockaddr_nl addr; |
55 | int sz = 64*1024; // XXX larger? udev uses 16MB! | 55 | int sz = 64*1024; // XXX larger? udev uses 16MB! |
56 | int on = 1; | ||
56 | int s; | 57 | int s; |
57 | 58 | ||
58 | memset(&addr, 0, sizeof(addr)); | 59 | memset(&addr, 0, sizeof(addr)); |
@@ -65,6 +66,7 @@ static int open_uevent_socket(void) | |||
65 | return -1; | 66 | return -1; |
66 | 67 | ||
67 | setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)); | 68 | setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)); |
69 | setsockopt(s, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)); | ||
68 | 70 | ||
69 | if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { | 71 | if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { |
70 | close(s); | 72 | close(s); |
@@ -571,18 +573,42 @@ static void handle_firmware_event(struct uevent *uevent) | |||
571 | #define UEVENT_MSG_LEN 1024 | 573 | #define UEVENT_MSG_LEN 1024 |
572 | void handle_device_fd(int fd) | 574 | void handle_device_fd(int fd) |
573 | { | 575 | { |
574 | char msg[UEVENT_MSG_LEN+2]; | 576 | for(;;) { |
575 | int n; | 577 | char msg[UEVENT_MSG_LEN+2]; |
578 | char cred_msg[CMSG_SPACE(sizeof(struct ucred))]; | ||
579 | struct iovec iov = {msg, sizeof(msg)}; | ||
580 | struct sockaddr_nl snl; | ||
581 | struct msghdr hdr = {&snl, sizeof(snl), &iov, 1, cred_msg, sizeof(cred_msg), 0}; | ||
582 | |||
583 | ssize_t n = recvmsg(fd, &hdr, 0); | ||
584 | if (n <= 0) { | ||
585 | break; | ||
586 | } | ||
576 | 587 | ||
577 | while((n = recv(fd, msg, UEVENT_MSG_LEN, 0)) > 0) { | 588 | if ((snl.nl_groups != 1) || (snl.nl_pid != 0)) { |
578 | struct uevent uevent; | 589 | /* ignoring non-kernel netlink multicast message */ |
590 | continue; | ||
591 | } | ||
592 | |||
593 | struct cmsghdr * cmsg = CMSG_FIRSTHDR(&hdr); | ||
594 | if (cmsg == NULL || cmsg->cmsg_type != SCM_CREDENTIALS) { | ||
595 | /* no sender credentials received, ignore message */ | ||
596 | continue; | ||
597 | } | ||
598 | |||
599 | struct ucred * cred = (struct ucred *)CMSG_DATA(cmsg); | ||
600 | if (cred->uid != 0) { | ||
601 | /* message from non-root user, ignore */ | ||
602 | continue; | ||
603 | } | ||
579 | 604 | ||
580 | if(n == UEVENT_MSG_LEN) /* overflow -- discard */ | 605 | if(n >= UEVENT_MSG_LEN) /* overflow -- discard */ |
581 | continue; | 606 | continue; |
582 | 607 | ||
583 | msg[n] = '\0'; | 608 | msg[n] = '\0'; |
584 | msg[n+1] = '\0'; | 609 | msg[n+1] = '\0'; |
585 | 610 | ||
611 | struct uevent uevent; | ||
586 | parse_event(msg, &uevent); | 612 | parse_event(msg, &uevent); |
587 | 613 | ||
588 | handle_device_event(&uevent); | 614 | handle_device_event(&uevent); |