aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux
diff options
context:
space:
mode:
Diffstat (limited to 'security/selinux')
-rw-r--r--security/selinux/hooks.c54
-rw-r--r--security/selinux/include/netlabel.h27
-rw-r--r--security/selinux/netlabel.c186
3 files changed, 81 insertions, 186 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 7c52ba243c64..ee2e781d11d7 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -311,7 +311,7 @@ static int sk_alloc_security(struct sock *sk, int family, gfp_t priority)
311 ssec->sid = SECINITSID_UNLABELED; 311 ssec->sid = SECINITSID_UNLABELED;
312 sk->sk_security = ssec; 312 sk->sk_security = ssec;
313 313
314 selinux_netlbl_sk_security_reset(ssec, family); 314 selinux_netlbl_sk_security_reset(ssec);
315 315
316 return 0; 316 return 0;
317} 317}
@@ -2945,7 +2945,6 @@ static void selinux_inode_getsecid(const struct inode *inode, u32 *secid)
2945static int selinux_revalidate_file_permission(struct file *file, int mask) 2945static int selinux_revalidate_file_permission(struct file *file, int mask)
2946{ 2946{
2947 const struct cred *cred = current_cred(); 2947 const struct cred *cred = current_cred();
2948 int rc;
2949 struct inode *inode = file->f_path.dentry->d_inode; 2948 struct inode *inode = file->f_path.dentry->d_inode;
2950 2949
2951 if (!mask) { 2950 if (!mask) {
@@ -2957,29 +2956,15 @@ static int selinux_revalidate_file_permission(struct file *file, int mask)
2957 if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE)) 2956 if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE))
2958 mask |= MAY_APPEND; 2957 mask |= MAY_APPEND;
2959 2958
2960 rc = file_has_perm(cred, file, 2959 return file_has_perm(cred, file,
2961 file_mask_to_av(inode->i_mode, mask)); 2960 file_mask_to_av(inode->i_mode, mask));
2962 if (rc)
2963 return rc;
2964
2965 return selinux_netlbl_inode_permission(inode, mask);
2966} 2961}
2967 2962
2968static int selinux_file_permission(struct file *file, int mask) 2963static int selinux_file_permission(struct file *file, int mask)
2969{ 2964{
2970 struct inode *inode = file->f_path.dentry->d_inode; 2965 if (!mask)
2971 struct file_security_struct *fsec = file->f_security;
2972 struct inode_security_struct *isec = inode->i_security;
2973 u32 sid = current_sid();
2974
2975 if (!mask) {
2976 /* No permission to check. Existence test. */ 2966 /* No permission to check. Existence test. */
2977 return 0; 2967 return 0;
2978 }
2979
2980 if (sid == fsec->sid && fsec->isid == isec->sid
2981 && fsec->pseqno == avc_policy_seqno())
2982 return selinux_netlbl_inode_permission(inode, mask);
2983 2968
2984 return selinux_revalidate_file_permission(file, mask); 2969 return selinux_revalidate_file_permission(file, mask);
2985} 2970}
@@ -3723,7 +3708,7 @@ static int selinux_socket_post_create(struct socket *sock, int family,
3723 sksec = sock->sk->sk_security; 3708 sksec = sock->sk->sk_security;
3724 sksec->sid = isec->sid; 3709 sksec->sid = isec->sid;
3725 sksec->sclass = isec->sclass; 3710 sksec->sclass = isec->sclass;
3726 err = selinux_netlbl_socket_post_create(sock); 3711 err = selinux_netlbl_socket_post_create(sock->sk, family);
3727 } 3712 }
3728 3713
3729 return err; 3714 return err;
@@ -3914,13 +3899,7 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
3914static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg, 3899static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
3915 int size) 3900 int size)
3916{ 3901{
3917 int rc; 3902 return socket_has_perm(current, sock, SOCKET__WRITE);
3918
3919 rc = socket_has_perm(current, sock, SOCKET__WRITE);
3920 if (rc)
3921 return rc;
3922
3923 return selinux_netlbl_inode_permission(SOCK_INODE(sock), MAY_WRITE);
3924} 3903}
3925 3904
3926static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg, 3905static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
@@ -4304,7 +4283,7 @@ static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
4304 newssec->peer_sid = ssec->peer_sid; 4283 newssec->peer_sid = ssec->peer_sid;
4305 newssec->sclass = ssec->sclass; 4284 newssec->sclass = ssec->sclass;
4306 4285
4307 selinux_netlbl_sk_security_reset(newssec, newsk->sk_family); 4286 selinux_netlbl_sk_security_reset(newssec);
4308} 4287}
4309 4288
4310static void selinux_sk_getsecid(struct sock *sk, u32 *secid) 4289static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
@@ -4348,16 +4327,15 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
4348 if (peersid == SECSID_NULL) { 4327 if (peersid == SECSID_NULL) {
4349 req->secid = sksec->sid; 4328 req->secid = sksec->sid;
4350 req->peer_secid = SECSID_NULL; 4329 req->peer_secid = SECSID_NULL;
4351 return 0; 4330 } else {
4331 err = security_sid_mls_copy(sksec->sid, peersid, &newsid);
4332 if (err)
4333 return err;
4334 req->secid = newsid;
4335 req->peer_secid = peersid;
4352 } 4336 }
4353 4337
4354 err = security_sid_mls_copy(sksec->sid, peersid, &newsid); 4338 return selinux_netlbl_inet_conn_request(req, family);
4355 if (err)
4356 return err;
4357
4358 req->secid = newsid;
4359 req->peer_secid = peersid;
4360 return 0;
4361} 4339}
4362 4340
4363static void selinux_inet_csk_clone(struct sock *newsk, 4341static void selinux_inet_csk_clone(struct sock *newsk,
@@ -4374,7 +4352,7 @@ static void selinux_inet_csk_clone(struct sock *newsk,
4374 4352
4375 /* We don't need to take any sort of lock here as we are the only 4353 /* We don't need to take any sort of lock here as we are the only
4376 * thread with access to newsksec */ 4354 * thread with access to newsksec */
4377 selinux_netlbl_sk_security_reset(newsksec, req->rsk_ops->family); 4355 selinux_netlbl_inet_csk_clone(newsk, req->rsk_ops->family);
4378} 4356}
4379 4357
4380static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb) 4358static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
@@ -4387,8 +4365,6 @@ static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
4387 family = PF_INET; 4365 family = PF_INET;
4388 4366
4389 selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid); 4367 selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid);
4390
4391 selinux_netlbl_inet_conn_established(sk, family);
4392} 4368}
4393 4369
4394static void selinux_req_classify_flow(const struct request_sock *req, 4370static void selinux_req_classify_flow(const struct request_sock *req,
diff --git a/security/selinux/include/netlabel.h b/security/selinux/include/netlabel.h
index b913c8d06038..b4b5b9b2f0be 100644
--- a/security/selinux/include/netlabel.h
+++ b/security/selinux/include/netlabel.h
@@ -32,6 +32,7 @@
32#include <linux/net.h> 32#include <linux/net.h>
33#include <linux/skbuff.h> 33#include <linux/skbuff.h>
34#include <net/sock.h> 34#include <net/sock.h>
35#include <net/request_sock.h>
35 36
36#include "avc.h" 37#include "avc.h"
37#include "objsec.h" 38#include "objsec.h"
@@ -42,8 +43,7 @@ void selinux_netlbl_cache_invalidate(void);
42void selinux_netlbl_err(struct sk_buff *skb, int error, int gateway); 43void selinux_netlbl_err(struct sk_buff *skb, int error, int gateway);
43 44
44void selinux_netlbl_sk_security_free(struct sk_security_struct *ssec); 45void selinux_netlbl_sk_security_free(struct sk_security_struct *ssec);
45void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec, 46void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec);
46 int family);
47 47
48int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, 48int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
49 u16 family, 49 u16 family,
@@ -53,9 +53,9 @@ int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
53 u16 family, 53 u16 family,
54 u32 sid); 54 u32 sid);
55 55
56void selinux_netlbl_inet_conn_established(struct sock *sk, u16 family); 56int selinux_netlbl_inet_conn_request(struct request_sock *req, u16 family);
57int selinux_netlbl_socket_post_create(struct socket *sock); 57void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family);
58int selinux_netlbl_inode_permission(struct inode *inode, int mask); 58int selinux_netlbl_socket_post_create(struct sock *sk, u16 family);
59int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, 59int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
60 struct sk_buff *skb, 60 struct sk_buff *skb,
61 u16 family, 61 u16 family,
@@ -85,8 +85,7 @@ static inline void selinux_netlbl_sk_security_free(
85} 85}
86 86
87static inline void selinux_netlbl_sk_security_reset( 87static inline void selinux_netlbl_sk_security_reset(
88 struct sk_security_struct *ssec, 88 struct sk_security_struct *ssec)
89 int family)
90{ 89{
91 return; 90 return;
92} 91}
@@ -113,17 +112,17 @@ static inline int selinux_netlbl_conn_setsid(struct sock *sk,
113 return 0; 112 return 0;
114} 113}
115 114
116static inline void selinux_netlbl_inet_conn_established(struct sock *sk, 115static inline int selinux_netlbl_inet_conn_request(struct request_sock *req,
117 u16 family) 116 u16 family)
118{ 117{
119 return; 118 return 0;
120} 119}
121static inline int selinux_netlbl_socket_post_create(struct socket *sock) 120static inline void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family)
122{ 121{
123 return 0; 122 return;
124} 123}
125static inline int selinux_netlbl_inode_permission(struct inode *inode, 124static inline int selinux_netlbl_socket_post_create(struct sock *sk,
126 int mask) 125 u16 family)
127{ 126{
128 return 0; 127 return 0;
129} 128}
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c
index 350794ab9b42..2e984413c7b2 100644
--- a/security/selinux/netlabel.c
+++ b/security/selinux/netlabel.c
@@ -100,41 +100,6 @@ static struct netlbl_lsm_secattr *selinux_netlbl_sock_genattr(struct sock *sk)
100} 100}
101 101
102/** 102/**
103 * selinux_netlbl_sock_setsid - Label a socket using the NetLabel mechanism
104 * @sk: the socket to label
105 *
106 * Description:
107 * Attempt to label a socket using the NetLabel mechanism. Returns zero values
108 * on success, negative values on failure.
109 *
110 */
111static int selinux_netlbl_sock_setsid(struct sock *sk)
112{
113 int rc;
114 struct sk_security_struct *sksec = sk->sk_security;
115 struct netlbl_lsm_secattr *secattr;
116
117 if (sksec->nlbl_state != NLBL_REQUIRE)
118 return 0;
119
120 secattr = selinux_netlbl_sock_genattr(sk);
121 if (secattr == NULL)
122 return -ENOMEM;
123 rc = netlbl_sock_setattr(sk, secattr);
124 switch (rc) {
125 case 0:
126 sksec->nlbl_state = NLBL_LABELED;
127 break;
128 case -EDESTADDRREQ:
129 sksec->nlbl_state = NLBL_REQSKB;
130 rc = 0;
131 break;
132 }
133
134 return rc;
135}
136
137/**
138 * selinux_netlbl_cache_invalidate - Invalidate the NetLabel cache 103 * selinux_netlbl_cache_invalidate - Invalidate the NetLabel cache
139 * 104 *
140 * Description: 105 * Description:
@@ -188,13 +153,9 @@ void selinux_netlbl_sk_security_free(struct sk_security_struct *ssec)
188 * The caller is responsibile for all the NetLabel sk_security_struct locking. 153 * The caller is responsibile for all the NetLabel sk_security_struct locking.
189 * 154 *
190 */ 155 */
191void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec, 156void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec)
192 int family)
193{ 157{
194 if (family == PF_INET) 158 ssec->nlbl_state = NLBL_UNSET;
195 ssec->nlbl_state = NLBL_REQUIRE;
196 else
197 ssec->nlbl_state = NLBL_UNSET;
198} 159}
199 160
200/** 161/**
@@ -281,127 +242,86 @@ skbuff_setsid_return:
281} 242}
282 243
283/** 244/**
284 * selinux_netlbl_inet_conn_established - Netlabel the newly accepted connection 245 * selinux_netlbl_inet_conn_request - Label an incoming stream connection
285 * @sk: the new connection 246 * @req: incoming connection request socket
286 * 247 *
287 * Description: 248 * Description:
288 * A new connection has been established on @sk so make sure it is labeled 249 * A new incoming connection request is represented by @req, we need to label
289 * correctly with the NetLabel susbsystem. 250 * the new request_sock here and the stack will ensure the on-the-wire label
251 * will get preserved when a full sock is created once the connection handshake
252 * is complete. Returns zero on success, negative values on failure.
290 * 253 *
291 */ 254 */
292void selinux_netlbl_inet_conn_established(struct sock *sk, u16 family) 255int selinux_netlbl_inet_conn_request(struct request_sock *req, u16 family)
293{ 256{
294 int rc; 257 int rc;
295 struct sk_security_struct *sksec = sk->sk_security; 258 struct netlbl_lsm_secattr secattr;
296 struct netlbl_lsm_secattr *secattr;
297 struct inet_sock *sk_inet = inet_sk(sk);
298 struct sockaddr_in addr;
299
300 if (sksec->nlbl_state != NLBL_REQUIRE)
301 return;
302 259
303 secattr = selinux_netlbl_sock_genattr(sk); 260 if (family != PF_INET)
304 if (secattr == NULL) 261 return 0;
305 return;
306 262
307 rc = netlbl_sock_setattr(sk, secattr); 263 netlbl_secattr_init(&secattr);
308 switch (rc) { 264 rc = security_netlbl_sid_to_secattr(req->secid, &secattr);
309 case 0: 265 if (rc != 0)
310 sksec->nlbl_state = NLBL_LABELED; 266 goto inet_conn_request_return;
311 break; 267 rc = netlbl_req_setattr(req, &secattr);
312 case -EDESTADDRREQ: 268inet_conn_request_return:
313 /* no PF_INET6 support yet because we don't support any IPv6 269 netlbl_secattr_destroy(&secattr);
314 * labeling protocols */ 270 return rc;
315 if (family != PF_INET) {
316 sksec->nlbl_state = NLBL_UNSET;
317 return;
318 }
319
320 addr.sin_family = family;
321 addr.sin_addr.s_addr = sk_inet->daddr;
322 if (netlbl_conn_setattr(sk, (struct sockaddr *)&addr,
323 secattr) != 0) {
324 /* we failed to label the connected socket (could be
325 * for a variety of reasons, the actual "why" isn't
326 * important here) so we have to go to our backup plan,
327 * labeling the packets individually in the netfilter
328 * local output hook. this is okay but we need to
329 * adjust the MSS of the connection to take into
330 * account any labeling overhead, since we don't know
331 * the exact overhead at this point we'll use the worst
332 * case value which is 40 bytes for IPv4 */
333 struct inet_connection_sock *sk_conn = inet_csk(sk);
334 sk_conn->icsk_ext_hdr_len += 40 -
335 (sk_inet->opt ? sk_inet->opt->optlen : 0);
336 sk_conn->icsk_sync_mss(sk, sk_conn->icsk_pmtu_cookie);
337
338 sksec->nlbl_state = NLBL_REQSKB;
339 } else
340 sksec->nlbl_state = NLBL_CONNLABELED;
341 break;
342 default:
343 /* note that we are failing to label the socket which could be
344 * a bad thing since it means traffic could leave the system
345 * without the desired labeling, however, all is not lost as
346 * we have a check in selinux_netlbl_inode_permission() to
347 * pick up the pieces that we might drop here because we can't
348 * return an error code */
349 break;
350 }
351} 271}
352 272
353/** 273/**
354 * selinux_netlbl_socket_post_create - Label a socket using NetLabel 274 * selinux_netlbl_inet_csk_clone - Initialize the newly created sock
355 * @sock: the socket to label 275 * @sk: the new sock
356 * 276 *
357 * Description: 277 * Description:
358 * Attempt to label a socket using the NetLabel mechanism using the given 278 * A new connection has been established using @sk, we've already labeled the
359 * SID. Returns zero values on success, negative values on failure. 279 * socket via the request_sock struct in selinux_netlbl_inet_conn_request() but
280 * we need to set the NetLabel state here since we now have a sock structure.
360 * 281 *
361 */ 282 */
362int selinux_netlbl_socket_post_create(struct socket *sock) 283void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family)
363{ 284{
364 return selinux_netlbl_sock_setsid(sock->sk); 285 struct sk_security_struct *sksec = sk->sk_security;
286
287 if (family == PF_INET)
288 sksec->nlbl_state = NLBL_LABELED;
289 else
290 sksec->nlbl_state = NLBL_UNSET;
365} 291}
366 292
367/** 293/**
368 * selinux_netlbl_inode_permission - Verify the socket is NetLabel labeled 294 * selinux_netlbl_socket_post_create - Label a socket using NetLabel
369 * @inode: the file descriptor's inode 295 * @sock: the socket to label
370 * @mask: the permission mask 296 * @family: protocol family
371 * 297 *
372 * Description: 298 * Description:
373 * Looks at a file's inode and if it is marked as a socket protected by 299 * Attempt to label a socket using the NetLabel mechanism using the given
374 * NetLabel then verify that the socket has been labeled, if not try to label 300 * SID. Returns zero values on success, negative values on failure.
375 * the socket now with the inode's SID. Returns zero on success, negative
376 * values on failure.
377 * 301 *
378 */ 302 */
379int selinux_netlbl_inode_permission(struct inode *inode, int mask) 303int selinux_netlbl_socket_post_create(struct sock *sk, u16 family)
380{ 304{
381 int rc; 305 int rc;
382 struct sock *sk; 306 struct sk_security_struct *sksec = sk->sk_security;
383 struct socket *sock; 307 struct netlbl_lsm_secattr *secattr;
384 struct sk_security_struct *sksec;
385 308
386 if (!S_ISSOCK(inode->i_mode) || 309 if (family != PF_INET)
387 ((mask & (MAY_WRITE | MAY_APPEND)) == 0))
388 return 0;
389 sock = SOCKET_I(inode);
390 sk = sock->sk;
391 if (sk == NULL)
392 return 0;
393 sksec = sk->sk_security;
394 if (sksec == NULL || sksec->nlbl_state != NLBL_REQUIRE)
395 return 0; 310 return 0;
396 311
397 local_bh_disable(); 312 secattr = selinux_netlbl_sock_genattr(sk);
398 bh_lock_sock_nested(sk); 313 if (secattr == NULL)
399 if (likely(sksec->nlbl_state == NLBL_REQUIRE)) 314 return -ENOMEM;
400 rc = selinux_netlbl_sock_setsid(sk); 315 rc = netlbl_sock_setattr(sk, family, secattr);
401 else 316 switch (rc) {
317 case 0:
318 sksec->nlbl_state = NLBL_LABELED;
319 break;
320 case -EDESTADDRREQ:
321 sksec->nlbl_state = NLBL_REQSKB;
402 rc = 0; 322 rc = 0;
403 bh_unlock_sock(sk); 323 break;
404 local_bh_enable(); 324 }
405 325
406 return rc; 326 return rc;
407} 327}