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/selinux') diff --git a/security/selinux/netport.c b/security/selinux/netport.c index 0b62bd11246..7b9eb1faf68 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.3 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/selinux') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 266a2292451..e07cf7fcdce 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.3 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/selinux') diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 3ba4feba048..8556e1a263c 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 f6917bc0aa0..37c50c602f1 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.3 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/selinux') diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 8556e1a263c..30002c43436 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 55d92cbb177..d3677c6c12c 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.3 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/selinux') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index e07cf7fcdce..4a176b46871 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 30002c43436..13b626352f0 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 d3677c6c12c..ba2ada5f16a 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.3 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/selinux') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 4a176b46871..1206cee31c7 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 13b626352f0..d871e8ad210 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 36ac257cec9..ce3f481558d 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 8b02b2137da..0920ea3bf59 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 ba2ada5f16a..f46658722c7 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 37c50c602f1..185f849a26f 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.3 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/selinux') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 1206cee31c7..e545b9f6707 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 4677aa519b0..d5c328452df 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 a53373207fb..2ec904177fe 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 3f209c63529..4d1f8746650 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 2381d0ded22..a7f61d52f05 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.3 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/selinux/hooks.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) (limited to 'security/selinux') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index e545b9f6707..c9605c4a2e0 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.3 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/selinux') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index c9605c4a2e0..14f94cd29c8 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.3 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/selinux/hooks.c | 19 ------------------- 1 file changed, 19 deletions(-) (limited to 'security/selinux') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 14f94cd29c8..3e37d25a9bb 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.3