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

Commit aab8d1f8 authored by Steven Moreland's avatar Steven Moreland Committed by Android (Google) Code Review
Browse files

Merge "Get SID from kernel."

parents 517e5c4d 3d79547d
Loading
Loading
Loading
Loading
+40 −12
Original line number Diff line number Diff line
@@ -146,7 +146,21 @@ void binder_close(struct binder_state *bs)

int binder_become_context_manager(struct binder_state *bs)
{
    return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
    struct flat_binder_object obj;
    memset(&obj, 0, sizeof(obj));
    obj.flags = FLAT_BINDER_FLAG_TXN_SECURITY_CTX;

    int result = ioctl(bs->fd, BINDER_SET_CONTEXT_MGR_EXT, &obj);

    // fallback to original method
    if (result != 0) {
#ifndef VENDORSERVICEMANAGER
        android_errorWriteLog(0x534e4554, "121035042");
#endif

        result = ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
    }
    return result;
}

int binder_write(struct binder_state *bs, void *data, size_t len)
@@ -240,13 +254,28 @@ int binder_parse(struct binder_state *bs, struct binder_io *bio,
#endif
            ptr += sizeof(struct binder_ptr_cookie);
            break;
        case BR_TRANSACTION_SEC_CTX:
        case BR_TRANSACTION: {
            struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr;
            if ((end - ptr) < sizeof(*txn)) {
                ALOGE("parse: txn too small!\n");
            struct binder_transaction_data_secctx txn;
            if (cmd == BR_TRANSACTION_SEC_CTX) {
                if ((end - ptr) < sizeof(struct binder_transaction_data_secctx)) {
                    ALOGE("parse: txn too small (binder_transaction_data_secctx)!\n");
                    return -1;
                }
            binder_dump_txn(txn);
                memcpy(&txn, (void*) ptr, sizeof(struct binder_transaction_data_secctx));
                ptr += sizeof(struct binder_transaction_data_secctx);
            } else /* BR_TRANSACTION */ {
                if ((end - ptr) < sizeof(struct binder_transaction_data)) {
                    ALOGE("parse: txn too small (binder_transaction_data)!\n");
                    return -1;
                }
                memcpy(&txn.transaction_data, (void*) ptr, sizeof(struct binder_transaction_data));
                ptr += sizeof(struct binder_transaction_data);

                txn.secctx = 0;
            }

            binder_dump_txn(&txn.transaction_data);
            if (func) {
                unsigned rdata[256/4];
                struct binder_io msg;
@@ -254,15 +283,14 @@ int binder_parse(struct binder_state *bs, struct binder_io *bio,
                int res;

                bio_init(&reply, rdata, sizeof(rdata), 4);
                bio_init_from_txn(&msg, txn);
                res = func(bs, txn, &msg, &reply);
                if (txn->flags & TF_ONE_WAY) {
                    binder_free_buffer(bs, txn->data.ptr.buffer);
                bio_init_from_txn(&msg, &txn.transaction_data);
                res = func(bs, &txn, &msg, &reply);
                if (txn.transaction_data.flags & TF_ONE_WAY) {
                    binder_free_buffer(bs, txn.transaction_data.data.ptr.buffer);
                } else {
                    binder_send_reply(bs, &reply, txn->data.ptr.buffer, res);
                    binder_send_reply(bs, &reply, txn.transaction_data.data.ptr.buffer, res);
                }
            }
            ptr += sizeof(*txn);
            break;
        }
        case BR_REPLY: {
+3 −2
Original line number Diff line number Diff line
@@ -5,7 +5,8 @@
#define _BINDER_H_

#include <sys/ioctl.h>
#include <linux/android/binder.h>

#include "binder_kernel.h"

struct binder_state;

@@ -42,7 +43,7 @@ enum {
};

typedef int (*binder_handler)(struct binder_state *bs,
                              struct binder_transaction_data *txn,
                              struct binder_transaction_data_secctx *txn,
                              struct binder_io *msg,
                              struct binder_io *reply);

+46 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 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 ANDROID_BINDER_KERNEL_H
#define ANDROID_BINDER_KERNEL_H

#include <linux/android/binder.h>

/**
 * This file exists because the uapi kernel headers in bionic are built
 * from upstream kernel headers only, and not all of the hwbinder kernel changes
 * have made it upstream yet. Therefore, the modifications to the
 * binder header are added locally in this file.
 */

enum {
        FLAT_BINDER_FLAG_TXN_SECURITY_CTX = 0x1000,
};

#define BINDER_SET_CONTEXT_MGR_EXT      _IOW('b', 13, struct flat_binder_object)

struct binder_transaction_data_secctx {
        struct binder_transaction_data transaction_data;
        binder_uintptr_t secctx;
};

enum {
        BR_TRANSACTION_SEC_CTX = _IOR('r', 2,
                              struct binder_transaction_data_secctx),
};


#endif // ANDROID_BINDER_KERNEL_H
+32 −23
Original line number Diff line number Diff line
@@ -61,14 +61,14 @@ int str16eq(const uint16_t *a, const char *b)
static char *service_manager_context;
static struct selabel_handle* sehandle;

static bool check_mac_perms(pid_t spid, uid_t uid, const char *tctx, const char *perm, const char *name)
static bool check_mac_perms(pid_t spid, const char* sid, uid_t uid, const char *tctx, const char *perm, const char *name)
{
    char *sctx = NULL;
    char *lookup_sid = NULL;
    const char *class = "service_manager";
    bool allowed;
    struct audit_data ad;

    if (getpidcon(spid, &sctx) < 0) {
    if (sid == NULL && getpidcon(spid, &lookup_sid) < 0) {
        ALOGE("SELinux: getpidcon(pid=%d) failed to retrieve pid context.\n", spid);
        return false;
    }
@@ -77,19 +77,25 @@ static bool check_mac_perms(pid_t spid, uid_t uid, const char *tctx, const char
    ad.uid = uid;
    ad.name = name;

    int result = selinux_check_access(sctx, tctx, class, perm, (void *) &ad);
#ifndef VENDORSERVICEMANAGER
    if (sid == NULL) {
        android_errorWriteLog(0x534e4554, "121035042");
    }
#endif

    int result = selinux_check_access(sid ? sid : lookup_sid, tctx, class, perm, (void *) &ad);
    allowed = (result == 0);

    freecon(sctx);
    freecon(lookup_sid);
    return allowed;
}

static bool check_mac_perms_from_getcon(pid_t spid, uid_t uid, const char *perm)
static bool check_mac_perms_from_getcon(pid_t spid, const char* sid, uid_t uid, const char *perm)
{
    return check_mac_perms(spid, uid, service_manager_context, perm, NULL);
    return check_mac_perms(spid, sid, uid, service_manager_context, perm, NULL);
}

static bool check_mac_perms_from_lookup(pid_t spid, uid_t uid, const char *perm, const char *name)
static bool check_mac_perms_from_lookup(pid_t spid, const char* sid, uid_t uid, const char *perm, const char *name)
{
    bool allowed;
    char *tctx = NULL;
@@ -104,12 +110,12 @@ static bool check_mac_perms_from_lookup(pid_t spid, uid_t uid, const char *perm,
        return false;
    }

    allowed = check_mac_perms(spid, uid, tctx, perm, name);
    allowed = check_mac_perms(spid, sid, uid, tctx, perm, name);
    freecon(tctx);
    return allowed;
}

static int svc_can_register(const uint16_t *name, size_t name_len, pid_t spid, uid_t uid)
static int svc_can_register(const uint16_t *name, size_t name_len, pid_t spid, const char* sid, uid_t uid)
{
    const char *perm = "add";

@@ -117,19 +123,19 @@ static int svc_can_register(const uint16_t *name, size_t name_len, pid_t spid, u
        return 0; /* Don't allow apps to register services */
    }

    return check_mac_perms_from_lookup(spid, uid, perm, str8(name, name_len)) ? 1 : 0;
    return check_mac_perms_from_lookup(spid, sid, uid, perm, str8(name, name_len)) ? 1 : 0;
}

static int svc_can_list(pid_t spid, uid_t uid)
static int svc_can_list(pid_t spid, const char* sid, uid_t uid)
{
    const char *perm = "list";
    return check_mac_perms_from_getcon(spid, uid, perm) ? 1 : 0;
    return check_mac_perms_from_getcon(spid, sid, uid, perm) ? 1 : 0;
}

static int svc_can_find(const uint16_t *name, size_t name_len, pid_t spid, uid_t uid)
static int svc_can_find(const uint16_t *name, size_t name_len, pid_t spid, const char* sid, uid_t uid)
{
    const char *perm = "find";
    return check_mac_perms_from_lookup(spid, uid, perm, str8(name, name_len)) ? 1 : 0;
    return check_mac_perms_from_lookup(spid, sid, uid, perm, str8(name, name_len)) ? 1 : 0;
}

struct svcinfo
@@ -175,7 +181,7 @@ uint16_t svcmgr_id[] = {
};


uint32_t do_find_service(const uint16_t *s, size_t len, uid_t uid, pid_t spid)
uint32_t do_find_service(const uint16_t *s, size_t len, uid_t uid, pid_t spid, const char* sid)
{
    struct svcinfo *si = find_svc(s, len);

@@ -192,7 +198,7 @@ uint32_t do_find_service(const uint16_t *s, size_t len, uid_t uid, pid_t spid)
        }
    }

    if (!svc_can_find(s, len, spid, uid)) {
    if (!svc_can_find(s, len, spid, sid, uid)) {
        return 0;
    }

@@ -200,7 +206,7 @@ uint32_t do_find_service(const uint16_t *s, size_t len, uid_t uid, pid_t spid)
}

int do_add_service(struct binder_state *bs, const uint16_t *s, size_t len, uint32_t handle,
                   uid_t uid, int allow_isolated, uint32_t dumpsys_priority, pid_t spid) {
                   uid_t uid, int allow_isolated, uint32_t dumpsys_priority, pid_t spid, const char* sid) {
    struct svcinfo *si;

    //ALOGI("add_service('%s',%x,%s) uid=%d\n", str8(s, len), handle,
@@ -209,7 +215,7 @@ int do_add_service(struct binder_state *bs, const uint16_t *s, size_t len, uint3
    if (!handle || (len == 0) || (len > 127))
        return -1;

    if (!svc_can_register(s, len, spid, uid)) {
    if (!svc_can_register(s, len, spid, sid, uid)) {
        ALOGE("add_service('%s',%x) uid=%d - PERMISSION DENIED\n",
             str8(s, len), handle, uid);
        return -1;
@@ -248,7 +254,7 @@ int do_add_service(struct binder_state *bs, const uint16_t *s, size_t len, uint3
}

int svcmgr_handler(struct binder_state *bs,
                   struct binder_transaction_data *txn,
                   struct binder_transaction_data_secctx *txn_secctx,
                   struct binder_io *msg,
                   struct binder_io *reply)
{
@@ -260,6 +266,8 @@ int svcmgr_handler(struct binder_state *bs,
    int allow_isolated;
    uint32_t dumpsys_priority;

    struct binder_transaction_data *txn = &txn_secctx->transaction_data;

    //ALOGI("target=%p code=%d pid=%d uid=%d\n",
    //      (void*) txn->target.ptr, txn->code, txn->sender_pid, txn->sender_euid);

@@ -305,7 +313,8 @@ int svcmgr_handler(struct binder_state *bs,
        if (s == NULL) {
            return -1;
        }
        handle = do_find_service(s, len, txn->sender_euid, txn->sender_pid);
        handle = do_find_service(s, len, txn->sender_euid, txn->sender_pid,
                                 (const char*) txn_secctx->secctx);
        if (!handle)
            break;
        bio_put_ref(reply, handle);
@@ -320,7 +329,7 @@ int svcmgr_handler(struct binder_state *bs,
        allow_isolated = bio_get_uint32(msg) ? 1 : 0;
        dumpsys_priority = bio_get_uint32(msg);
        if (do_add_service(bs, s, len, handle, txn->sender_euid, allow_isolated, dumpsys_priority,
                           txn->sender_pid))
                           txn->sender_pid, (const char*) txn_secctx->secctx))
            return -1;
        break;

@@ -328,7 +337,7 @@ int svcmgr_handler(struct binder_state *bs,
        uint32_t n = bio_get_uint32(msg);
        uint32_t req_dumpsys_priority = bio_get_uint32(msg);

        if (!svc_can_list(txn->sender_pid, txn->sender_euid)) {
        if (!svc_can_list(txn->sender_pid, (const char*) txn_secctx->secctx, txn->sender_euid)) {
            ALOGE("list_service() uid=%d - PERMISSION DENIED\n",
                    txn->sender_euid);
            return -1;