Validate sender credentials on netlink msg receive
Verify that netlink messages are actually from the kernel,
and not from a userspace program.
This is a manual cherry-pick from b620a0b1c7
Change-Id: I237f0a5cb56393bb3aab64a7ae5898f2bdc95cef
This commit is contained in:
parent
71ead18353
commit
6bc0828010
1 changed files with 26 additions and 3 deletions
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <string.h>
|
||||
|
||||
#define LOG_TAG "NetlinkListener"
|
||||
|
@ -32,11 +33,33 @@ NetlinkListener::NetlinkListener(int socket) :
|
|||
bool NetlinkListener::onDataAvailable(SocketClient *cli)
|
||||
{
|
||||
int socket = cli->getSocket();
|
||||
int count;
|
||||
ssize_t count;
|
||||
char cred_msg[CMSG_SPACE(sizeof(struct ucred))];
|
||||
struct sockaddr_nl snl;
|
||||
struct iovec iov = {mBuffer, sizeof(mBuffer)};
|
||||
struct msghdr hdr = {&snl, sizeof(snl), &iov, 1, cred_msg, sizeof(cred_msg), 0};
|
||||
|
||||
count = TEMP_FAILURE_RETRY(recv(socket, mBuffer, sizeof(mBuffer), 0));
|
||||
count = TEMP_FAILURE_RETRY(recvmsg(socket, &hdr, 0));
|
||||
if (count < 0) {
|
||||
SLOGE("recv failed (%s)", strerror(errno));
|
||||
SLOGE("recvmsg failed (%s)", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((snl.nl_groups != 1) || (snl.nl_pid != 0)) {
|
||||
SLOGE("ignoring non-kernel netlink multicast message");
|
||||
return false;
|
||||
}
|
||||
|
||||
struct cmsghdr * cmsg = CMSG_FIRSTHDR(&hdr);
|
||||
|
||||
if (cmsg == NULL || cmsg->cmsg_type != SCM_CREDENTIALS) {
|
||||
SLOGE("ignoring message with no sender credentials");
|
||||
return false;
|
||||
}
|
||||
|
||||
struct ucred * cred = (struct ucred *)CMSG_DATA(cmsg);
|
||||
if (cred->uid != 0) {
|
||||
SLOGE("ignoring message from non-root UID %d", cred->uid);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue