diff options
Diffstat (limited to 'security/selinux')
-rw-r--r-- | security/selinux/avc.c | 5 | ||||
-rw-r--r-- | security/selinux/hooks.c | 102 | ||||
-rw-r--r-- | security/selinux/include/classmap.h | 2 | ||||
-rw-r--r-- | security/selinux/ss/policydb.c | 8 |
4 files changed, 89 insertions, 28 deletions
diff --git a/security/selinux/avc.c b/security/selinux/avc.c index a18f1fa6440b..afcc0aed9393 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -517,11 +517,6 @@ out: return rc; } -static inline int avc_sidcmp(u32 x, u32 y) -{ - return (x == y || x == SECSID_WILD || y == SECSID_WILD); -} - /** * avc_update_node Update an AVC entry * @event : Updating event diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 6da7532893a1..29c39e0b03ed 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -401,23 +401,14 @@ static int selinux_is_sblabel_mnt(struct super_block *sb) { struct superblock_security_struct *sbsec = sb->s_security; - if (sbsec->behavior == SECURITY_FS_USE_XATTR || - sbsec->behavior == SECURITY_FS_USE_TRANS || - sbsec->behavior == SECURITY_FS_USE_TASK) - return 1; - - /* Special handling for sysfs. Is genfs but also has setxattr handler*/ - if (strncmp(sb->s_type->name, "sysfs", sizeof("sysfs")) == 0) - return 1; - - /* - * Special handling for rootfs. Is genfs but supports - * setting SELinux context on in-core inodes. - */ - if (strncmp(sb->s_type->name, "rootfs", sizeof("rootfs")) == 0) - return 1; - - return 0; + return sbsec->behavior == SECURITY_FS_USE_XATTR || + sbsec->behavior == SECURITY_FS_USE_TRANS || + sbsec->behavior == SECURITY_FS_USE_TASK || + /* Special handling. Genfs but also in-core setxattr handler */ + !strcmp(sb->s_type->name, "sysfs") || + !strcmp(sb->s_type->name, "pstore") || + !strcmp(sb->s_type->name, "debugfs") || + !strcmp(sb->s_type->name, "rootfs"); } static int sb_finish_set_opts(struct super_block *sb) @@ -456,10 +447,6 @@ static int sb_finish_set_opts(struct super_block *sb) if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors)) printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n", sb->s_id, sb->s_type->name); - else - printk(KERN_DEBUG "SELinux: initialized (dev %s, type %s), %s\n", - sb->s_id, sb->s_type->name, - labeling_behaviors[sbsec->behavior-1]); sbsec->flags |= SE_SBINITIALIZED; if (selinux_is_sblabel_mnt(sb)) @@ -1933,6 +1920,74 @@ static inline u32 open_file_to_av(struct file *file) /* Hook functions begin here. */ +static int selinux_binder_set_context_mgr(struct task_struct *mgr) +{ + u32 mysid = current_sid(); + u32 mgrsid = task_sid(mgr); + + return avc_has_perm(mysid, mgrsid, SECCLASS_BINDER, + BINDER__SET_CONTEXT_MGR, NULL); +} + +static int selinux_binder_transaction(struct task_struct *from, + struct task_struct *to) +{ + u32 mysid = current_sid(); + u32 fromsid = task_sid(from); + u32 tosid = task_sid(to); + int rc; + + if (mysid != fromsid) { + rc = avc_has_perm(mysid, fromsid, SECCLASS_BINDER, + BINDER__IMPERSONATE, NULL); + if (rc) + return rc; + } + + return avc_has_perm(fromsid, tosid, SECCLASS_BINDER, BINDER__CALL, + NULL); +} + +static int selinux_binder_transfer_binder(struct task_struct *from, + struct task_struct *to) +{ + u32 fromsid = task_sid(from); + u32 tosid = task_sid(to); + + return avc_has_perm(fromsid, tosid, SECCLASS_BINDER, BINDER__TRANSFER, + NULL); +} + +static int selinux_binder_transfer_file(struct task_struct *from, + struct task_struct *to, + struct file *file) +{ + u32 sid = task_sid(to); + struct file_security_struct *fsec = file->f_security; + struct inode *inode = file->f_path.dentry->d_inode; + struct inode_security_struct *isec = inode->i_security; + struct common_audit_data ad; + int rc; + + ad.type = LSM_AUDIT_DATA_PATH; + ad.u.path = file->f_path; + + if (sid != fsec->sid) { + rc = avc_has_perm(sid, fsec->sid, + SECCLASS_FD, + FD__USE, + &ad); + if (rc) + return rc; + } + + if (unlikely(IS_PRIVATE(inode))) + return 0; + + return avc_has_perm(sid, isec->sid, isec->sclass, file_to_av(file), + &ad); +} + static int selinux_ptrace_access_check(struct task_struct *child, unsigned int mode) { @@ -5810,6 +5865,11 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer) static struct security_operations selinux_ops = { .name = "selinux", + .binder_set_context_mgr = selinux_binder_set_context_mgr, + .binder_transaction = selinux_binder_transaction, + .binder_transfer_binder = selinux_binder_transfer_binder, + .binder_transfer_file = selinux_binder_transfer_file, + .ptrace_access_check = selinux_ptrace_access_check, .ptrace_traceme = selinux_ptrace_traceme, .capget = selinux_capget, diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h index be491a74c1ed..eccd61b3de8a 100644 --- a/security/selinux/include/classmap.h +++ b/security/selinux/include/classmap.h @@ -151,5 +151,7 @@ struct security_class_mapping secclass_map[] = { { "kernel_service", { "use_as_override", "create_files_as", NULL } }, { "tun_socket", { COMMON_SOCK_PERMS, "attach_queue", NULL } }, + { "binder", { "impersonate", "call", "set_context_mgr", "transfer", + NULL } }, { NULL } }; diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index bc2a586f095c..74aa224267c1 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c @@ -289,12 +289,16 @@ static int policydb_init(struct policydb *p) goto out; p->filename_trans = hashtab_create(filenametr_hash, filenametr_cmp, (1 << 10)); - if (!p->filename_trans) + if (!p->filename_trans) { + rc = -ENOMEM; goto out; + } p->range_tr = hashtab_create(rangetr_hash, rangetr_cmp, 256); - if (!p->range_tr) + if (!p->range_tr) { + rc = -ENOMEM; goto out; + } ebitmap_init(&p->filename_trans_ttypes); ebitmap_init(&p->policycaps); |