[NetLabel]: correct improper handling of non-NetLabel peer contexts
authorPaul Moore <paul.moore@hp.com>
Mon, 25 Sep 2006 22:52:01 +0000 (15:52 -0700)
committerDavid S. Miller <davem@davemloft.net>
Mon, 25 Sep 2006 22:52:01 +0000 (15:52 -0700)
Fix a problem where NetLabel would always set the value of
sk_security_struct->peer_sid in selinux_netlbl_sock_graft() to the context of
the socket, causing problems when users would query the context of the
connection.  This patch fixes this so that the value in
sk_security_struct->peer_sid is only set when the connection is NetLabel based,
otherwise the value is untouched.

Signed-off-by: Paul Moore <paul.moore@hp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/cipso_ipv4.h
include/net/netlabel.h
net/ipv4/cipso_ipv4.c
net/netlabel/netlabel_kapi.c
security/selinux/ss/services.c

index 59406e0..6718452 100644 (file)
@@ -205,6 +205,7 @@ void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway);
 int cipso_v4_socket_setattr(const struct socket *sock,
                            const struct cipso_v4_doi *doi_def,
                            const struct netlbl_lsm_secattr *secattr);
+int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr);
 int cipso_v4_socket_getattr(const struct socket *sock,
                            struct netlbl_lsm_secattr *secattr);
 int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
@@ -225,6 +226,12 @@ static inline int cipso_v4_socket_setattr(const struct socket *sock,
        return -ENOSYS;
 }
 
