Loading cmds/servicemanager/binder.c +40 −12 Original line number Diff line number Diff line Loading @@ -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) Loading Loading @@ -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; Loading @@ -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: { Loading cmds/servicemanager/binder.h +3 −2 Original line number Diff line number Diff line Loading @@ -5,7 +5,8 @@ #define _BINDER_H_ #include <sys/ioctl.h> #include <linux/android/binder.h> #include "binder_kernel.h" struct binder_state; Loading Loading @@ -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); Loading cmds/servicemanager/binder_kernel.h 0 → 100644 +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 cmds/servicemanager/service_manager.c +32 −23 Original line number Diff line number Diff line Loading @@ -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; } Loading @@ -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; Loading @@ -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"; Loading @@ -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 Loading Loading @@ -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); Loading @@ -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; } Loading @@ -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, Loading @@ -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; Loading Loading @@ -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) { Loading @@ -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); Loading Loading @@ -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); Loading @@ -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; Loading @@ -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; Loading Loading
cmds/servicemanager/binder.c +40 −12 Original line number Diff line number Diff line Loading @@ -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) Loading Loading @@ -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; Loading @@ -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: { Loading
cmds/servicemanager/binder.h +3 −2 Original line number Diff line number Diff line Loading @@ -5,7 +5,8 @@ #define _BINDER_H_ #include <sys/ioctl.h> #include <linux/android/binder.h> #include "binder_kernel.h" struct binder_state; Loading Loading @@ -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); Loading
cmds/servicemanager/binder_kernel.h 0 → 100644 +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
cmds/servicemanager/service_manager.c +32 −23 Original line number Diff line number Diff line Loading @@ -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; } Loading @@ -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; Loading @@ -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"; Loading @@ -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 Loading Loading @@ -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); Loading @@ -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; } Loading @@ -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, Loading @@ -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; Loading Loading @@ -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) { Loading @@ -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); Loading Loading @@ -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); Loading @@ -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; Loading @@ -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; Loading