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

Commit 3d79547d authored by Steven Moreland's avatar Steven Moreland
Browse files

Get SID from kernel.

Bug: 121035042
Test: boot
Change-Id: I0941e5a13305859e1b913ec4451173e5408c808e
parent 21a3067d
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;