Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit de9e65dd authored by Nick Kralevich's avatar Nick Kralevich
Browse files

Revert "Fold uevent message origin checking from init into libcutils."

This reverts commit 8405ec0e.

The original change does not compile.
parent 282c2ab4
Loading
Loading
Loading
Loading

include/cutils/uevent.h

deleted100644 → 0
+0 −32
Original line number Diff line number Diff line
/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef __CUTILS_UEVENT_H
#define __CUTILS_UEVENT_H

#include <sys/socket.h>

#ifdef __cplusplus
extern "C" {
#endif

ssize_t uevent_checked_recv(int socket, void *buffer, size_t length);

#ifdef __cplusplus
}
#endif

#endif /* __CUTILS_UEVENT_H */
+29 −5
Original line number Diff line number Diff line
@@ -33,8 +33,6 @@
#include <asm/page.h>
#include <sys/wait.h>

#include <cutils/uevent.h>

#include "devices.h"
#include "util.h"
#include "log.h"
@@ -591,9 +589,35 @@ static void handle_firmware_event(struct uevent *uevent)
#define UEVENT_MSG_LEN  1024
void handle_device_fd()
{
    for(;;) {
        char msg[UEVENT_MSG_LEN+2];
    int n;
    while ((n = uevent_checked_recv(device_fd, msg, UEVENT_MSG_LEN)) > 0) {
        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;
        }

        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 */
            continue;

+0 −1
Original line number Diff line number Diff line
@@ -74,7 +74,6 @@ else
        mspace.c \
        selector.c \
        tztime.c \
        uevent.c \
        zygote.c

    commonHostSources += \

libcutils/uevent.c

deleted100644 → 0
+0 −70
Original line number Diff line number Diff line
/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <cutils/uevent.h>

#include <errno.h>
#include <strings.h>

#include <linux/netlink.h>

/**
 * Like recv(), but checks that messages actually originate from the kernel.
 */
ssize_t uevent_checked_recv(int socket, void *buffer, size_t length) {
    struct iovec iov = { buffer, length };
    struct sockaddr_nl addr;
    char control[CMSG_SPACE(sizeof(struct ucred))];
    struct msghdr hdr = {
        &addr,
        sizeof(addr),
        &iov,
        1,
        control,
        sizeof(control),
        0,
    };

    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 */
        goto out;
    }

    struct ucred *cred = (struct ucred *)CMSG_DATA(cmsg);
    if (cred->uid != 0) {
        /* ignoring netlink message from non-root user */
        goto out;
    }

    return n;

out:
    /* clear residual potentially malicious data */
    bzero(buffer, length);
    errno = EIO;
    return -1;
}