Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
netlabel.c
Go to the documentation of this file.
1 /*
2  * SELinux NetLabel Support
3  *
4  * This file provides the necessary glue to tie NetLabel into the SELinux
5  * subsystem.
6  *
7  * Author: Paul Moore <[email protected]>
8  *
9  */
10 
11 /*
12  * (c) Copyright Hewlett-Packard Development Company, L.P., 2007, 2008
13  *
14  * This program is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 2 of the License, or
17  * (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
22  * the GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27  *
28  */
29 
30 #include <linux/spinlock.h>
31 #include <linux/rcupdate.h>
32 #include <linux/gfp.h>
33 #include <linux/ip.h>
34 #include <linux/ipv6.h>
35 #include <net/sock.h>
36 #include <net/netlabel.h>
37 #include <net/ip.h>
38 #include <net/ipv6.h>
39 
40 #include "objsec.h"
41 #include "security.h"
42 #include "netlabel.h"
43 
56 static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb,
57  struct netlbl_lsm_secattr *secattr,
58  u32 *sid)
59 {
60  int rc;
61 
62  rc = security_netlbl_secattr_to_sid(secattr, sid);
63  if (rc == 0 &&
64  (secattr->flags & NETLBL_SECATTR_CACHEABLE) &&
65  (secattr->flags & NETLBL_SECATTR_CACHE))
66  netlbl_cache_add(skb, secattr);
67 
68  return rc;
69 }
70 
81 static struct netlbl_lsm_secattr *selinux_netlbl_sock_genattr(struct sock *sk)
82 {
83  int rc;
84  struct sk_security_struct *sksec = sk->sk_security;
85  struct netlbl_lsm_secattr *secattr;
86 
87  if (sksec->nlbl_secattr != NULL)
88  return sksec->nlbl_secattr;
89 
90  secattr = netlbl_secattr_alloc(GFP_ATOMIC);
91  if (secattr == NULL)
92  return NULL;
93  rc = security_netlbl_sid_to_secattr(sksec->sid, secattr);
94  if (rc != 0) {
95  netlbl_secattr_free(secattr);
96  return NULL;
97  }
98  sksec->nlbl_secattr = secattr;
99 
100  return secattr;
101 }
102 
111 {
113 }
114 
128 void selinux_netlbl_err(struct sk_buff *skb, int error, int gateway)
129 {
130  netlbl_skbuff_err(skb, error, gateway);
131 }
132 
142 {
143  if (sksec->nlbl_secattr != NULL)
144  netlbl_secattr_free(sksec->nlbl_secattr);
145 }
146 
158 {
159  sksec->nlbl_state = NLBL_UNSET;
160 }
161 
176  u16 family,
177  u32 *type,
178  u32 *sid)
179 {
180  int rc;
181  struct netlbl_lsm_secattr secattr;
182 
183  if (!netlbl_enabled()) {
184  *sid = SECSID_NULL;
185  return 0;
186  }
187 
188  netlbl_secattr_init(&secattr);
189  rc = netlbl_skbuff_getattr(skb, family, &secattr);
190  if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE)
191  rc = selinux_netlbl_sidlookup_cached(skb, &secattr, sid);
192  else
193  *sid = SECSID_NULL;
194  *type = secattr.type;
195  netlbl_secattr_destroy(&secattr);
196 
197  return rc;
198 }
199 
212  u16 family,
213  u32 sid)
214 {
215  int rc;
216  struct netlbl_lsm_secattr secattr_storage;
217  struct netlbl_lsm_secattr *secattr = NULL;
218  struct sock *sk;
219 
220  /* if this is a locally generated packet check to see if it is already
221  * being labeled by it's parent socket, if it is just exit */
222  sk = skb->sk;
223  if (sk != NULL) {
224  struct sk_security_struct *sksec = sk->sk_security;
225  if (sksec->nlbl_state != NLBL_REQSKB)
226  return 0;
227  secattr = sksec->nlbl_secattr;
228  }
229  if (secattr == NULL) {
230  secattr = &secattr_storage;
231  netlbl_secattr_init(secattr);
232  rc = security_netlbl_sid_to_secattr(sid, secattr);
233  if (rc != 0)
234  goto skbuff_setsid_return;
235  }
236 
237  rc = netlbl_skbuff_setattr(skb, family, secattr);
238 
239 skbuff_setsid_return:
240  if (secattr == &secattr_storage)
241  netlbl_secattr_destroy(secattr);
242  return rc;
243 }
244 
257 {
258  int rc;
259  struct netlbl_lsm_secattr secattr;
260 
261  if (family != PF_INET)
262  return 0;
263 
264  netlbl_secattr_init(&secattr);
265  rc = security_netlbl_sid_to_secattr(req->secid, &secattr);
266  if (rc != 0)
267  goto inet_conn_request_return;
268  rc = netlbl_req_setattr(req, &secattr);
269 inet_conn_request_return:
270  netlbl_secattr_destroy(&secattr);
271  return rc;
272 }
273 
285 {
286  struct sk_security_struct *sksec = sk->sk_security;
287 
288  if (family == PF_INET)
289  sksec->nlbl_state = NLBL_LABELED;
290  else
291  sksec->nlbl_state = NLBL_UNSET;
292 }
293 
305 {
306  int rc;
307  struct sk_security_struct *sksec = sk->sk_security;
308  struct netlbl_lsm_secattr *secattr;
309 
310  if (family != PF_INET)
311  return 0;
312 
313  secattr = selinux_netlbl_sock_genattr(sk);
314  if (secattr == NULL)
315  return -ENOMEM;
316  rc = netlbl_sock_setattr(sk, family, secattr);
317  switch (rc) {
318  case 0:
319  sksec->nlbl_state = NLBL_LABELED;
320  break;
321  case -EDESTADDRREQ:
322  sksec->nlbl_state = NLBL_REQSKB;
323  rc = 0;
324  break;
325  }
326 
327  return rc;
328 }
329 
344  struct sk_buff *skb,
345  u16 family,
346  struct common_audit_data *ad)
347 {
348  int rc;
349  u32 nlbl_sid;
350  u32 perm;
351  struct netlbl_lsm_secattr secattr;
352 
353  if (!netlbl_enabled())
354  return 0;
355 
356  netlbl_secattr_init(&secattr);
357  rc = netlbl_skbuff_getattr(skb, family, &secattr);
358  if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE)
359  rc = selinux_netlbl_sidlookup_cached(skb, &secattr, &nlbl_sid);
360  else
361  nlbl_sid = SECINITSID_UNLABELED;
362  netlbl_secattr_destroy(&secattr);
363  if (rc != 0)
364  return rc;
365 
366  switch (sksec->sclass) {
367  case SECCLASS_UDP_SOCKET:
368  perm = UDP_SOCKET__RECVFROM;
369  break;
370  case SECCLASS_TCP_SOCKET:
371  perm = TCP_SOCKET__RECVFROM;
372  break;
373  default:
374  perm = RAWIP_SOCKET__RECVFROM;
375  }
376 
377  rc = avc_has_perm(sksec->sid, nlbl_sid, sksec->sclass, perm, ad);
378  if (rc == 0)
379  return 0;
380 
381  if (nlbl_sid != SECINITSID_UNLABELED)
382  netlbl_skbuff_err(skb, rc, 0);
383  return rc;
384 }
385 
400  int level,
401  int optname)
402 {
403  int rc = 0;
404  struct sock *sk = sock->sk;
405  struct sk_security_struct *sksec = sk->sk_security;
406  struct netlbl_lsm_secattr secattr;
407 
408  if (level == IPPROTO_IP && optname == IP_OPTIONS &&
409  (sksec->nlbl_state == NLBL_LABELED ||
410  sksec->nlbl_state == NLBL_CONNLABELED)) {
411  netlbl_secattr_init(&secattr);
412  lock_sock(sk);
413  rc = netlbl_sock_getattr(sk, &secattr);
414  release_sock(sk);
415  if (rc == 0)
416  rc = -EACCES;
417  else if (rc == -ENOMSG)
418  rc = 0;
419  netlbl_secattr_destroy(&secattr);
420  }
421 
422  return rc;
423 }
424 
436 {
437  int rc;
438  struct sk_security_struct *sksec = sk->sk_security;
439  struct netlbl_lsm_secattr *secattr;
440 
441  if (sksec->nlbl_state != NLBL_REQSKB &&
442  sksec->nlbl_state != NLBL_CONNLABELED)
443  return 0;
444 
447 
448  /* connected sockets are allowed to disconnect when the address family
449  * is set to AF_UNSPEC, if that is what is happening we want to reset
450  * the socket */
451  if (addr->sa_family == AF_UNSPEC) {
453  sksec->nlbl_state = NLBL_REQSKB;
454  rc = 0;
455  goto socket_connect_return;
456  }
457  secattr = selinux_netlbl_sock_genattr(sk);
458  if (secattr == NULL) {
459  rc = -ENOMEM;
460  goto socket_connect_return;
461  }
462  rc = netlbl_conn_setattr(sk, addr, secattr);
463  if (rc == 0)
464  sksec->nlbl_state = NLBL_CONNLABELED;
465 
466 socket_connect_return:
467  bh_unlock_sock(sk);
468  local_bh_enable();
469  return rc;
470 }