From 94d4ef0c2b3e6c799f78d223e233254a870c4559 Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 5 Oct 2011 12:19:19 +0100 Subject: SELinux: Fix RCU deref check warning in sel_netport_insert() Fix the following bug in sel_netport_insert() where rcu_dereference() should be rcu_dereference_protected() as sel_netport_lock is held. =================================================== [ INFO: suspicious rcu_dereference_check() usage. ] --------------------------------------------------- security/selinux/netport.c:127 invoked rcu_dereference_check() without protection! other info that might help us debug this: rcu_scheduler_active = 1, debug_locks = 0 1 lock held by ossec-rootcheck/3323: #0: (sel_netport_lock){+.....}, at: [] sel_netport_sid+0xbb/0x226 stack backtrace: Pid: 3323, comm: ossec-rootcheck Not tainted 3.1.0-rc8-fsdevel+ #1095 Call Trace: [] lockdep_rcu_dereference+0xa7/0xb0 [] sel_netport_sid+0x1b7/0x226 [] ? sel_netport_avc_callback+0xbc/0xbc [] selinux_socket_bind+0x115/0x230 [] ? might_fault+0x4e/0x9e [] ? might_fault+0x97/0x9e [] security_socket_bind+0x11/0x13 [] sys_bind+0x56/0x95 [] ? sysret_check+0x27/0x62 [] ? trace_hardirqs_on_caller+0x11e/0x155 [] ? audit_syscall_entry+0x17b/0x1ae [] ? trace_hardirqs_on_thunk+0x3a/0x3f [] system_call_fastpath+0x16/0x1b Signed-off-by: David Howells Acked-by: Eric Dumazet Acked-by: Paul Moore Signed-off-by: Eric Paris --- security/selinux/netport.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'security') diff --git a/security/selinux/netport.c b/security/selinux/netport.c index 0b62bd112461..7b9eb1faf68b 100644 --- a/security/selinux/netport.c +++ b/security/selinux/netport.c @@ -123,7 +123,9 @@ static void sel_netport_insert(struct sel_netport *port) if (sel_netport_hash[idx].size == SEL_NETPORT_HASH_BKT_LIMIT) { struct sel_netport *tail; tail = list_entry( - rcu_dereference(sel_netport_hash[idx].list.prev), + rcu_dereference_protected( + sel_netport_hash[idx].list.prev, + lockdep_is_held(&sel_netport_lock)), struct sel_netport, list); list_del_rcu(&tail->list); kfree_rcu(tail, rcu); -- cgit v1.2.1 From b46610caba4bd9263afd07c7ef7a79974550554a Mon Sep 17 00:00:00 2001 From: James Morris Date: Tue, 30 Aug 2011 14:11:24 +1000 Subject: selinux: sparse fix: make selinux_secmark_refcount static Sparse fix: make selinux_secmark_refcount static. Signed-off-by: James Morris Signed-off-by: Eric Paris --- security/selinux/hooks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'security') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 266a2292451d..e07cf7fcdce2 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -96,7 +96,7 @@ extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm); extern struct security_operations *security_ops; /* SECMARK reference count */ -atomic_t selinux_secmark_refcount = ATOMIC_INIT(0); +static atomic_t selinux_secmark_refcount = ATOMIC_INIT(0); #ifdef CONFIG_SECURITY_SELINUX_DEVELOP int selinux_enforcing; -- cgit v1.2.1 From 5c884c1d4ac955987e84acf2d36c0f160536aca4 Mon Sep 17 00:00:00 2001 From: James Morris Date: Tue, 30 Aug 2011 14:16:24 +1000 Subject: selinux: sparse fix: move selinux_complete_init Sparse fix: move selinux_complete_init Signed-off-by: James Morris Signed-off-by: Eric Paris --- security/selinux/include/security.h | 1 + security/selinux/ss/services.c | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) (limited to 'security') diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 3ba4feba048a..8556e1a263c2 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -216,6 +216,7 @@ struct selinux_kernel_status { extern void selinux_status_update_setenforce(int enforcing); extern void selinux_status_update_policyload(int seqno); +extern void selinux_complete_init(void); #endif /* _SELINUX_SECURITY_H_ */ diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index f6917bc0aa05..37c50c602f17 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -1790,7 +1790,6 @@ static void security_load_policycaps(void) POLICYDB_CAPABILITY_OPENPERM); } -extern void selinux_complete_init(void); static int security_preserve_bools(struct policydb *p); /** -- cgit v1.2.1 From 6063c0461b947c26a77674f33a3409eb99e15d2f Mon Sep 17 00:00:00 2001 From: James Morris Date: Tue, 30 Aug 2011 14:12:13 +1000 Subject: selinux: sparse fix: declare selinux_disable() in security.h Sparse fix: declare selinux_disable() in security.h Signed-off-by: James Morris Signed-off-by: Eric Paris --- security/selinux/include/security.h | 1 + security/selinux/selinuxfs.c | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) (limited to 'security') diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 8556e1a263c2..30002c43436f 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -217,6 +217,7 @@ struct selinux_kernel_status { extern void selinux_status_update_setenforce(int enforcing); extern void selinux_status_update_policyload(int seqno); extern void selinux_complete_init(void); +extern int selinux_disable(void); #endif /* _SELINUX_SECURITY_H_ */ diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index 55d92cbb177a..d3677c6c12c6 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -278,7 +278,6 @@ static ssize_t sel_write_disable(struct file *file, const char __user *buf, char *page = NULL; ssize_t length; int new_value; - extern int selinux_disable(void); length = -ENOMEM; if (count >= PAGE_SIZE) -- cgit v1.2.1 From e8a65a3f67f8a85802c0a0250e48c4c4652d0da0 Mon Sep 17 00:00:00 2001 From: James Morris Date: Tue, 30 Aug 2011 14:17:34 +1000 Subject: selinux: sparse fix: eliminate warnings for selinuxfs Fixes several sparse warnings for selinuxfs.c Signed-off-by: James Morris Signed-off-by: Eric Paris --- security/selinux/hooks.c | 5 ----- security/selinux/include/security.h | 3 +++ security/selinux/selinuxfs.c | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) (limited to 'security') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index e07cf7fcdce2..4a176b468719 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2097,9 +2097,6 @@ static int selinux_bprm_secureexec(struct linux_binprm *bprm) return (atsecure || cap_bprm_secureexec(bprm)); } -extern struct vfsmount *selinuxfs_mount; -extern struct dentry *selinux_null; - /* Derived from fs/exec.c:flush_old_files. */ static inline void flush_unauthorized_files(const struct cred *cred, struct files_struct *files) @@ -5803,8 +5800,6 @@ static int selinux_disabled; int selinux_disable(void) { - extern void exit_sel_fs(void); - if (ss_initialized) { /* Not permitted after initial policy load. */ return -EINVAL; diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 30002c43436f..13b626352f0b 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -218,6 +218,9 @@ extern void selinux_status_update_setenforce(int enforcing); extern void selinux_status_update_policyload(int seqno); extern void selinux_complete_init(void); extern int selinux_disable(void); +extern void exit_sel_fs(void); +extern struct dentry *selinux_null; +extern struct vfsmount *selinuxfs_mount; #endif /* _SELINUX_SECURITY_H_ */ diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index d3677c6c12c6..ba2ada5f16a9 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -477,7 +477,7 @@ static struct vm_operations_struct sel_mmap_policy_ops = { .page_mkwrite = sel_mmap_policy_fault, }; -int sel_mmap_policy(struct file *filp, struct vm_area_struct *vma) +static int sel_mmap_policy(struct file *filp, struct vm_area_struct *vma) { if (vma->vm_flags & VM_SHARED) { /* do not allow mprotect to make mapping writable */ -- cgit v1.2.1 From 02f5daa563456c1ff3c3422aa3ec00e67460f762 Mon Sep 17 00:00:00 2001 From: James Morris Date: Tue, 30 Aug 2011 14:18:06 +1000 Subject: selinux: sparse fix: fix warnings in netlink code Fix sparse warnings in SELinux Netlink code. Signed-off-by: James Morris Signed-off-by: Eric Paris --- security/selinux/hooks.c | 1 - security/selinux/include/security.h | 3 +++ security/selinux/netlink.c | 2 ++ security/selinux/nlmsgtab.c | 1 + security/selinux/selinuxfs.c | 2 -- security/selinux/ss/services.c | 2 -- 6 files changed, 6 insertions(+), 5 deletions(-) (limited to 'security') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 4a176b468719..1206cee31c79 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -92,7 +92,6 @@ #define NUM_SEL_MNT_OPTS 5 -extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm); extern struct security_operations *security_ops; /* SECMARK reference count */ diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 13b626352f0b..d871e8ad2103 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -221,6 +221,9 @@ extern int selinux_disable(void); extern void exit_sel_fs(void); extern struct dentry *selinux_null; extern struct vfsmount *selinuxfs_mount; +extern void selnl_notify_setenforce(int val); +extern void selnl_notify_policyload(u32 seqno); +extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm); #endif /* _SELINUX_SECURITY_H_ */ diff --git a/security/selinux/netlink.c b/security/selinux/netlink.c index 36ac257cec9a..ce3f481558d8 100644 --- a/security/selinux/netlink.c +++ b/security/selinux/netlink.c @@ -19,6 +19,8 @@ #include #include +#include "security.h" + static struct sock *selnl; static int selnl_msglen(int msgtype) diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c index 8b02b2137da2..0920ea3bf599 100644 --- a/security/selinux/nlmsgtab.c +++ b/security/selinux/nlmsgtab.c @@ -21,6 +21,7 @@ #include "flask.h" #include "av_permissions.h" +#include "security.h" struct nlmsg_perm { u16 nlmsg_type; diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index ba2ada5f16a9..f46658722c78 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -75,8 +75,6 @@ static char policy_opened; /* global data for policy capabilities */ static struct dentry *policycap_dir; -extern void selnl_notify_setenforce(int val); - /* Check whether a task is allowed to use a security operation. */ static int task_has_security(struct task_struct *tsk, u32 perms) diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 37c50c602f17..185f849a26f6 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -70,8 +70,6 @@ #include "ebitmap.h" #include "audit.h" -extern void selnl_notify_policyload(u32 seqno); - int selinux_policycap_netpeer; int selinux_policycap_openperm; -- cgit v1.2.1 From 2653812e14f4e16688ec8247d7fd290bdbbc4747 Mon Sep 17 00:00:00 2001 From: James Morris Date: Tue, 30 Aug 2011 14:19:02 +1000 Subject: selinux: sparse fix: fix several warnings in the security server cod Fix several sparse warnings in the SELinux security server code. Signed-off-by: James Morris Signed-off-by: Eric Paris --- security/selinux/hooks.c | 5 +---- security/selinux/include/avc_ss.h | 6 ++++++ security/selinux/ss/conditional.c | 2 +- security/selinux/ss/conditional.h | 1 + security/selinux/ss/policydb.c | 2 -- 5 files changed, 9 insertions(+), 7 deletions(-) (limited to 'security') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 1206cee31c79..e545b9f67072 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -89,6 +89,7 @@ #include "xfrm.h" #include "netlabel.h" #include "audit.h" +#include "avc_ss.h" #define NUM_SEL_MNT_OPTS 5 @@ -278,10 +279,6 @@ static void superblock_free_security(struct super_block *sb) kfree(sbsec); } -/* The security server must be initialized before - any labeling or access decisions can be provided. */ -extern int ss_initialized; - /* The file system's label must be initialized prior to use. */ static const char *labeling_behaviors[6] = { diff --git a/security/selinux/include/avc_ss.h b/security/selinux/include/avc_ss.h index 4677aa519b04..d5c328452df0 100644 --- a/security/selinux/include/avc_ss.h +++ b/security/selinux/include/avc_ss.h @@ -18,5 +18,11 @@ struct security_class_mapping { extern struct security_class_mapping secclass_map[]; +/* + * The security server must be initialized before + * any labeling or access decisions can be provided. + */ +extern int ss_initialized; + #endif /* _SELINUX_AVC_SS_H_ */ diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c index a53373207fb4..2ec904177fe0 100644 --- a/security/selinux/ss/conditional.c +++ b/security/selinux/ss/conditional.c @@ -555,7 +555,7 @@ static int cond_write_av_list(struct policydb *p, return 0; } -int cond_write_node(struct policydb *p, struct cond_node *node, +static int cond_write_node(struct policydb *p, struct cond_node *node, struct policy_file *fp) { struct cond_expr *cur_expr; diff --git a/security/selinux/ss/conditional.h b/security/selinux/ss/conditional.h index 3f209c635295..4d1f87466508 100644 --- a/security/selinux/ss/conditional.h +++ b/security/selinux/ss/conditional.h @@ -13,6 +13,7 @@ #include "avtab.h" #include "symtab.h" #include "policydb.h" +#include "../include/conditional.h" #define COND_EXPR_MAXDEPTH 10 diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index 2381d0ded228..a7f61d52f05c 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c @@ -1743,8 +1743,6 @@ static int policydb_bounds_sanity_check(struct policydb *p) return 0; } -extern int ss_initialized; - u16 string_to_security_class(struct policydb *p, const char *name) { struct class_datum *cladatum; -- cgit v1.2.1 From 6a9de49115d5ff9871d953af1a5c8249e1585731 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Tue, 3 Jan 2012 12:25:14 -0500 Subject: capabilities: remove the task from capable LSM hook entirely The capabilities framework is based around credentials, not necessarily the current task. Yet we still passed the current task down into LSMs from the security_capable() LSM hook as if it was a meaningful portion of the security decision. This patch removes the 'generic' passing of current and instead forces individual LSMs to use current explicitly if they think it is appropriate. In our case those LSMs are SELinux and AppArmor. I believe the AppArmor use of current is incorrect, but that is wholely unrelated to this patch. This patch does not change what AppArmor does, it just makes it clear in the AppArmor code that it is doing it. The SELinux code still uses current in it's audit message, which may also be wrong and needs further investigation. Again this is NOT a change, it may have always been wrong, this patch just makes it clear what is happening. Signed-off-by: Eric Paris --- security/apparmor/lsm.c | 8 ++++---- security/commoncap.c | 16 +++++++--------- security/security.c | 7 +++---- security/selinux/hooks.c | 23 ++++++++++------------- 4 files changed, 24 insertions(+), 30 deletions(-) (limited to 'security') diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 37832026e58a..ef4e2a8a33a5 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -136,16 +136,16 @@ static int apparmor_capget(struct task_struct *target, kernel_cap_t *effective, return 0; } -static int apparmor_capable(struct task_struct *task, const struct cred *cred, - struct user_namespace *ns, int cap, int audit) +static int apparmor_capable(const struct cred *cred, struct user_namespace *ns, + int cap, int audit) { struct aa_profile *profile; /* cap_capable returns 0 on success, else -EPERM */ - int error = cap_capable(task, cred, ns, cap, audit); + int error = cap_capable(cred, ns, cap, audit); if (!error) { profile = aa_cred_profile(cred); if (!unconfined(profile)) - error = aa_capable(task, profile, cap, audit); + error = aa_capable(current, profile, cap, audit); } return error; } diff --git a/security/commoncap.c b/security/commoncap.c index a93b3b733079..89f02ff66af9 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -66,7 +66,6 @@ EXPORT_SYMBOL(cap_netlink_recv); /** * cap_capable - Determine whether a task has a particular effective capability - * @tsk: The task to query * @cred: The credentials to use * @ns: The user namespace in which we need the capability * @cap: The capability to check for @@ -80,8 +79,8 @@ EXPORT_SYMBOL(cap_netlink_recv); * cap_has_capability() returns 0 when a task has a capability, but the * kernel's capable() and has_capability() returns 1 for this case. */ -int cap_capable(struct task_struct *tsk, const struct cred *cred, - struct user_namespace *targ_ns, int cap, int audit) +int cap_capable(const struct cred *cred, struct user_namespace *targ_ns, + int cap, int audit) { for (;;) { /* The creator of the user namespace has all caps. */ @@ -222,9 +221,8 @@ static inline int cap_inh_is_capped(void) /* they are so limited unless the current task has the CAP_SETPCAP * capability */ - if (cap_capable(current, current_cred(), - current_cred()->user->user_ns, CAP_SETPCAP, - SECURITY_CAP_AUDIT) == 0) + if (cap_capable(current_cred(), current_cred()->user->user_ns, + CAP_SETPCAP, SECURITY_CAP_AUDIT) == 0) return 0; return 1; } @@ -870,7 +868,7 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3, & (new->securebits ^ arg2)) /*[1]*/ || ((new->securebits & SECURE_ALL_LOCKS & ~arg2)) /*[2]*/ || (arg2 & ~(SECURE_ALL_LOCKS | SECURE_ALL_BITS)) /*[3]*/ - || (cap_capable(current, current_cred(), + || (cap_capable(current_cred(), current_cred()->user->user_ns, CAP_SETPCAP, SECURITY_CAP_AUDIT) != 0) /*[4]*/ /* @@ -936,7 +934,7 @@ int cap_vm_enough_memory(struct mm_struct *mm, long pages) { int cap_sys_admin = 0; - if (cap_capable(current, current_cred(), &init_user_ns, CAP_SYS_ADMIN, + if (cap_capable(current_cred(), &init_user_ns, CAP_SYS_ADMIN, SECURITY_CAP_NOAUDIT) == 0) cap_sys_admin = 1; return __vm_enough_memory(mm, pages, cap_sys_admin); @@ -963,7 +961,7 @@ int cap_file_mmap(struct file *file, unsigned long reqprot, int ret = 0; if (addr < dac_mmap_min_addr) { - ret = cap_capable(current, current_cred(), &init_user_ns, CAP_SYS_RAWIO, + ret = cap_capable(current_cred(), &init_user_ns, CAP_SYS_RAWIO, SECURITY_CAP_AUDIT); /* set PF_SUPERPRIV if it turns out we allow the low mmap */ if (ret == 0) diff --git a/security/security.c b/security/security.c index d9e153390926..9ae68c64455e 100644 --- a/security/security.c +++ b/security/security.c @@ -157,8 +157,7 @@ int security_capset(struct cred *new, const struct cred *old, int security_capable(struct user_namespace *ns, const struct cred *cred, int cap) { - return security_ops->capable(current, cred, ns, cap, - SECURITY_CAP_AUDIT); + return security_ops->capable(cred, ns, cap, SECURITY_CAP_AUDIT); } int security_real_capable(struct task_struct *tsk, struct user_namespace *ns, @@ -168,7 +167,7 @@ int security_real_capable(struct task_struct *tsk, struct user_namespace *ns, int ret; cred = get_task_cred(tsk); - ret = security_ops->capable(tsk, cred, ns, cap, SECURITY_CAP_AUDIT); + ret = security_ops->capable(cred, ns, cap, SECURITY_CAP_AUDIT); put_cred(cred); return ret; } @@ -180,7 +179,7 @@ int security_real_capable_noaudit(struct task_struct *tsk, int ret; cred = get_task_cred(tsk); - ret = security_ops->capable(tsk, cred, ns, cap, SECURITY_CAP_NOAUDIT); + ret = security_ops->capable(cred, ns, cap, SECURITY_CAP_NOAUDIT); put_cred(cred); return ret; } diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index e545b9f67072..c9605c4a2e08 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -1414,8 +1414,7 @@ static int current_has_perm(const struct task_struct *tsk, #endif /* Check whether a task is allowed to use a capability. */ -static int task_has_capability(struct task_struct *tsk, - const struct cred *cred, +static int cred_has_capability(const struct cred *cred, int cap, int audit) { struct common_audit_data ad; @@ -1426,7 +1425,7 @@ static int task_has_capability(struct task_struct *tsk, int rc; COMMON_AUDIT_DATA_INIT(&ad, CAP); - ad.tsk = tsk; + ad.tsk = current; ad.u.cap = cap; switch (CAP_TO_INDEX(cap)) { @@ -1867,16 +1866,16 @@ static int selinux_capset(struct cred *new, const struct cred *old, * the CAP_SETUID and CAP_SETGID capabilities using the capable hook. */ -static int selinux_capable(struct task_struct *tsk, const struct cred *cred, - struct user_namespace *ns, int cap, int audit) +static int selinux_capable(const struct cred *cred, struct user_namespace *ns, + int cap, int audit) { int rc; - rc = cap_capable(tsk, cred, ns, cap, audit); + rc = cap_capable(cred, ns, cap, audit); if (rc) return rc; - return task_has_capability(tsk, cred, cap, audit); + return cred_has_capability(cred, cap, audit); } static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb) @@ -1953,8 +1952,7 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages) { int rc, cap_sys_admin = 0; - rc = selinux_capable(current, current_cred(), - &init_user_ns, CAP_SYS_ADMIN, + rc = selinux_capable(current_cred(), &init_user_ns, CAP_SYS_ADMIN, SECURITY_CAP_NOAUDIT); if (rc == 0) cap_sys_admin = 1; @@ -2858,8 +2856,7 @@ static int selinux_inode_getsecurity(const struct inode *inode, const char *name * and lack of permission just means that we fall back to the * in-core context value, not a denial. */ - error = selinux_capable(current, current_cred(), - &init_user_ns, CAP_MAC_ADMIN, + error = selinux_capable(current_cred(), &init_user_ns, CAP_MAC_ADMIN, SECURITY_CAP_NOAUDIT); if (!error) error = security_sid_to_context_force(isec->sid, &context, @@ -2992,8 +2989,8 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd, case KDSKBENT: case KDSKBSENT: - error = task_has_capability(current, cred, CAP_SYS_TTY_CONFIG, - SECURITY_CAP_AUDIT); + error = cred_has_capability(cred, CAP_SYS_TTY_CONFIG, + SECURITY_CAP_AUDIT); break; /* default case assumes that the command will go -- cgit v1.2.1 From b7e724d303b684655e4ca3dabd5a6840ad19012d Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Tue, 3 Jan 2012 12:25:15 -0500 Subject: capabilities: reverse arguments to security_capable security_capable takes ns, cred, cap. But the LSM capable() hook takes cred, ns, cap. The capability helper functions also take cred, ns, cap. Rather than flip argument order just to flip it back, leave them alone. Heck, this should be a little faster since argument will be in the right place! Signed-off-by: Eric Paris --- security/security.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'security') diff --git a/security/security.c b/security/security.c index 9ae68c64455e..b9e57f4fc44a 100644 --- a/security/security.c +++ b/security/security.c @@ -154,7 +154,7 @@ int security_capset(struct cred *new, const struct cred *old, effective, inheritable, permitted); } -int security_capable(struct user_namespace *ns, const struct cred *cred, +int security_capable(const struct cred *cred, struct user_namespace *ns, int cap) { return security_ops->capable(cred, ns, cap, SECURITY_CAP_AUDIT); -- cgit v1.2.1 From c7eba4a97563fd8b431787f7ad623444f2da80c6 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Tue, 3 Jan 2012 12:25:15 -0500 Subject: capabilities: introduce security_capable_noaudit Exactly like security_capable except don't audit any denials. This is for places where the kernel may make decisions about what to do if a task has a given capability, but which failing that capability is not a sign of a security policy violation. An example is checking if a task has CAP_SYS_ADMIN to lower it's likelyhood of being killed by the oom killer. This check is not a security violation if it is denied. Signed-off-by: Eric Paris Acked-by: Serge E. Hallyn --- security/security.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'security') diff --git a/security/security.c b/security/security.c index b9e57f4fc44a..b7edaae77d1d 100644 --- a/security/security.c +++ b/security/security.c @@ -160,6 +160,12 @@ int security_capable(const struct cred *cred, struct user_namespace *ns, return security_ops->capable(cred, ns, cap, SECURITY_CAP_AUDIT); } +int security_capable_noaudit(const struct cred *cred, struct user_namespace *ns, + int cap) +{ + return security_ops->capable(cred, ns, cap, SECURITY_CAP_NOAUDIT); +} + int security_real_capable(struct task_struct *tsk, struct user_namespace *ns, int cap) { -- cgit v1.2.1 From 2920a8409de5a51575d03deca07e5bb2be6fc98d Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Tue, 3 Jan 2012 12:25:15 -0500 Subject: capabilities: remove all _real_ interfaces The name security_real_capable and security_real_capable_noaudit just don't make much sense to me. Convert them to use security_capable and security_capable_noaudit. Signed-off-by: Eric Paris Acked-by: Serge E. Hallyn --- security/security.c | 24 ------------------------ 1 file changed, 24 deletions(-) (limited to 'security') diff --git a/security/security.c b/security/security.c index b7edaae77d1d..8900c5c4db5c 100644 --- a/security/security.c +++ b/security/security.c @@ -166,30 +166,6 @@ int security_capable_noaudit(const struct cred *cred, struct user_namespace *ns, return security_ops->capable(cred, ns, cap, SECURITY_CAP_NOAUDIT); } -int security_real_capable(struct task_struct *tsk, struct user_namespace *ns, - int cap) -{ - const struct cred *cred; - int ret; - - cred = get_task_cred(tsk); - ret = security_ops->capable(cred, ns, cap, SECURITY_CAP_AUDIT); - put_cred(cred); - return ret; -} - -int security_real_capable_noaudit(struct task_struct *tsk, - struct user_namespace *ns, int cap) -{ - const struct cred *cred; - int ret; - - cred = get_task_cred(tsk); - ret = security_ops->capable(cred, ns, cap, SECURITY_CAP_NOAUDIT); - put_cred(cred); - return ret; -} - int security_quotactl(int cmds, int type, int id, struct super_block *sb) { return security_ops->quotactl(cmds, type, id, sb); -- cgit v1.2.1 From 69f594a38967f4540ce7a29b3fd214e68a8330bd Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Tue, 3 Jan 2012 12:25:15 -0500 Subject: ptrace: do not audit capability check when outputing /proc/pid/stat Reading /proc/pid/stat of another process checks if one has ptrace permissions on that process. If one does have permissions it outputs some data about the process which might have security and attack implications. If the current task does not have ptrace permissions the read still works, but those fields are filled with inocuous (0) values. Since this check and a subsequent denial is not a violation of the security policy we should not audit such denials. This can be quite useful to removing ptrace broadly across a system without flooding the logs when ps is run or something which harmlessly walks proc. Signed-off-by: Eric Paris Acked-by: Serge E. Hallyn --- security/selinux/hooks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'security') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index c9605c4a2e08..14f94cd29c80 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -1809,7 +1809,7 @@ static int selinux_ptrace_access_check(struct task_struct *child, if (rc) return rc; - if (mode == PTRACE_MODE_READ) { + if (mode & PTRACE_MODE_READ) { u32 sid = current_sid(); u32 csid = task_sid(child); return avc_has_perm(sid, csid, SECCLASS_FILE, FILE__READ, NULL); -- cgit v1.2.1 From fd778461524849afd035679030ae8e8873c72b81 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Tue, 3 Jan 2012 12:25:16 -0500 Subject: security: remove the security_netlink_recv hook as it is equivalent to capable() Once upon a time netlink was not sync and we had to get the effective capabilities from the skb that was being received. Today we instead get the capabilities from the current task. This has rendered the entire purpose of the hook moot as it is now functionally equivalent to the capable() call. Signed-off-by: Eric Paris --- security/capability.c | 1 - security/commoncap.c | 8 -------- security/security.c | 6 ------ security/selinux/hooks.c | 19 ------------------- 4 files changed, 34 deletions(-) (limited to 'security') diff --git a/security/capability.c b/security/capability.c index 2984ea4f776f..a2c064d10448 100644 --- a/security/capability.c +++ b/security/capability.c @@ -999,7 +999,6 @@ void __init security_fixup_ops(struct security_operations *ops) set_to_cap_if_null(ops, sem_semctl); set_to_cap_if_null(ops, sem_semop); set_to_cap_if_null(ops, netlink_send); - set_to_cap_if_null(ops, netlink_recv); set_to_cap_if_null(ops, d_instantiate); set_to_cap_if_null(ops, getprocattr); set_to_cap_if_null(ops, setprocattr); diff --git a/security/commoncap.c b/security/commoncap.c index 89f02ff66af9..7817a763444d 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -56,14 +56,6 @@ int cap_netlink_send(struct sock *sk, struct sk_buff *skb) return 0; } -int cap_netlink_recv(struct sk_buff *skb, int cap) -{ - if (!cap_raised(current_cap(), cap)) - return -EPERM; - return 0; -} -EXPORT_SYMBOL(cap_netlink_recv); - /** * cap_capable - Determine whether a task has a particular effective capability * @cred: The credentials to use diff --git a/security/security.c b/security/security.c index 8900c5c4db5c..85481a9c5632 100644 --- a/security/security.c +++ b/security/security.c @@ -922,12 +922,6 @@ int security_netlink_send(struct sock *sk, struct sk_buff *skb) return security_ops->netlink_send(sk, skb); } -int security_netlink_recv(struct sk_buff *skb, int cap) -{ - return security_ops->netlink_recv(skb, cap); -} -EXPORT_SYMBOL(security_netlink_recv); - int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) { return security_ops->secid_to_secctx(secid, secdata, seclen); diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 14f94cd29c80..3e37d25a9bbe 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -4713,24 +4713,6 @@ static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb) return selinux_nlmsg_perm(sk, skb); } -static int selinux_netlink_recv(struct sk_buff *skb, int capability) -{ - int err; - struct common_audit_data ad; - u32 sid; - - err = cap_netlink_recv(skb, capability); - if (err) - return err; - - COMMON_AUDIT_DATA_INIT(&ad, CAP); - ad.u.cap = capability; - - security_task_getsecid(current, &sid); - return avc_has_perm(sid, sid, SECCLASS_CAPABILITY, - CAP_TO_MASK(capability), &ad); -} - static int ipc_alloc_security(struct task_struct *task, struct kern_ipc_perm *perm, u16 sclass) @@ -5459,7 +5441,6 @@ static struct security_operations selinux_ops = { .vm_enough_memory = selinux_vm_enough_memory, .netlink_send = selinux_netlink_send, - .netlink_recv = selinux_netlink_recv, .bprm_set_creds = selinux_bprm_set_creds, .bprm_committing_creds = selinux_bprm_committing_creds, -- cgit v1.2.1