Add MAC for remaining service_manager functionality.
Add SELinux MAC for the list and find functionality
to service_manager. By default the list action uses
the service_manager_type attribute as its target
object.
(cherry picked from commit c67e6307ca
)
Change-Id: Iaf14b21346822a6b544091a0f4a9949117934b9a
This commit is contained in:
parent
2ad9d8a6e7
commit
2a0e40945b
@ -52,46 +52,18 @@ int str16eq(const uint16_t *a, const char *b)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int selinux_enabled;
|
||||||
|
static char *service_manager_context;
|
||||||
static struct selabel_handle* sehandle;
|
static struct selabel_handle* sehandle;
|
||||||
|
|
||||||
static bool check_mac_perms(const char *name, pid_t spid)
|
static bool check_mac_perms(pid_t spid, const char *tctx, const char *perm, const char *name)
|
||||||
{
|
{
|
||||||
if (is_selinux_enabled() <= 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool allowed = false;
|
|
||||||
|
|
||||||
const char *class = "service_manager";
|
|
||||||
const char *perm = "add";
|
|
||||||
|
|
||||||
char *tctx = NULL;
|
|
||||||
char *sctx = NULL;
|
char *sctx = NULL;
|
||||||
|
const char *class = "service_manager";
|
||||||
if (!sehandle) {
|
bool allowed;
|
||||||
ALOGE("SELinux: Failed to find sehandle %s.\n", name);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getpidcon(spid, &sctx) < 0) {
|
if (getpidcon(spid, &sctx) < 0) {
|
||||||
ALOGE("SELinux: getpidcon failed to retrieve pid context.\n");
|
ALOGE("SELinux: getpidcon(pid=%d) failed to retrieve pid context.\n", spid);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!sctx) {
|
|
||||||
ALOGE("SELinux: Failed to find sctx for %s.\n", name);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (selabel_lookup(sehandle, &tctx, name, 1) != 0) {
|
|
||||||
ALOGE("SELinux: selabel_lookup failed to set tctx for %s.\n", name);
|
|
||||||
freecon(sctx);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!tctx) {
|
|
||||||
ALOGE("SELinux: Failed to find tctx for %s.\n", name);
|
|
||||||
freecon(sctx);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,13 +71,58 @@ static bool check_mac_perms(const char *name, pid_t spid)
|
|||||||
allowed = (result == 0);
|
allowed = (result == 0);
|
||||||
|
|
||||||
freecon(sctx);
|
freecon(sctx);
|
||||||
|
return allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool check_mac_perms_from_getcon(pid_t spid, const char *perm)
|
||||||
|
{
|
||||||
|
if (selinux_enabled <= 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return check_mac_perms(spid, service_manager_context, perm, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool check_mac_perms_from_lookup(pid_t spid, const char *perm, const char *name)
|
||||||
|
{
|
||||||
|
bool allowed;
|
||||||
|
char *tctx = NULL;
|
||||||
|
|
||||||
|
if (selinux_enabled <= 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sehandle) {
|
||||||
|
ALOGE("SELinux: Failed to find sehandle. Aborting service_manager.\n");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selabel_lookup(sehandle, &tctx, name, 0) != 0) {
|
||||||
|
ALOGE("SELinux: No match for %s in service_contexts.\n", name);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
allowed = check_mac_perms(spid, tctx, perm, name);
|
||||||
freecon(tctx);
|
freecon(tctx);
|
||||||
return allowed;
|
return allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int svc_can_register(uid_t uid, const uint16_t *name, size_t name_len, pid_t spid)
|
static int svc_can_register(const uint16_t *name, size_t name_len, pid_t spid)
|
||||||
{
|
{
|
||||||
return check_mac_perms(str8(name, name_len), spid) ? 1 : 0;
|
const char *perm = "add";
|
||||||
|
return check_mac_perms_from_lookup(spid, perm, str8(name, name_len)) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int svc_can_list(pid_t spid)
|
||||||
|
{
|
||||||
|
const char *perm = "list";
|
||||||
|
return check_mac_perms_from_getcon(spid, perm) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int svc_can_find(const uint16_t *name, size_t name_len, pid_t spid)
|
||||||
|
{
|
||||||
|
const char *perm = "find";
|
||||||
|
return check_mac_perms_from_lookup(spid, perm, str8(name, name_len)) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct svcinfo
|
struct svcinfo
|
||||||
@ -150,10 +167,15 @@ uint16_t svcmgr_id[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
uint32_t do_find_service(struct binder_state *bs, const uint16_t *s, size_t len, uid_t uid)
|
uint32_t do_find_service(struct binder_state *bs, const uint16_t *s, size_t len, uid_t uid, pid_t spid)
|
||||||
{
|
{
|
||||||
struct svcinfo *si;
|
struct svcinfo *si;
|
||||||
|
|
||||||
|
if (!svc_can_find(s, len, spid)) {
|
||||||
|
ALOGE("find_service('%s') uid=%d - PERMISSION DENIED\n",
|
||||||
|
str8(s, len), uid);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
si = find_svc(s, len);
|
si = find_svc(s, len);
|
||||||
//ALOGI("check_service('%s') handle = %x\n", str8(s, len), si ? si->handle : 0);
|
//ALOGI("check_service('%s') handle = %x\n", str8(s, len), si ? si->handle : 0);
|
||||||
if (si && si->handle) {
|
if (si && si->handle) {
|
||||||
@ -184,7 +206,7 @@ int do_add_service(struct binder_state *bs,
|
|||||||
if (!handle || (len == 0) || (len > 127))
|
if (!handle || (len == 0) || (len > 127))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (!svc_can_register(uid, s, len, spid)) {
|
if (!svc_can_register(s, len, spid)) {
|
||||||
ALOGE("add_service('%s',%x) uid=%d - PERMISSION DENIED\n",
|
ALOGE("add_service('%s',%x) uid=%d - PERMISSION DENIED\n",
|
||||||
str8(s, len), handle, uid);
|
str8(s, len), handle, uid);
|
||||||
return -1;
|
return -1;
|
||||||
@ -273,7 +295,7 @@ int svcmgr_handler(struct binder_state *bs,
|
|||||||
if (s == NULL) {
|
if (s == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
handle = do_find_service(bs, s, len, txn->sender_euid);
|
handle = do_find_service(bs, s, len, txn->sender_euid, txn->sender_pid);
|
||||||
if (!handle)
|
if (!handle)
|
||||||
break;
|
break;
|
||||||
bio_put_ref(reply, handle);
|
bio_put_ref(reply, handle);
|
||||||
@ -294,6 +316,11 @@ int svcmgr_handler(struct binder_state *bs,
|
|||||||
case SVC_MGR_LIST_SERVICES: {
|
case SVC_MGR_LIST_SERVICES: {
|
||||||
uint32_t n = bio_get_uint32(msg);
|
uint32_t n = bio_get_uint32(msg);
|
||||||
|
|
||||||
|
if (!svc_can_list(txn->sender_pid)) {
|
||||||
|
ALOGE("list_service() uid=%d - PERMISSION DENIED\n",
|
||||||
|
txn->sender_euid);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
si = svclist;
|
si = svclist;
|
||||||
while ((n-- > 0) && si)
|
while ((n-- > 0) && si)
|
||||||
si = si->next;
|
si = si->next;
|
||||||
@ -334,8 +361,21 @@ int main(int argc, char **argv)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
selinux_enabled = is_selinux_enabled();
|
||||||
sehandle = selinux_android_service_context_handle();
|
sehandle = selinux_android_service_context_handle();
|
||||||
|
|
||||||
|
if (selinux_enabled > 0) {
|
||||||
|
if (sehandle == NULL) {
|
||||||
|
ALOGE("SELinux: Failed to acquire sehandle. Aborting.\n");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getcon(&service_manager_context) != 0) {
|
||||||
|
ALOGE("SELinux: Failed to acquire service_manager context. Aborting.\n");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
union selinux_callback cb;
|
union selinux_callback cb;
|
||||||
cb.func_audit = audit_callback;
|
cb.func_audit = audit_callback;
|
||||||
selinux_set_callback(SELINUX_CB_AUDIT, cb);
|
selinux_set_callback(SELINUX_CB_AUDIT, cb);
|
||||||
|
Loading…
Reference in New Issue
Block a user