cutils: return the remote uid on netlink recv failure
This change adds a layer of indirection to uevent's uevent_kernel_multicast_recv, allowing dependent code to get the remote endpoint if desired. Change-Id: If2f00708a1dd6196c415b1ebc2a7eeb72399a90e
This commit is contained in:
parent
15892e10a4
commit
15621e0970
2 changed files with 26 additions and 6 deletions
|
@ -26,6 +26,7 @@ extern "C" {
|
|||
|
||||
int uevent_open_socket(int buf_sz, bool passcred);
|
||||
ssize_t uevent_kernel_multicast_recv(int socket, void *buffer, size_t length);
|
||||
ssize_t uevent_kernel_multicast_uid_recv(int socket, void *buffer, size_t length, uid_t *uid);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in a new issue