From 2c3c05dbcbc7b9d71549fe0e2b249f10f5a66518 Mon Sep 17 00:00:00 2001 From: Stephen Smalley Date: Thu, 7 Jun 2007 15:34:10 -0400 Subject: SELinux: allow preemption between transition permission checks In security_get_user_sids, move the transition permission checks outside of the section holding the policy rdlock, and use the AVC to perform the checks, calling cond_resched after each one. These changes should allow preemption between the individual checks and enable caching of the results. It may however increase the overall time spent in the function in some cases, particularly in the cache miss case. The long term fix will be to take much of this logic to userspace by exporting additional state via selinuxfs, and ultimately deprecating and eliminating this interface from the kernel. Tested-by: Ingo Molnar Signed-off-by: Stephen Smalley Signed-off-by: James Morris --- security/selinux/hooks.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'security/selinux/hooks.c') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index ad8dd4e8657e..b29059ecc045 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -1592,9 +1592,10 @@ static int selinux_vm_enough_memory(long pages) rc = secondary_ops->capable(current, CAP_SYS_ADMIN); if (rc == 0) rc = avc_has_perm_noaudit(tsec->sid, tsec->sid, - SECCLASS_CAPABILITY, - CAP_TO_MASK(CAP_SYS_ADMIN), - NULL); + SECCLASS_CAPABILITY, + CAP_TO_MASK(CAP_SYS_ADMIN), + 0, + NULL); if (rc == 0) cap_sys_admin = 1; @@ -4626,7 +4627,7 @@ static int selinux_setprocattr(struct task_struct *p, if (p->ptrace & PT_PTRACED) { error = avc_has_perm_noaudit(tsec->ptrace_sid, sid, SECCLASS_PROCESS, - PROCESS__PTRACE, &avd); + PROCESS__PTRACE, 0, &avd); if (!error) tsec->sid = sid; task_unlock(p); -- cgit v1.2.3 From ed0321895182ffb6ecf210e066d87911b270d587 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Thu, 28 Jun 2007 15:55:21 -0400 Subject: security: Protection for exploiting null dereference using mmap Add a new security check on mmap operations to see if the user is attempting to mmap to low area of the address space. The amount of space protected is indicated by the new proc tunable /proc/sys/vm/mmap_min_addr and defaults to 0, preserving existing behavior. This patch uses a new SELinux security class "memprotect." Policy already contains a number of allow rules like a_t self:process * (unconfined_t being one of them) which mean that putting this check in the process class (its best current fit) would make it useless as all user processes, which we also want to protect against, would be allowed. By taking the memprotect name of the new class it will also make it possible for us to move some of the other memory protect permissions out of 'process' and into the new class next time we bump the policy version number (which I also think is a good future idea) Acked-by: Stephen Smalley Acked-by: Chris Wright Signed-off-by: Eric Paris Signed-off-by: James Morris --- security/selinux/hooks.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'security/selinux/hooks.c') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index b29059ecc045..78c3f98fcdcf 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2569,12 +2569,16 @@ static int file_map_prot_check(struct file *file, unsigned long prot, int shared } static int selinux_file_mmap(struct file *file, unsigned long reqprot, - unsigned long prot, unsigned long flags) + unsigned long prot, unsigned long flags, + unsigned long addr, unsigned long addr_only) { - int rc; + int rc = 0; + u32 sid = ((struct task_security_struct*)(current->security))->sid; - rc = secondary_ops->file_mmap(file, reqprot, prot, flags); - if (rc) + if (addr < mmap_min_addr) + rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT, + MEMPROTECT__MMAP_ZERO, NULL); + if (rc || addr_only) return rc; if (selinux_checkreqprot) -- cgit v1.2.3 From 9faf65fb6ee2b4e08325ba2d69e5ccf0c46453d0 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Fri, 29 Jun 2007 11:48:16 -0400 Subject: SELinux: use SECINITSID_NETMSG instead of SECINITSID_UNLABELED for NetLabel These changes will make NetLabel behave like labeled IPsec where there is an access check for both labeled and unlabeled packets as well as providing the ability to restrict domains to receiving only labeled packets when NetLabel is in use. The changes to the policy are straight forward with the following necessary to receive labeled traffic (with SECINITSID_NETMSG defined as "netlabel_peer_t"): allow mydom_t netlabel_peer_t:{ tcp_socket udp_socket rawip_socket } recvfrom; The policy for unlabeled traffic would be: allow mydom_t unlabeled_t:{ tcp_socket udp_socket rawip_socket } recvfrom; These policy changes, as well as more general NetLabel support, are included in the SELinux Reference Policy SVN tree, r2352 or later. Users who enable NetLabel support in the kernel are strongly encouraged to upgrade their policy to avoid network problems. Signed-off-by: Paul Moore Signed-off-by: James Morris --- security/selinux/hooks.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'security/selinux/hooks.c') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 78c3f98fcdcf..aff8f46c2aa2 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3129,17 +3129,19 @@ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, /** * selinux_skb_extlbl_sid - Determine the external label of a packet * @skb: the packet - * @base_sid: the SELinux SID to use as a context for MLS only external labels * @sid: the packet's SID * * Description: * Check the various different forms of external packet labeling and determine - * the external SID for the packet. + * the external SID for the packet. If only one form of external labeling is + * present then it is used, if both labeled IPsec and NetLabel labels are + * present then the SELinux type information is taken from the labeled IPsec + * SA and the MLS sensitivity label information is taken from the NetLabel + * security attributes. This bit of "magic" is done in the call to + * selinux_netlbl_skbuff_getsid(). * */ -static void selinux_skb_extlbl_sid(struct sk_buff *skb, - u32 base_sid, - u32 *sid) +static void selinux_skb_extlbl_sid(struct sk_buff *skb, u32 *sid) { u32 xfrm_sid; u32 nlbl_sid; @@ -3147,10 +3149,9 @@ static void selinux_skb_extlbl_sid(struct sk_buff *skb, selinux_skb_xfrm_sid(skb, &xfrm_sid); if (selinux_netlbl_skbuff_getsid(skb, (xfrm_sid == SECSID_NULL ? - base_sid : xfrm_sid), + SECINITSID_NETMSG : xfrm_sid), &nlbl_sid) != 0) nlbl_sid = SECSID_NULL; - *sid = (nlbl_sid == SECSID_NULL ? xfrm_sid : nlbl_sid); } @@ -3695,7 +3696,7 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff * if (sock && sock->sk->sk_family == PF_UNIX) selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid); else if (skb) - selinux_skb_extlbl_sid(skb, SECINITSID_UNLABELED, &peer_secid); + selinux_skb_extlbl_sid(skb, &peer_secid); if (peer_secid == SECSID_NULL) err = -EINVAL; @@ -3756,7 +3757,7 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb, u32 newsid; u32 peersid; - selinux_skb_extlbl_sid(skb, SECINITSID_UNLABELED, &peersid); + selinux_skb_extlbl_sid(skb, &peersid); if (peersid == SECSID_NULL) { req->secid = sksec->sid; req->peer_secid = SECSID_NULL; @@ -3794,7 +3795,7 @@ static void selinux_inet_conn_established(struct sock *sk, { struct sk_security_struct *sksec = sk->sk_security; - selinux_skb_extlbl_sid(skb, SECINITSID_UNLABELED, &sksec->peer_sid); + selinux_skb_extlbl_sid(skb, &sksec->peer_sid); } static void selinux_req_classify_flow(const struct request_sock *req, -- cgit v1.2.3 From 8d9107e8c50e1c4ff43c91c8841805833f3ecfb9 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 13 Jul 2007 16:53:18 -0700 Subject: Revert "SELinux: use SECINITSID_NETMSG instead of SECINITSID_UNLABELED for NetLabel" This reverts commit 9faf65fb6ee2b4e08325ba2d69e5ccf0c46453d0. It bit people like Michal Piotrowski: "My system is too secure, I can not login :)" because it changed how CONFIG_NETLABEL worked, and broke older SElinux policies. As a result, quoth James Morris: "Can you please revert this patch? We thought it only affected people running MLS, but it will affect others. Sorry for the hassle." Cc: James Morris Cc: Stephen Smalley Cc: Michal Piotrowski Cc: Paul Moore Signed-off-by: Linus Torvalds --- security/selinux/hooks.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'security/selinux/hooks.c') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index aff8f46c2aa2..78c3f98fcdcf 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3129,19 +3129,17 @@ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, /** * selinux_skb_extlbl_sid - Determine the external label of a packet * @skb: the packet + * @base_sid: the SELinux SID to use as a context for MLS only external labels * @sid: the packet's SID * * Description: * Check the various different forms of external packet labeling and determine - * the external SID for the packet. If only one form of external labeling is - * present then it is used, if both labeled IPsec and NetLabel labels are - * present then the SELinux type information is taken from the labeled IPsec - * SA and the MLS sensitivity label information is taken from the NetLabel - * security attributes. This bit of "magic" is done in the call to - * selinux_netlbl_skbuff_getsid(). + * the external SID for the packet. * */ -static void selinux_skb_extlbl_sid(struct sk_buff *skb, u32 *sid) +static void selinux_skb_extlbl_sid(struct sk_buff *skb, + u32 base_sid, + u32 *sid) { u32 xfrm_sid; u32 nlbl_sid; @@ -3149,9 +3147,10 @@ static void selinux_skb_extlbl_sid(struct sk_buff *skb, u32 *sid) selinux_skb_xfrm_sid(skb, &xfrm_sid); if (selinux_netlbl_skbuff_getsid(skb, (xfrm_sid == SECSID_NULL ? - SECINITSID_NETMSG : xfrm_sid), + base_sid : xfrm_sid), &nlbl_sid) != 0) nlbl_sid = SECSID_NULL; + *sid = (nlbl_sid == SECSID_NULL ? xfrm_sid : nlbl_sid); } @@ -3696,7 +3695,7 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff * if (sock && sock->sk->sk_family == PF_UNIX) selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid); else if (skb) - selinux_skb_extlbl_sid(skb, &peer_secid); + selinux_skb_extlbl_sid(skb, SECINITSID_UNLABELED, &peer_secid); if (peer_secid == SECSID_NULL) err = -EINVAL; @@ -3757,7 +3756,7 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb, u32 newsid; u32 peersid; - selinux_skb_extlbl_sid(skb, &peersid); + selinux_skb_extlbl_sid(skb, SECINITSID_UNLABELED, &peersid); if (peersid == SECSID_NULL) { req->secid = sksec->sid; req->peer_secid = SECSID_NULL; @@ -3795,7 +3794,7 @@ static void selinux_inet_conn_established(struct sock *sk, { struct sk_security_struct *sksec = sk->sk_security; - selinux_skb_extlbl_sid(skb, &sksec->peer_sid); + selinux_skb_extlbl_sid(skb, SECINITSID_UNLABELED, &sksec->peer_sid); } static void selinux_req_classify_flow(const struct request_sock *req, -- cgit v1.2.3 From 3bd858ab1c451725c07a805dcb315215dc85b86e Mon Sep 17 00:00:00 2001 From: Satyam Sharma Date: Tue, 17 Jul 2007 15:00:08 +0530 Subject: Introduce is_owner_or_cap() to wrap CAP_FOWNER use with fsuid check Introduce is_owner_or_cap() macro in fs.h, and convert over relevant users to it. This is done because we want to avoid bugs in the future where we check for only effective fsuid of the current task against a file's owning uid, without simultaneously checking for CAP_FOWNER as well, thus violating its semantics. [ XFS uses special macros and structures, and in general looked ... untouchable, so we leave it alone -- but it has been looked over. ] The (current->fsuid != inode->i_uid) check in generic_permission() and exec_permission_lite() is left alone, because those operations are covered by CAP_DAC_OVERRIDE and CAP_DAC_READ_SEARCH. Similarly operations falling under the purview of CAP_CHOWN and CAP_LEASE are also left alone. Signed-off-by: Satyam Sharma Cc: Al Viro Acked-by: Serge E. Hallyn Signed-off-by: Linus Torvalds --- security/selinux/hooks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'security/selinux/hooks.c') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 78c3f98fcdcf..520b9998123e 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2318,7 +2318,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT) return -EOPNOTSUPP; - if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER)) + if (!is_owner_or_cap(inode)) return -EPERM; AVC_AUDIT_DATA_INIT(&ad,FS); -- cgit v1.2.3