diff options
author | Nick Kralevich <nnk@google.com> | 2010-07-20 10:48:18 -0700 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2010-07-20 10:48:18 -0700 |
commit | 72f3a00cc7b9a53120a4fb38a3d374d6d692618d (patch) | |
tree | 7517ef4be30d5537199a9c60325fd8a604016df9 /init | |
parent | f0a66c807b4cd7b561decc8d5c82d65537cf421a (diff) | |
parent | 3fc108acf2b05153489730178c85b8db94f603af (diff) | |
download | system_core-72f3a00cc7b9a53120a4fb38a3d374d6d692618d.zip system_core-72f3a00cc7b9a53120a4fb38a3d374d6d692618d.tar.gz system_core-72f3a00cc7b9a53120a4fb38a3d374d6d692618d.tar.bz2 |
am 3fc108ac: am fad7204e: resolved conflicts for merge of 5f5d5c8c to gingerbread
Merge commit '3fc108acf2b05153489730178c85b8db94f603af'
* commit '3fc108acf2b05153489730178c85b8db94f603af':
validate the source of uevent messages
Diffstat (limited to 'init')
-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 155a41e..8e912de 100644 --- a/init/devices.c +++ b/init/devices.c @@ -58,6 +58,7 @@ static int open_uevent_socket(void) { struct sockaddr_nl addr; int sz = 64*1024; // XXX larger? udev uses 16MB! + int on = 1; int s; memset(&addr, 0, sizeof(addr)); @@ -70,6 +71,7 @@ static int open_uevent_socket(void) return -1; setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)); + setsockopt(s, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)); if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { close(s); @@ -562,18 +564,42 @@ static void handle_firmware_event(struct uevent *uevent) #define UEVENT_MSG_LEN 1024 void handle_device_fd() { - char msg[UEVENT_MSG_LEN+2]; - int n; + for(;;) { + char msg[UEVENT_MSG_LEN+2]; + char cred_msg[CMSG_SPACE(sizeof(struct ucred))]; + struct iovec iov = {msg, sizeof(msg)}; + struct sockaddr_nl snl; + struct msghdr hdr = {&snl, sizeof(snl), &iov, 1, cred_msg, sizeof(cred_msg), 0}; + + ssize_t n = recvmsg(device_fd, &hdr, 0); + if (n <= 0) { + break; + } - while((n = recv(device_fd, msg, UEVENT_MSG_LEN, 0)) > 0) { - struct uevent uevent; + if ((snl.nl_groups != 1) || (snl.nl_pid != 0)) { + /* ignoring non-kernel netlink multicast message */ + continue; + } + + struct cmsghdr * cmsg = CMSG_FIRSTHDR(&hdr); + if (cmsg == NULL || cmsg->cmsg_type != SCM_CREDENTIALS) { + /* no sender credentials received, ignore message */ + continue; + } + + struct ucred * cred = (struct ucred *)CMSG_DATA(cmsg); + if (cred->uid != 0) { + /* message from non-root user, ignore */ + continue; + } - if(n == UEVENT_MSG_LEN) /* overflow -- discard */ + if(n >= UEVENT_MSG_LEN) /* overflow -- discard */ continue; msg[n] = '\0'; msg[n+1] = '\0'; + struct uevent uevent; parse_event(msg, &uevent); handle_device_event(&uevent); |