From 6363097cc4d182f93788131b5d8f72aa91d950a0 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 7 Jun 2007 18:35:38 -0700 Subject: [PATCH 1/3] [IPV4]: Do not remove idev when addresses are cleared Now that we create idev before addresses are added, it no longer makes sense to remove them when addresses are all deleted. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/ipv4/devinet.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index fa97b96a3d89..abf6352f990f 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -327,12 +327,8 @@ static void __inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, } } - if (destroy) { + if (destroy) inet_free_ifa(ifa1); - - if (!in_dev->ifa_list) - inetdev_destroy(in_dev); - } } static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, From ba6ff9f2b5c6018b293bd21083ffaa5ad710e671 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Thu, 7 Jun 2007 18:37:15 -0700 Subject: [PATCH 2/3] [NetLabel]: consolidate the struct socket/sock handling to just struct sock The current NetLabel code has some redundant APIs which allow both "struct socket" and "struct sock" types to be used; this may have made sense at some point but it is wasteful now. Remove the functions that operate on sockets and convert the callers. Not only does this make the code smaller and more consistent but it pushes the locking burden up to the caller which can be more intelligent about the locks. Also, perform the same conversion (socket to sock) on the SELinux/NetLabel glue code where it make sense. Signed-off-by: Paul Moore Acked-by: James Morris Signed-off-by: David S. Miller --- include/net/cipso_ipv4.h | 20 +++++------------ include/net/netlabel.h | 14 +++--------- net/ipv4/cipso_ipv4.c | 41 +++++++--------------------------- net/netlabel/netlabel_kapi.c | 43 ++++++++---------------------------- security/selinux/netlabel.c | 36 +++++++++++++++++------------- 5 files changed, 47 insertions(+), 107 deletions(-) diff --git a/include/net/cipso_ipv4.h b/include/net/cipso_ipv4.h index 4f90f5554fac..a6bb94530cfd 100644 --- a/include/net/cipso_ipv4.h +++ b/include/net/cipso_ipv4.h @@ -203,12 +203,10 @@ static inline int cipso_v4_cache_add(const struct sk_buff *skb, #ifdef CONFIG_NETLABEL 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_setattr(struct sock *sk, + 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, struct netlbl_lsm_secattr *secattr); int cipso_v4_validate(unsigned char **option); @@ -220,9 +218,9 @@ static inline void cipso_v4_error(struct sk_buff *skb, return; } -static inline int cipso_v4_socket_setattr(const struct socket *sock, - const struct cipso_v4_doi *doi_def, - const struct netlbl_lsm_secattr *secattr) +static inline int cipso_v4_sock_setattr(struct sock *sk, + const struct cipso_v4_doi *doi_def, + const struct netlbl_lsm_secattr *secattr) { return -ENOSYS; } @@ -233,12 +231,6 @@ static inline int cipso_v4_sock_getattr(struct sock *sk, return -ENOSYS; } -static inline int cipso_v4_socket_getattr(const struct socket *sock, - struct netlbl_lsm_secattr *secattr) -{ - return -ENOSYS; -} - static inline int cipso_v4_skbuff_getattr(const struct sk_buff *skb, struct netlbl_lsm_secattr *secattr) { diff --git a/include/net/netlabel.h b/include/net/netlabel.h index 83da7e1f0d3d..9b7d6f2ac9a3 100644 --- a/include/net/netlabel.h +++ b/include/net/netlabel.h @@ -332,17 +332,15 @@ static inline int netlbl_secattr_catmap_setrng( */ #ifdef CONFIG_NETLABEL -int netlbl_socket_setattr(const struct socket *sock, - const struct netlbl_lsm_secattr *secattr); +int netlbl_sock_setattr(struct sock *sk, + 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, struct netlbl_lsm_secattr *secattr); void netlbl_skbuff_err(struct sk_buff *skb, int error); #else -static inline int netlbl_socket_setattr(const struct socket *sock, +static inline int netlbl_sock_setattr(struct sock *sk, const struct netlbl_lsm_secattr *secattr) { return -ENOSYS; @@ -354,12 +352,6 @@ static inline int netlbl_sock_getattr(struct sock *sk, return -ENOSYS; } -static inline int netlbl_socket_getattr(const struct socket *sock, - struct netlbl_lsm_secattr *secattr) -{ - return -ENOSYS; -} - static inline int netlbl_skbuff_getattr(const struct sk_buff *skb, struct netlbl_lsm_secattr *secattr) { diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index 86a2b52aad38..fc839f9148ec 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c @@ -1709,22 +1709,22 @@ void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway) } /** - * cipso_v4_socket_setattr - Add a CIPSO option to a socket - * @sock: the socket + * cipso_v4_sock_setattr - Add a CIPSO option to a socket + * @sk: the socket * @doi_def: the CIPSO DOI to use * @secattr: the specific security attributes of the socket * * Description: * Set the CIPSO option on the given socket using the DOI definition and * security attributes passed to the function. This function requires - * exclusive access to @sock->sk, which means it either needs to be in the - * process of being created or locked via lock_sock(sock->sk). Returns zero on - * success and negative values on failure. + * exclusive access to @sk, which means it either needs to be in the + * process of being created or locked. Returns zero on success and negative + * values on failure. * */ -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_setattr(struct sock *sk, + const struct cipso_v4_doi *doi_def, + const struct netlbl_lsm_secattr *secattr) { int ret_val = -EPERM; u32 iter; @@ -1732,7 +1732,6 @@ int cipso_v4_socket_setattr(const struct socket *sock, u32 buf_len = 0; u32 opt_len; struct ip_options *opt = NULL; - struct sock *sk; struct inet_sock *sk_inet; struct inet_connection_sock *sk_conn; @@ -1740,7 +1739,6 @@ int cipso_v4_socket_setattr(const struct socket *sock, * defined yet but it is not a problem as the only users of these * "lite" PF_INET sockets are functions which do an accept() call * afterwards so we will label the socket as part of the accept(). */ - sk = sock->sk; if (sk == NULL) return 0; @@ -1891,29 +1889,6 @@ int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr) 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; -} - /** * cipso_v4_skbuff_getattr - Get the security attributes from the CIPSO option * @skb: the packet diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c index f2535e7f2869..b165712aaa70 100644 --- a/net/netlabel/netlabel_kapi.c +++ b/net/netlabel/netlabel_kapi.c @@ -246,19 +246,18 @@ int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap *catmap, /** * netlbl_socket_setattr - Label a socket using the correct protocol - * @sock: the socket to label + * @sk: the socket to label * @secattr: the security attributes * * Description: * Attach the correct label to the given socket using the security attributes - * specified in @secattr. This function requires exclusive access to - * @sock->sk, which means it either needs to be in the process of being - * created or locked via lock_sock(sock->sk). Returns zero on success, - * negative values on failure. + * specified in @secattr. This function requires exclusive access to @sk, + * which means it either needs to be in the process of being created or locked. + * Returns zero on success, negative values on failure. * */ -int netlbl_socket_setattr(const struct socket *sock, - const struct netlbl_lsm_secattr *secattr) +int netlbl_sock_setattr(struct sock *sk, + const struct netlbl_lsm_secattr *secattr) { int ret_val = -ENOENT; struct netlbl_dom_map *dom_entry; @@ -269,9 +268,9 @@ int netlbl_socket_setattr(const struct socket *sock, goto socket_setattr_return; switch (dom_entry->type) { case NETLBL_NLTYPE_CIPSOV4: - ret_val = cipso_v4_socket_setattr(sock, - dom_entry->type_def.cipsov4, - secattr); + ret_val = cipso_v4_sock_setattr(sk, + dom_entry->type_def.cipsov4, + secattr); break; case NETLBL_NLTYPE_UNLABELED: ret_val = 0; @@ -308,30 +307,6 @@ int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr) return netlbl_unlabel_getattr(secattr); } -/** - * netlbl_socket_getattr - Determine the security attributes of a socket - * @sock: the socket - * @secattr: the security attributes - * - * Description: - * Examines the given socket to see any NetLabel style labeling has been - * applied to the socket, if so it parses the socket label and returns the - * security attributes in @secattr. Returns zero on success, negative values - * on failure. - * - */ -int netlbl_socket_getattr(const struct socket *sock, - struct netlbl_lsm_secattr *secattr) -{ - int ret_val; - - ret_val = cipso_v4_socket_getattr(sock, secattr); - if (ret_val == 0) - return 0; - - return netlbl_unlabel_getattr(secattr); -} - /** * netlbl_skbuff_getattr - Determine the security attributes of a packet * @skb: the packet diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c index bf8750791dd1..e64eca246f1a 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c @@ -36,8 +36,8 @@ #include "security.h" /** - * selinux_netlbl_socket_setsid - Label a socket using the NetLabel mechanism - * @sock: the socket to label + * selinux_netlbl_sock_setsid - Label a socket using the NetLabel mechanism + * @sk: the socket to label * @sid: the SID to use * * Description: @@ -47,17 +47,17 @@ * this function and rcu_read_unlock() after this function returns. * */ -static int selinux_netlbl_socket_setsid(struct socket *sock, u32 sid) +static int selinux_netlbl_sock_setsid(struct sock *sk, u32 sid) { int rc; - struct sk_security_struct *sksec = sock->sk->sk_security; + struct sk_security_struct *sksec = sk->sk_security; struct netlbl_lsm_secattr secattr; rc = security_netlbl_sid_to_secattr(sid, &secattr); if (rc != 0) return rc; - rc = netlbl_socket_setattr(sock, &secattr); + rc = netlbl_sock_setattr(sk, &secattr); if (rc == 0) { spin_lock_bh(&sksec->nlbl_lock); sksec->nlbl_state = NLBL_LABELED; @@ -206,7 +206,7 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock) /* 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 * selinux_netlbl_inode_permission(). */ - selinux_netlbl_socket_setsid(sock, sksec->sid); + selinux_netlbl_sock_setsid(sk, sksec->sid); rcu_read_unlock(); } @@ -223,14 +223,15 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock) int selinux_netlbl_socket_post_create(struct socket *sock) { int rc = 0; + struct sock *sk = sock->sk; struct inode_security_struct *isec = SOCK_INODE(sock)->i_security; - struct sk_security_struct *sksec = sock->sk->sk_security; + struct sk_security_struct *sksec = sk->sk_security; sksec->sclass = isec->sclass; rcu_read_lock(); if (sksec->nlbl_state == NLBL_REQUIRE) - rc = selinux_netlbl_socket_setsid(sock, sksec->sid); + rc = selinux_netlbl_sock_setsid(sk, sksec->sid); rcu_read_unlock(); return rc; @@ -251,14 +252,16 @@ int selinux_netlbl_socket_post_create(struct socket *sock) int selinux_netlbl_inode_permission(struct inode *inode, int mask) { int rc; - struct sk_security_struct *sksec; + struct sock *sk; struct socket *sock; + struct sk_security_struct *sksec; if (!S_ISSOCK(inode->i_mode) || ((mask & (MAY_WRITE | MAY_APPEND)) == 0)) return 0; sock = SOCKET_I(inode); - sksec = sock->sk->sk_security; + sk = sock->sk; + sksec = sk->sk_security; rcu_read_lock(); if (sksec->nlbl_state != NLBL_REQUIRE) { @@ -266,9 +269,9 @@ int selinux_netlbl_inode_permission(struct inode *inode, int mask) return 0; } local_bh_disable(); - bh_lock_sock_nested(sock->sk); - rc = selinux_netlbl_socket_setsid(sock, sksec->sid); - bh_unlock_sock(sock->sk); + bh_lock_sock_nested(sk); + rc = selinux_netlbl_sock_setsid(sk, sksec->sid); + bh_unlock_sock(sk); local_bh_enable(); rcu_read_unlock(); @@ -345,14 +348,17 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock, int optname) { int rc = 0; - struct sk_security_struct *sksec = sock->sk->sk_security; + struct sock *sk = sock->sk; + struct sk_security_struct *sksec = sk->sk_security; struct netlbl_lsm_secattr secattr; rcu_read_lock(); if (level == IPPROTO_IP && optname == IP_OPTIONS && sksec->nlbl_state == NLBL_LABELED) { netlbl_secattr_init(&secattr); - rc = netlbl_socket_getattr(sock, &secattr); + lock_sock(sk); + rc = netlbl_sock_getattr(sk, &secattr); + release_sock(sk); if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE) rc = -EACCES; netlbl_secattr_destroy(&secattr); From 50e5d35ce2c4190cead13a091ea1ceab47d29cc2 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Thu, 7 Jun 2007 18:38:14 -0700 Subject: [PATCH 3/3] [CIPSO]: Fix several unaligned kernel accesses in the CIPSO engine. IPv4 options are not very well aligned within the packet and the format of a CIPSO option is even worse. The result is that the CIPSO engine in the kernel does a few unaligned accesses when parsing and validating incoming packets with CIPSO options attached which generate error messages on certain alignment sensitive platforms. This patch fixes this by marking these unaligned accesses with the get_unaliagned() macro. Signed-off-by: Paul Moore Acked-by: James Morris Signed-off-by: David S. Miller --- net/ipv4/cipso_ipv4.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index fc839f9148ec..ab56a052ce31 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c @@ -45,6 +45,7 @@ #include #include #include +#include struct cipso_v4_domhsh_entry { char *domain; @@ -1000,7 +1001,7 @@ static int cipso_v4_map_cat_enum_valid(const struct cipso_v4_doi *doi_def, return -EFAULT; for (iter = 0; iter < enumcat_len; iter += 2) { - cat = ntohs(*((__be16 *)&enumcat[iter])); + cat = ntohs(get_unaligned((__be16 *)&enumcat[iter])); if (cat <= cat_prev) return -EFAULT; cat_prev = cat; @@ -1068,8 +1069,8 @@ static int cipso_v4_map_cat_enum_ntoh(const struct cipso_v4_doi *doi_def, for (iter = 0; iter < net_cat_len; iter += 2) { ret_val = netlbl_secattr_catmap_setbit(secattr->mls_cat, - ntohs(*((__be16 *)&net_cat[iter])), - GFP_ATOMIC); + ntohs(get_unaligned((__be16 *)&net_cat[iter])), + GFP_ATOMIC); if (ret_val != 0) return ret_val; } @@ -1102,9 +1103,10 @@ static int cipso_v4_map_cat_rng_valid(const struct cipso_v4_doi *doi_def, return -EFAULT; for (iter = 0; iter < rngcat_len; iter += 4) { - cat_high = ntohs(*((__be16 *)&rngcat[iter])); + cat_high = ntohs(get_unaligned((__be16 *)&rngcat[iter])); if ((iter + 4) <= rngcat_len) - cat_low = ntohs(*((__be16 *)&rngcat[iter + 2])); + cat_low = ntohs( + get_unaligned((__be16 *)&rngcat[iter + 2])); else cat_low = 0; @@ -1201,9 +1203,10 @@ static int cipso_v4_map_cat_rng_ntoh(const struct cipso_v4_doi *doi_def, u16 cat_high; for (net_iter = 0; net_iter < net_cat_len; net_iter += 4) { - cat_high = ntohs(*((__be16 *)&net_cat[net_iter])); + cat_high = ntohs(get_unaligned((__be16 *)&net_cat[net_iter])); if ((net_iter + 4) <= net_cat_len) - cat_low = ntohs(*((__be16 *)&net_cat[net_iter + 2])); + cat_low = ntohs( + get_unaligned((__be16 *)&net_cat[net_iter + 2])); else cat_low = 0; @@ -1565,7 +1568,7 @@ int cipso_v4_validate(unsigned char **option) } rcu_read_lock(); - doi_def = cipso_v4_doi_search(ntohl(*((__be32 *)&opt[2]))); + doi_def = cipso_v4_doi_search(ntohl(get_unaligned((__be32 *)&opt[2]))); if (doi_def == NULL) { err_offset = 2; goto validate_return_locked; @@ -1856,7 +1859,7 @@ int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr) if (ret_val == 0) return ret_val; - doi = ntohl(*(__be32 *)&cipso_ptr[2]); + doi = ntohl(get_unaligned((__be32 *)&cipso_ptr[2])); rcu_read_lock(); doi_def = cipso_v4_doi_search(doi); if (doi_def == NULL) { @@ -1911,7 +1914,7 @@ int cipso_v4_skbuff_getattr(const struct sk_buff *skb, if (cipso_v4_cache_check(cipso_ptr, cipso_ptr[1], secattr) == 0) return 0; - doi = ntohl(*(__be32 *)&cipso_ptr[2]); + doi = ntohl(get_unaligned((__be32 *)&cipso_ptr[2])); rcu_read_lock(); doi_def = cipso_v4_doi_search(doi); if (doi_def == NULL)