summaryrefslogtreecommitdiffstats
path: root/init
diff options
context:
space:
mode:
authorNick Kralevich <nnk@google.com>2010-07-20 10:45:06 -0700
committerAndroid Git Automerger <android-git-automerger@android.com>2010-07-20 10:45:06 -0700
commit3fc108acf2b05153489730178c85b8db94f603af (patch)
tree101e8882d8709b9894a5c33ac710a466904d664f /init
parent3c5581da1d58d0b7e3bac0f03d7ec1e63d71b86d (diff)
parentfad7204e9eac20a87afacd7547ed8202a39319f8 (diff)
downloadsystem_core-3fc108acf2b05153489730178c85b8db94f603af.zip
system_core-3fc108acf2b05153489730178c85b8db94f603af.tar.gz
system_core-3fc108acf2b05153489730178c85b8db94f603af.tar.bz2
am fad7204e: resolved conflicts for merge of 5f5d5c8c to gingerbread
Merge commit 'fad7204e9eac20a87afacd7547ed8202a39319f8' into gingerbread-plus-aosp * commit 'fad7204e9eac20a87afacd7547ed8202a39319f8': validate the source of uevent messages
Diffstat (limited to 'init')
-rw-r--r--init/devices.c36
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);