summaryrefslogtreecommitdiffstats
path: root/security/selinux
diff options
context:
space:
mode:
authorPaul Moore <pmoore@redhat.com>2013-12-03 11:36:11 -0500
committerPaul Moore <pmoore@redhat.com>2013-12-04 16:08:17 -0500
commit050d032b25e617cd738db8d6fd5aed24d87cbbcb (patch)
tree53771bb7cebc1cf36bbd0442d3acc1a93e4ccedb /security/selinux
parent7f721643db3b2da53e1b91aaa4e8cb7706bfdd10 (diff)
selinux: ensure that the cached NetLabel secattr matches the desired SID
In selinux_netlbl_skbuff_setsid() we leverage a cached NetLabel secattr whenever possible. However, we never check to ensure that the desired SID matches the cached NetLabel secattr. This patch checks the SID against the secattr before use and only uses the cached secattr when the SID values match. Signed-off-by: Paul Moore <pmoore@redhat.com>
Diffstat (limited to 'security/selinux')
-rw-r--r--security/selinux/netlabel.c31
1 files changed, 30 insertions, 1 deletions
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c
index 6235d052338..0364120d1ec 100644
--- a/security/selinux/netlabel.c
+++ b/security/selinux/netlabel.c
@@ -101,6 +101,32 @@ static struct netlbl_lsm_secattr *selinux_netlbl_sock_genattr(struct sock *sk)
}
/**
+ * selinux_netlbl_sock_getattr - Get the cached NetLabel secattr
+ * @sk: the socket
+ * @sid: the SID
+ *
+ * Query the socket's cached secattr and if the SID matches the cached value
+ * return the cache, otherwise return NULL.
+ *
+ */
+static struct netlbl_lsm_secattr *selinux_netlbl_sock_getattr(
+ const struct sock *sk,
+ u32 sid)
+{
+ struct sk_security_struct *sksec = sk->sk_security;
+ struct netlbl_lsm_secattr *secattr = sksec->nlbl_secattr;
+
+ if (secattr == NULL)
+ return NULL;
+
+ if ((secattr->flags & NETLBL_SECATTR_SECID) &&
+ (secattr->attr.secid == sid))
+ return secattr;
+
+ return NULL;
+}
+
+/**
* selinux_netlbl_cache_invalidate - Invalidate the NetLabel cache
*
* Description:
@@ -224,7 +250,7 @@ int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
struct sk_security_struct *sksec = sk->sk_security;
if (sksec->nlbl_state != NLBL_REQSKB)
return 0;
- secattr = sksec->nlbl_secattr;
+ secattr = selinux_netlbl_sock_getattr(sk, sid);
}
if (secattr == NULL) {
secattr = &secattr_storage;
@@ -410,6 +436,9 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock,
sksec->nlbl_state == NLBL_CONNLABELED)) {
netlbl_secattr_init(&secattr);
lock_sock(sk);
+ /* call the netlabel function directly as we want to see the
+ * on-the-wire label that is assigned via the socket's options
+ * and not the cached netlabel/lsm attributes */
rc = netlbl_sock_getattr(sk, &secattr);
release_sock(sk);
if (rc == 0)