summaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/capability.c27
-rw-r--r--security/commoncap.c6
-rw-r--r--security/integrity/Kconfig4
-rw-r--r--security/integrity/evm/Kconfig2
-rw-r--r--security/keys/request_key.c1
-rw-r--r--security/security.c36
-rw-r--r--security/selinux/hooks.c73
-rw-r--r--security/selinux/include/classmap.h2
-rw-r--r--security/selinux/selinuxfs.c52
-rw-r--r--security/smack/smack_lsm.c16
10 files changed, 155 insertions, 64 deletions
diff --git a/security/capability.c b/security/capability.c
index d68c57a62bc..070dd46f62f 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -12,6 +12,29 @@
#include <linux/security.h>
+static int cap_binder_set_context_mgr(struct task_struct *mgr)
+{
+ return 0;
+}
+
+static int cap_binder_transaction(struct task_struct *from,
+ struct task_struct *to)
+{
+ return 0;
+}
+
+static int cap_binder_transfer_binder(struct task_struct *from,
+ struct task_struct *to)
+{
+ return 0;
+}
+
+static int cap_binder_transfer_file(struct task_struct *from,
+ struct task_struct *to, struct file *file)
+{
+ return 0;
+}
+
static int cap_syslog(int type)
{
return 0;
@@ -930,6 +953,10 @@ static void cap_audit_rule_free(void *lsmrule)
void __init security_fixup_ops(struct security_operations *ops)
{
+ set_to_cap_if_null(ops, binder_set_context_mgr);
+ set_to_cap_if_null(ops, binder_transaction);
+ set_to_cap_if_null(ops, binder_transfer_binder);
+ set_to_cap_if_null(ops, binder_transfer_file);
set_to_cap_if_null(ops, ptrace_access_check);
set_to_cap_if_null(ops, ptrace_traceme);
set_to_cap_if_null(ops, capget);
diff --git a/security/commoncap.c b/security/commoncap.c
index 2915d850305..f66713bd745 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -434,7 +434,6 @@ int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data
*/
static int get_file_caps(struct linux_binprm *bprm, bool *effective, bool *has_cap)
{
- struct dentry *dentry;
int rc = 0;
struct cpu_vfs_cap_data vcaps;
@@ -446,9 +445,7 @@ static int get_file_caps(struct linux_binprm *bprm, bool *effective, bool *has_c
if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)
return 0;
- dentry = dget(bprm->file->f_path.dentry);
-
- rc = get_vfs_caps_from_disk(dentry, &vcaps);
+ rc = get_vfs_caps_from_disk(bprm->file->f_path.dentry, &vcaps);
if (rc < 0) {
if (rc == -EINVAL)
printk(KERN_NOTICE "%s: get_vfs_caps_from_disk returned %d for %s\n",
@@ -464,7 +461,6 @@ static int get_file_caps(struct linux_binprm *bprm, bool *effective, bool *has_c
__func__, rc, bprm->filename);
out:
- dput(dentry);
if (rc)
bprm_clear_caps(bprm);
diff --git a/security/integrity/Kconfig b/security/integrity/Kconfig
index b76235ae478..73c457bf5a4 100644
--- a/security/integrity/Kconfig
+++ b/security/integrity/Kconfig
@@ -16,7 +16,7 @@ config INTEGRITY
if INTEGRITY
config INTEGRITY_SIGNATURE
- boolean "Digital signature verification using multiple keyrings"
+ bool "Digital signature verification using multiple keyrings"
depends on KEYS
default n
select SIGNATURE
@@ -30,7 +30,7 @@ config INTEGRITY_SIGNATURE
usually only added from initramfs.
config INTEGRITY_ASYMMETRIC_KEYS
- boolean "Enable asymmetric keys support"
+ bool "Enable asymmetric keys support"
depends on INTEGRITY_SIGNATURE
default n
select ASYMMETRIC_KEY_TYPE
diff --git a/security/integrity/evm/Kconfig b/security/integrity/evm/Kconfig
index df586fa00ef..bf19723cf11 100644
--- a/security/integrity/evm/Kconfig
+++ b/security/integrity/evm/Kconfig
@@ -1,5 +1,5 @@
config EVM
- boolean "EVM support"
+ bool "EVM support"
select KEYS
select ENCRYPTED_KEYS
select CRYPTO_HMAC
diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index 0c7aea4dea5..486ef6fa393 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -414,6 +414,7 @@ link_check_failed:
link_prealloc_failed:
mutex_unlock(&user->cons_lock);
+ key_put(key);
kleave(" = %d [prelink]", ret);
return ret;
diff --git a/security/security.c b/security/security.c
index 18b35c63fc0..e81d5bbe736 100644
--- a/security/security.c
+++ b/security/security.c
@@ -135,6 +135,29 @@ int __init register_security(struct security_operations *ops)
/* Security operations */
+int security_binder_set_context_mgr(struct task_struct *mgr)
+{
+ return security_ops->binder_set_context_mgr(mgr);
+}
+
+int security_binder_transaction(struct task_struct *from,
+ struct task_struct *to)
+{
+ return security_ops->binder_transaction(from, to);
+}
+
+int security_binder_transfer_binder(struct task_struct *from,
+ struct task_struct *to)
+{
+ return security_ops->binder_transfer_binder(from, to);
+}
+
+int security_binder_transfer_file(struct task_struct *from,
+ struct task_struct *to, struct file *file)
+{
+ return security_ops->binder_transfer_file(from, to, file);
+}
+
int security_ptrace_access_check(struct task_struct *child, unsigned int mode)
{
#ifdef CONFIG_SECURITY_YAMA_STACKED
@@ -726,16 +749,15 @@ static inline unsigned long mmap_prot(struct file *file, unsigned long prot)
return prot | PROT_EXEC;
/*
* ditto if it's not on noexec mount, except that on !MMU we need
- * BDI_CAP_EXEC_MMAP (== VM_MAYEXEC) in this case
+ * NOMMU_MAP_EXEC (== VM_MAYEXEC) in this case
*/
if (!(file->f_path.mnt->mnt_flags & MNT_NOEXEC)) {
#ifndef CONFIG_MMU
- unsigned long caps = 0;
- struct address_space *mapping = file->f_mapping;
- if (mapping && mapping->backing_dev_info)
- caps = mapping->backing_dev_info->capabilities;
- if (!(caps & BDI_CAP_EXEC_MAP))
- return prot;
+ if (file->f_op->mmap_capabilities) {
+ unsigned caps = file->f_op->mmap_capabilities(file);
+ if (!(caps & NOMMU_MAP_EXEC))
+ return prot;
+ }
#endif
return prot | PROT_EXEC;
}
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 87a915656ea..29c39e0b03e 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -1920,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)
{
@@ -5797,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 be491a74c1e..eccd61b3de8 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/selinuxfs.c b/security/selinux/selinuxfs.c
index 33db1ad4fd1..1684bcc78b3 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -1195,30 +1195,8 @@ static const struct file_operations sel_commit_bools_ops = {
static void sel_remove_entries(struct dentry *de)
{
- struct list_head *node;
-
- spin_lock(&de->d_lock);
- node = de->d_subdirs.next;
- while (node != &de->d_subdirs) {
- struct dentry *d = list_entry(node, struct dentry, d_child);
-
- spin_lock_nested(&d->d_lock, DENTRY_D_LOCK_NESTED);
- list_del_init(node);
-
- if (d->d_inode) {
- dget_dlock(d);
- spin_unlock(&de->d_lock);
- spin_unlock(&d->d_lock);
- d_delete(d);
- simple_unlink(de->d_inode, d);
- dput(d);
- spin_lock(&de->d_lock);
- } else
- spin_unlock(&d->d_lock);
- node = de->d_subdirs.next;
- }
-
- spin_unlock(&de->d_lock);
+ d_genocide(de);
+ shrink_dcache_parent(de);
}
#define BOOL_DIR_NAME "booleans"
@@ -1668,37 +1646,13 @@ static int sel_make_class_dir_entries(char *classname, int index,
return rc;
}
-static void sel_remove_classes(void)
-{
- struct list_head *class_node;
-
- list_for_each(class_node, &class_dir->d_subdirs) {
- struct dentry *class_subdir = list_entry(class_node,
- struct dentry, d_child);
- struct list_head *class_subdir_node;
-
- list_for_each(class_subdir_node, &class_subdir->d_subdirs) {
- struct dentry *d = list_entry(class_subdir_node,
- struct dentry, d_child);
-
- if (d->d_inode)
- if (d->d_inode->i_mode & S_IFDIR)
- sel_remove_entries(d);
- }
-
- sel_remove_entries(class_subdir);
- }
-
- sel_remove_entries(class_dir);
-}
-
static int sel_make_classes(void)
{
int rc, nclasses, i;
char **classes;
/* delete any existing entries */
- sel_remove_classes();
+ sel_remove_entries(class_dir);
rc = security_get_classes(&classes, &nclasses);
if (rc)
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index a0ccce4e46f..ed94f6f836e 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -3818,6 +3818,18 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
}
#endif /* CONFIG_IPV6 */
+#ifdef CONFIG_SECURITY_SMACK_NETFILTER
+ /*
+ * If there is a secmark use it rather than the CIPSO label.
+ * If there is no secmark fall back to CIPSO.
+ * The secmark is assumed to reflect policy better.
+ */
+ if (skb && skb->secmark != 0) {
+ skp = smack_from_secid(skb->secmark);
+ goto access_check;
+ }
+#endif /* CONFIG_SECURITY_SMACK_NETFILTER */
+
netlbl_secattr_init(&secattr);
rc = netlbl_skbuff_getattr(skb, family, &secattr);
if (rc == 0)
@@ -3826,6 +3838,10 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
skp = &smack_known_huh;
netlbl_secattr_destroy(&secattr);
+#ifdef CONFIG_SECURITY_SMACK_NETFILTER
+access_check:
+#endif
+
#ifdef CONFIG_AUDIT
smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
ad.a.u.net->family = family;