aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux
diff options
context:
space:
mode:
authorJames Morris <james.l.morris@oracle.com>2016-07-06 20:15:34 -0400
committerJames Morris <james.l.morris@oracle.com>2016-07-06 20:15:34 -0400
commitd011a4d861ce583466a8ae72a0c8e7f51c8cba4e (patch)
tree1ff8dfe7d486f5648e69ee85e54cde1987d8296a /security/selinux
parent544e1cea03e6674e3c12a3b8e8cc507c3dbeaf0c (diff)
parent3f09354ac84c6904787189d85fb306bf60f714b8 (diff)
Merge branch 'stable-4.8' of git://git.infradead.org/users/pcmoore/selinux into next
Diffstat (limited to 'security/selinux')
-rw-r--r--security/selinux/hooks.c21
-rw-r--r--security/selinux/include/netlabel.h4
-rw-r--r--security/selinux/netlabel.c36
-rw-r--r--security/selinux/selinuxfs.c2
-rw-r--r--security/selinux/ss/ebitmap.c2
-rw-r--r--security/selinux/ss/services.c70
6 files changed, 72 insertions, 63 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index a86d537eb79b..da934342a39f 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -4604,13 +4604,13 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
4604 err = selinux_inet_sys_rcv_skb(sock_net(sk), skb->skb_iif, 4604 err = selinux_inet_sys_rcv_skb(sock_net(sk), skb->skb_iif,
4605 addrp, family, peer_sid, &ad); 4605 addrp, family, peer_sid, &ad);
4606 if (err) { 4606 if (err) {
4607 selinux_netlbl_err(skb, err, 0); 4607 selinux_netlbl_err(skb, family, err, 0);
4608 return err; 4608 return err;
4609 } 4609 }
4610 err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER, 4610 err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
4611 PEER__RECV, &ad); 4611 PEER__RECV, &ad);
4612 if (err) { 4612 if (err) {
4613 selinux_netlbl_err(skb, err, 0); 4613 selinux_netlbl_err(skb, family, err, 0);
4614 return err; 4614 return err;
4615 } 4615 }
4616 } 4616 }
@@ -4978,7 +4978,7 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb,
4978 err = selinux_inet_sys_rcv_skb(dev_net(indev), indev->ifindex, 4978 err = selinux_inet_sys_rcv_skb(dev_net(indev), indev->ifindex,
4979 addrp, family, peer_sid, &ad); 4979 addrp, family, peer_sid, &ad);
4980 if (err) { 4980 if (err) {
4981 selinux_netlbl_err(skb, err, 1); 4981 selinux_netlbl_err(skb, family, err, 1);
4982 return NF_DROP; 4982 return NF_DROP;
4983 } 4983 }
4984 } 4984 }
@@ -5064,6 +5064,15 @@ static unsigned int selinux_ipv4_output(void *priv,
5064 return selinux_ip_output(skb, PF_INET); 5064 return selinux_ip_output(skb, PF_INET);
5065} 5065}
5066 5066
5067#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
5068static unsigned int selinux_ipv6_output(void *priv,
5069 struct sk_buff *skb,
5070 const struct nf_hook_state *state)
5071{
5072 return selinux_ip_output(skb, PF_INET6);
5073}
5074#endif /* IPV6 */
5075
5067static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, 5076static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
5068 int ifindex, 5077 int ifindex,
5069 u16 family) 5078 u16 family)
@@ -6298,6 +6307,12 @@ static struct nf_hook_ops selinux_nf_ops[] = {
6298 .hooknum = NF_INET_FORWARD, 6307 .hooknum = NF_INET_FORWARD,
6299 .priority = NF_IP6_PRI_SELINUX_FIRST, 6308 .priority = NF_IP6_PRI_SELINUX_FIRST,
6300 }, 6309 },
6310 {
6311 .hook = selinux_ipv6_output,
6312 .pf = NFPROTO_IPV6,
6313 .hooknum = NF_INET_LOCAL_OUT,
6314 .priority = NF_IP6_PRI_SELINUX_FIRST,
6315 },
6301#endif /* IPV6 */ 6316#endif /* IPV6 */
6302}; 6317};
6303 6318
diff --git a/security/selinux/include/netlabel.h b/security/selinux/include/netlabel.h
index 8c59b8f150e8..75686d53df07 100644
--- a/security/selinux/include/netlabel.h
+++ b/security/selinux/include/netlabel.h
@@ -40,7 +40,8 @@
40#ifdef CONFIG_NETLABEL 40#ifdef CONFIG_NETLABEL
41void selinux_netlbl_cache_invalidate(void); 41void selinux_netlbl_cache_invalidate(void);
42 42
43void selinux_netlbl_err(struct sk_buff *skb, int error, int gateway); 43void selinux_netlbl_err(struct sk_buff *skb, u16 family, int error,
44 int gateway);
44 45
45void selinux_netlbl_sk_security_free(struct sk_security_struct *sksec); 46void selinux_netlbl_sk_security_free(struct sk_security_struct *sksec);
46void selinux_netlbl_sk_security_reset(struct sk_security_struct *sksec); 47void selinux_netlbl_sk_security_reset(struct sk_security_struct *sksec);
@@ -72,6 +73,7 @@ static inline void selinux_netlbl_cache_invalidate(void)
72} 73}
73 74
74static inline void selinux_netlbl_err(struct sk_buff *skb, 75static inline void selinux_netlbl_err(struct sk_buff *skb,
76 u16 family,
75 int error, 77 int error,
76 int gateway) 78 int gateway)
77{ 79{
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c
index 1f989a539fd4..aaba6677ee2e 100644
--- a/security/selinux/netlabel.c
+++ b/security/selinux/netlabel.c
@@ -54,6 +54,7 @@
54 * 54 *
55 */ 55 */
56static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb, 56static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb,
57 u16 family,
57 struct netlbl_lsm_secattr *secattr, 58 struct netlbl_lsm_secattr *secattr,
58 u32 *sid) 59 u32 *sid)
59{ 60{
@@ -63,7 +64,7 @@ static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb,
63 if (rc == 0 && 64 if (rc == 0 &&
64 (secattr->flags & NETLBL_SECATTR_CACHEABLE) && 65 (secattr->flags & NETLBL_SECATTR_CACHEABLE) &&
65 (secattr->flags & NETLBL_SECATTR_CACHE)) 66 (secattr->flags & NETLBL_SECATTR_CACHE))
66 netlbl_cache_add(skb, secattr); 67 netlbl_cache_add(skb, family, secattr);
67 68
68 return rc; 69 return rc;
69} 70}
@@ -151,9 +152,9 @@ void selinux_netlbl_cache_invalidate(void)
151 * present on the packet, NetLabel is smart enough to only act when it should. 152 * present on the packet, NetLabel is smart enough to only act when it should.
152 * 153 *
153 */ 154 */
154void selinux_netlbl_err(struct sk_buff *skb, int error, int gateway) 155void selinux_netlbl_err(struct sk_buff *skb, u16 family, int error, int gateway)
155{ 156{
156 netlbl_skbuff_err(skb, error, gateway); 157 netlbl_skbuff_err(skb, family, error, gateway);
157} 158}
158 159
159/** 160/**
@@ -214,7 +215,8 @@ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
214 netlbl_secattr_init(&secattr); 215 netlbl_secattr_init(&secattr);
215 rc = netlbl_skbuff_getattr(skb, family, &secattr); 216 rc = netlbl_skbuff_getattr(skb, family, &secattr);
216 if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE) 217 if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE)
217 rc = selinux_netlbl_sidlookup_cached(skb, &secattr, sid); 218 rc = selinux_netlbl_sidlookup_cached(skb, family,
219 &secattr, sid);
218 else 220 else
219 *sid = SECSID_NULL; 221 *sid = SECSID_NULL;
220 *type = secattr.type; 222 *type = secattr.type;
@@ -284,7 +286,7 @@ int selinux_netlbl_inet_conn_request(struct request_sock *req, u16 family)
284 int rc; 286 int rc;
285 struct netlbl_lsm_secattr secattr; 287 struct netlbl_lsm_secattr secattr;
286 288
287 if (family != PF_INET) 289 if (family != PF_INET && family != PF_INET6)
288 return 0; 290 return 0;
289 291
290 netlbl_secattr_init(&secattr); 292 netlbl_secattr_init(&secattr);
@@ -333,7 +335,7 @@ int selinux_netlbl_socket_post_create(struct sock *sk, u16 family)
333 struct sk_security_struct *sksec = sk->sk_security; 335 struct sk_security_struct *sksec = sk->sk_security;
334 struct netlbl_lsm_secattr *secattr; 336 struct netlbl_lsm_secattr *secattr;
335 337
336 if (family != PF_INET) 338 if (family != PF_INET && family != PF_INET6)
337 return 0; 339 return 0;
338 340
339 secattr = selinux_netlbl_sock_genattr(sk); 341 secattr = selinux_netlbl_sock_genattr(sk);
@@ -382,7 +384,8 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
382 netlbl_secattr_init(&secattr); 384 netlbl_secattr_init(&secattr);
383 rc = netlbl_skbuff_getattr(skb, family, &secattr); 385 rc = netlbl_skbuff_getattr(skb, family, &secattr);
384 if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE) 386 if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE)
385 rc = selinux_netlbl_sidlookup_cached(skb, &secattr, &nlbl_sid); 387 rc = selinux_netlbl_sidlookup_cached(skb, family,
388 &secattr, &nlbl_sid);
386 else 389 else
387 nlbl_sid = SECINITSID_UNLABELED; 390 nlbl_sid = SECINITSID_UNLABELED;
388 netlbl_secattr_destroy(&secattr); 391 netlbl_secattr_destroy(&secattr);
@@ -405,11 +408,26 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
405 return 0; 408 return 0;
406 409
407 if (nlbl_sid != SECINITSID_UNLABELED) 410 if (nlbl_sid != SECINITSID_UNLABELED)
408 netlbl_skbuff_err(skb, rc, 0); 411 netlbl_skbuff_err(skb, family, rc, 0);
409 return rc; 412 return rc;
410} 413}
411 414
412/** 415/**
416 * selinux_netlbl_option - Is this a NetLabel option
417 * @level: the socket level or protocol
418 * @optname: the socket option name
419 *
420 * Description:
421 * Returns true if @level and @optname refer to a NetLabel option.
422 * Helper for selinux_netlbl_socket_setsockopt().
423 */
424static inline int selinux_netlbl_option(int level, int optname)
425{
426 return (level == IPPROTO_IP && optname == IP_OPTIONS) ||
427 (level == IPPROTO_IPV6 && optname == IPV6_HOPOPTS);
428}
429
430/**
413 * selinux_netlbl_socket_setsockopt - Do not allow users to remove a NetLabel 431 * selinux_netlbl_socket_setsockopt - Do not allow users to remove a NetLabel
414 * @sock: the socket 432 * @sock: the socket
415 * @level: the socket level or protocol 433 * @level: the socket level or protocol
@@ -431,7 +449,7 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock,
431 struct sk_security_struct *sksec = sk->sk_security; 449 struct sk_security_struct *sksec = sk->sk_security;
432 struct netlbl_lsm_secattr secattr; 450 struct netlbl_lsm_secattr secattr;
433 451
434 if (level == IPPROTO_IP && optname == IP_OPTIONS && 452 if (selinux_netlbl_option(level, optname) &&
435 (sksec->nlbl_state == NLBL_LABELED || 453 (sksec->nlbl_state == NLBL_LABELED ||
436 sksec->nlbl_state == NLBL_CONNLABELED)) { 454 sksec->nlbl_state == NLBL_CONNLABELED)) {
437 netlbl_secattr_init(&secattr); 455 netlbl_secattr_init(&secattr);
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index 1b1fd27de632..0765c5b053b5 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -1347,7 +1347,7 @@ static ssize_t sel_write_avc_cache_threshold(struct file *file,
1347{ 1347{
1348 char *page; 1348 char *page;
1349 ssize_t ret; 1349 ssize_t ret;
1350 int new_value; 1350 unsigned int new_value;
1351 1351
1352 ret = task_has_security(current, SECURITY__SETSECPARAM); 1352 ret = task_has_security(current, SECURITY__SETSECPARAM);
1353 if (ret) 1353 if (ret)
diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c
index 57644b1dc42e..894b6cdc11c5 100644
--- a/security/selinux/ss/ebitmap.c
+++ b/security/selinux/ss/ebitmap.c
@@ -165,7 +165,7 @@ int ebitmap_netlbl_import(struct ebitmap *ebmap,
165 e_iter = kzalloc(sizeof(*e_iter), GFP_ATOMIC); 165 e_iter = kzalloc(sizeof(*e_iter), GFP_ATOMIC);
166 if (e_iter == NULL) 166 if (e_iter == NULL)
167 goto netlbl_import_failure; 167 goto netlbl_import_failure;
168 e_iter->startbit = offset & ~(EBITMAP_SIZE - 1); 168 e_iter->startbit = offset - (offset % EBITMAP_SIZE);
169 if (e_prev == NULL) 169 if (e_prev == NULL)
170 ebmap->node = e_iter; 170 ebmap->node = e_iter;
171 else 171 else
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 89df64672b89..082b20c78363 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -543,7 +543,7 @@ static void type_attribute_bounds_av(struct context *scontext,
543 struct av_decision *avd) 543 struct av_decision *avd)
544{ 544{
545 struct context lo_scontext; 545 struct context lo_scontext;
546 struct context lo_tcontext; 546 struct context lo_tcontext, *tcontextp = tcontext;
547 struct av_decision lo_avd; 547 struct av_decision lo_avd;
548 struct type_datum *source; 548 struct type_datum *source;
549 struct type_datum *target; 549 struct type_datum *target;
@@ -553,67 +553,41 @@ static void type_attribute_bounds_av(struct context *scontext,
553 scontext->type - 1); 553 scontext->type - 1);
554 BUG_ON(!source); 554 BUG_ON(!source);
555 555
556 if (!source->bounds)
557 return;
558
556 target = flex_array_get_ptr(policydb.type_val_to_struct_array, 559 target = flex_array_get_ptr(policydb.type_val_to_struct_array,
557 tcontext->type - 1); 560 tcontext->type - 1);
558 BUG_ON(!target); 561 BUG_ON(!target);
559 562
560 if (source->bounds) { 563 memset(&lo_avd, 0, sizeof(lo_avd));
561 memset(&lo_avd, 0, sizeof(lo_avd));
562
563 memcpy(&lo_scontext, scontext, sizeof(lo_scontext));
564 lo_scontext.type = source->bounds;
565 564
566 context_struct_compute_av(&lo_scontext, 565 memcpy(&lo_scontext, scontext, sizeof(lo_scontext));
567 tcontext, 566 lo_scontext.type = source->bounds;
568 tclass,
569 &lo_avd,
570 NULL);
571 if ((lo_avd.allowed & avd->allowed) == avd->allowed)
572 return; /* no masked permission */
573 masked = ~lo_avd.allowed & avd->allowed;
574 }
575 567
576 if (target->bounds) { 568 if (target->bounds) {
577 memset(&lo_avd, 0, sizeof(lo_avd));
578
579 memcpy(&lo_tcontext, tcontext, sizeof(lo_tcontext)); 569 memcpy(&lo_tcontext, tcontext, sizeof(lo_tcontext));
580 lo_tcontext.type = target->bounds; 570 lo_tcontext.type = target->bounds;
581 571 tcontextp = &lo_tcontext;
582 context_struct_compute_av(scontext,
583 &lo_tcontext,
584 tclass,
585 &lo_avd,
586 NULL);
587 if ((lo_avd.allowed & avd->allowed) == avd->allowed)
588 return; /* no masked permission */
589 masked = ~lo_avd.allowed & avd->allowed;
590 } 572 }
591 573
592 if (source->bounds && target->bounds) { 574 context_struct_compute_av(&lo_scontext,
593 memset(&lo_avd, 0, sizeof(lo_avd)); 575 tcontextp,
594 /* 576 tclass,
595 * lo_scontext and lo_tcontext are already 577 &lo_avd,
596 * set up. 578 NULL);
597 */
598 579
599 context_struct_compute_av(&lo_scontext, 580 masked = ~lo_avd.allowed & avd->allowed;
600 &lo_tcontext,
601 tclass,
602 &lo_avd,
603 NULL);
604 if ((lo_avd.allowed & avd->allowed) == avd->allowed)
605 return; /* no masked permission */
606 masked = ~lo_avd.allowed & avd->allowed;
607 }
608 581
609 if (masked) { 582 if (likely(!masked))
610 /* mask violated permissions */ 583 return; /* no masked permission */
611 avd->allowed &= ~masked;
612 584
613 /* audit masked permissions */ 585 /* mask violated permissions */
614 security_dump_masked_av(scontext, tcontext, 586 avd->allowed &= ~masked;
615 tclass, masked, "bounds"); 587
616 } 588 /* audit masked permissions */
589 security_dump_masked_av(scontext, tcontext,
590 tclass, masked, "bounds");
617} 591}
618 592
619/* 593/*