diff options
Diffstat (limited to 'security')
-rw-r--r-- | security/selinux/hooks.c | 8 | ||||
-rw-r--r-- | security/selinux/include/selinux_netlabel.h | 10 | ||||
-rw-r--r-- | security/selinux/ss/services.c | 37 |
3 files changed, 54 insertions, 1 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index e9969a2fc846..8ab5679a37a3 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -3313,7 +3313,13 @@ static int selinux_socket_getpeername(struct socket *sock) | |||
3313 | 3313 | ||
3314 | static int selinux_socket_setsockopt(struct socket *sock,int level,int optname) | 3314 | static int selinux_socket_setsockopt(struct socket *sock,int level,int optname) |
3315 | { | 3315 | { |
3316 | return socket_has_perm(current, sock, SOCKET__SETOPT); | 3316 | int err; |
3317 | |||
3318 | err = socket_has_perm(current, sock, SOCKET__SETOPT); | ||
3319 | if (err) | ||
3320 | return err; | ||
3321 | |||
3322 | return selinux_netlbl_socket_setsockopt(sock, level, optname); | ||
3317 | } | 3323 | } |
3318 | 3324 | ||
3319 | static int selinux_socket_getsockopt(struct socket *sock, int level, | 3325 | static int selinux_socket_getsockopt(struct socket *sock, int level, |
diff --git a/security/selinux/include/selinux_netlabel.h b/security/selinux/include/selinux_netlabel.h index ecab4bddaaf4..9de10cc2cef2 100644 --- a/security/selinux/include/selinux_netlabel.h +++ b/security/selinux/include/selinux_netlabel.h | |||
@@ -53,6 +53,9 @@ void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec, | |||
53 | void selinux_netlbl_sk_clone_security(struct sk_security_struct *ssec, | 53 | void selinux_netlbl_sk_clone_security(struct sk_security_struct *ssec, |
54 | struct sk_security_struct *newssec); | 54 | struct sk_security_struct *newssec); |
55 | int selinux_netlbl_inode_permission(struct inode *inode, int mask); | 55 | int selinux_netlbl_inode_permission(struct inode *inode, int mask); |
56 | int selinux_netlbl_socket_setsockopt(struct socket *sock, | ||
57 | int level, | ||
58 | int optname); | ||
56 | #else | 59 | #else |
57 | static inline void selinux_netlbl_cache_invalidate(void) | 60 | static inline void selinux_netlbl_cache_invalidate(void) |
58 | { | 61 | { |
@@ -114,6 +117,13 @@ static inline int selinux_netlbl_inode_permission(struct inode *inode, | |||
114 | { | 117 | { |
115 | return 0; | 118 | return 0; |
116 | } | 119 | } |
120 | |||
121 | static inline int selinux_netlbl_socket_setsockopt(struct socket *sock, | ||
122 | int level, | ||
123 | int optname) | ||
124 | { | ||
125 | return 0; | ||
126 | } | ||
117 | #endif /* CONFIG_NETLABEL */ | 127 | #endif /* CONFIG_NETLABEL */ |
118 | 128 | ||
119 | #endif | 129 | #endif |
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index b1f6fb36c699..bfe122764c98 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
@@ -2682,4 +2682,41 @@ u32 selinux_netlbl_socket_getpeersec_dgram(struct sk_buff *skb) | |||
2682 | 2682 | ||
2683 | return peer_sid; | 2683 | return peer_sid; |
2684 | } | 2684 | } |
2685 | |||
2686 | /** | ||
2687 | * selinux_netlbl_socket_setsockopt - Do not allow users to remove a NetLabel | ||
2688 | * @sock: the socket | ||
2689 | * @level: the socket level or protocol | ||
2690 | * @optname: the socket option name | ||
2691 | * | ||
2692 | * Description: | ||
2693 | * Check the setsockopt() call and if the user is trying to replace the IP | ||
2694 | * options on a socket and a NetLabel is in place for the socket deny the | ||
2695 | * access; otherwise allow the access. Returns zero when the access is | ||
2696 | * allowed, -EACCES when denied, and other negative values on error. | ||
2697 | * | ||
2698 | */ | ||
2699 | int selinux_netlbl_socket_setsockopt(struct socket *sock, | ||
2700 | int level, | ||
2701 | int optname) | ||
2702 | { | ||
2703 | int rc = 0; | ||
2704 | struct inode *inode = SOCK_INODE(sock); | ||
2705 | struct sk_security_struct *sksec = sock->sk->sk_security; | ||
2706 | struct inode_security_struct *isec = inode->i_security; | ||
2707 | struct netlbl_lsm_secattr secattr; | ||
2708 | |||
2709 | mutex_lock(&isec->lock); | ||
2710 | if (level == IPPROTO_IP && optname == IP_OPTIONS && | ||
2711 | sksec->nlbl_state == NLBL_LABELED) { | ||
2712 | netlbl_secattr_init(&secattr); | ||
2713 | rc = netlbl_socket_getattr(sock, &secattr); | ||
2714 | if (rc == 0 && (secattr.cache || secattr.mls_lvl_vld)) | ||
2715 | rc = -EACCES; | ||
2716 | netlbl_secattr_destroy(&secattr); | ||
2717 | } | ||
2718 | mutex_unlock(&isec->lock); | ||
2719 | |||
2720 | return rc; | ||
2721 | } | ||
2685 | #endif /* CONFIG_NETLABEL */ | 2722 | #endif /* CONFIG_NETLABEL */ |