diff options
Diffstat (limited to 'libcutils/uevent.c')
-rw-r--r-- | libcutils/uevent.c | 31 |
1 files changed, 25 insertions, 6 deletions
diff --git a/libcutils/uevent.c b/libcutils/uevent.c index 4add29c3d..97a81e309 100644 --- a/libcutils/uevent.c +++ b/libcutils/uevent.c @@ -29,7 +29,24 @@ /** * Like recv(), but checks that messages actually originate from the kernel. */ -ssize_t uevent_kernel_multicast_recv(int socket, void *buffer, size_t length) { +ssize_t uevent_kernel_multicast_recv(int socket, void *buffer, size_t length) +{ + uid_t user = -1; + return uevent_kernel_multicast_uid_recv(socket, buffer, length, &user); +} + +/** + * Like the above, but passes a uid_t in by reference. In the event that this + * fails due to a bad uid check, the uid_t will be set to the uid of the + * socket's peer. + * + * If this method rejects a netlink message from outside the kernel, it + * returns -1, sets errno to EIO, and sets "user" to the UID associated with the + * message. If the peer UID cannot be determined, "user" is set to -1." + */ +ssize_t uevent_kernel_multicast_uid_recv(int socket, void *buffer, + size_t length, uid_t *user) +{ struct iovec iov = { buffer, length }; struct sockaddr_nl addr; char control[CMSG_SPACE(sizeof(struct ucred))]; @@ -43,16 +60,12 @@ ssize_t uevent_kernel_multicast_recv(int socket, void *buffer, size_t length) { 0, }; + *user = -1; ssize_t n = recvmsg(socket, &hdr, 0); if (n <= 0) { return n; } - if (addr.nl_groups == 0 || addr.nl_pid != 0) { - /* ignoring non-kernel or unicast netlink message */ - goto out; - } - struct cmsghdr *cmsg = CMSG_FIRSTHDR(&hdr); if (cmsg == NULL || cmsg->cmsg_type != SCM_CREDENTIALS) { /* ignoring netlink message with no sender credentials */ @@ -60,11 +73,17 @@ ssize_t uevent_kernel_multicast_recv(int socket, void *buffer, size_t length) { } struct ucred *cred = (struct ucred *)CMSG_DATA(cmsg); + *user = cred->uid; if (cred->uid != 0) { /* ignoring netlink message from non-root user */ goto out; } + if (addr.nl_groups == 0 || addr.nl_pid != 0) { + /* ignoring non-kernel or unicast netlink message */ + goto out; + } + return n; out: |