+static inline int cipso_v4_sock_getattr(struct sock *sk,
+                                       struct netlbl_lsm_secattr *secattr)
+{
+       return -ENOSYS;
+}
+
 static inline int cipso_v4_socket_getattr(const struct socket *sock,
                                          struct netlbl_lsm_secattr *secattr)
 {
index dd5780b..bf7b564 100644 (file)
@@ -238,6 +238,8 @@ static inline void netlbl_secattr_free(struct netlbl_lsm_secattr *secattr,
 #ifdef CONFIG_NETLABEL
 int netlbl_socket_setattr(const struct socket *sock,
                          const struct netlbl_lsm_secattr *secattr);
+int netlbl_sock_getattr(struct sock *sk,
+                       struct netlbl_lsm_secattr *secattr);
 int netlbl_socket_getattr(const struct socket *sock,
                          struct netlbl_lsm_secattr *secattr);
 int netlbl_skbuff_getattr(const struct sk_buff *skb,
@@ -250,6 +252,12 @@ static inline int netlbl_socket_setattr(const struct socket *sock,
        return -ENOSYS;
 }
 
+static inline int netlbl_sock_getattr(struct sock *sk,
+                                     struct netlbl_lsm_secattr *secattr)
+{
+       return -ENOSYS;
+}
+
 static inline int netlbl_socket_getattr(const struct socket *sock,
                                        struct netlbl_lsm_secattr *secattr)
 {
index 80a2a09..a3bae2c 100644 (file)
@@ -1486,43 +1486,40 @@ socket_setattr_failure:
 }
 
 /**
- * cipso_v4_socket_getattr - Get the security attributes from a socket
- * @sock: the socket
+ * cipso_v4_sock_getattr - Get the security attributes from a sock
+ * @sk: the sock
  * @secattr: the security attributes
  *
  * Description:
- * Query @sock to see if there is a CIPSO option attached to the socket and if
- * there is return the CIPSO security attributes in @secattr.  Returns zero on
- * success and negative values on failure.
+ * Query @sk to see if there is a CIPSO option attached to the sock and if
+ * there is return the CIPSO security attributes in @secattr.  This function
+ * requires that @sk be locked, or privately held, but it does not do any
+ * locking itself.  Returns zero on success and negative values on failure.
  *
  */
-int cipso_v4_socket_getattr(const struct socket *sock,
-                           struct netlbl_lsm_secattr *secattr)
+int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
 {
        int ret_val = -ENOMSG;
-       struct sock *sk;
        struct inet_sock *sk_inet;
        unsigned char *cipso_ptr;
        u32 doi;
        struct cipso_v4_doi *doi_def;
 
-       sk = sock->sk;
-       lock_sock(sk);
        sk_inet = inet_sk(sk);
        if (sk_inet->opt == NULL || sk_inet->opt->cipso == 0)
-               goto socket_getattr_return;
+               return -ENOMSG;
        cipso_ptr = sk_inet->opt->__data + sk_inet->opt->cipso -
                sizeof(struct iphdr);
        ret_val = cipso_v4_cache_check(cipso_ptr, cipso_ptr[1], secattr);
        if (ret_val == 0)
-               goto socket_getattr_return;
+               return ret_val;
 
        doi = ntohl(*(u32 *)&cipso_ptr[2]);
        rcu_read_lock();
        doi_def = cipso_v4_doi_getdef(doi);
        if (doi_def == NULL) {
                rcu_read_unlock();
-               goto socket_getattr_return;
+               return -ENOMSG;
        }
        switch (cipso_ptr[6]) {
        case CIPSO_V4_TAG_RBITMAP:
@@ -1533,8 +1530,29 @@ int cipso_v4_socket_getattr(const struct socket *sock,
        }
        rcu_read_unlock();
 
-socket_getattr_return:
-       release_sock(sk);
+       return ret_val;
+}
+
+/**
+ * cipso_v4_socket_getattr - Get the security attributes from a socket
+ * @sock: the socket
+ * @secattr: the security attributes
+ *
+ * Description:
+ * Query @sock to see if there is a CIPSO option attached to the socket and if
+ * there is return the CIPSO security attributes in @secattr.  Returns zero on
+ * success and negative values on failure.
+ *
+ */
+int cipso_v4_socket_getattr(const struct socket *sock,
+                           struct netlbl_lsm_secattr *secattr)
+{
+       int ret_val;
+
+       lock_sock(sock->sk);
+       ret_val = cipso_v4_sock_getattr(sock->sk, secattr);
+       release_sock(sock->sk);
+
        return ret_val;
 }
 
index 0fd8aaa..54fb7de 100644 (file)
@@ -85,6 +85,29 @@ socket_setattr_return:
 }
 
 /**
+ * netlbl_sock_getattr - Determine the security attributes of a sock
+ * @sk: the sock
+ * @secattr: the security attributes
+ *
+ * Description:
+ * Examines the given sock to see any NetLabel style labeling has been
+ * applied to the sock, if so it parses the socket label and returns the
+ * security attributes in @secattr.  Returns zero on success, negative values
+ * on failure.
+ *
+ */
+int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
+{
+       int ret_val;
+
+       ret_val = cipso_v4_sock_getattr(sk, secattr);
+       if (ret_val == 0)
+               return 0;
+
+       return netlbl_unlabel_getattr(secattr);
+}
+
+/**
  * netlbl_socket_getattr - Determine the security attributes of a socket
  * @sock: the socket
  * @secattr: the security attributes
index 7eb69a6..d67f7e6 100644 (file)
@@ -2502,14 +2502,24 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
 {
        struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
        struct sk_security_struct *sksec = sk->sk_security;
+       struct netlbl_lsm_secattr secattr;
+       u32 nlbl_peer_sid;
 
        sksec->sclass = isec->sclass;
 
        if (sk->sk_family != PF_INET)
                return;
 
+       netlbl_secattr_init(&secattr);
+       if (netlbl_sock_getattr(sk, &secattr) == 0 &&
+           selinux_netlbl_secattr_to_sid(NULL,
+                                         &secattr,
+                                         sksec->sid,
+                                         &nlbl_peer_sid) == 0)
+               sksec->peer_sid = nlbl_peer_sid;
+       netlbl_secattr_destroy(&secattr, 0);
+
        sksec->nlbl_state = NLBL_REQUIRE;
-       sksec->peer_sid = sksec->sid;
 
        /* Try to set the NetLabel on the socket to save time later, if we fail
         * here we will pick up the pieces in later calls to