xref: /linux/security/selinux/netlabel.c (revision bcefe12eff5dca6fdfa94ed85e5bee66380d5cd9)
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 <paul.moore@hp.com>
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/ip.h>
33 #include <linux/ipv6.h>
34 #include <net/sock.h>
35 #include <net/netlabel.h>
36 #include <net/ip.h>
37 #include <net/ipv6.h>
38 
39 #include "objsec.h"
40 #include "security.h"
41 #include "netlabel.h"
42 
43 /**
44  * selinux_netlbl_sidlookup_cached - Cache a SID lookup
45  * @skb: the packet
46  * @secattr: the NetLabel security attributes
47  * @sid: the SID
48  *
49  * Description:
50  * Query the SELinux security server to lookup the correct SID for the given
51  * security attributes.  If the query is successful, cache the result to speed
52  * up future lookups.  Returns zero on success, negative values on failure.
53  *
54  */
55 static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb,
56 					   struct netlbl_lsm_secattr *secattr,
57 					   u32 *sid)
58 {
59 	int rc;
60 
61 	rc = security_netlbl_secattr_to_sid(secattr, sid);
62 	if (rc == 0 &&
63 	    (secattr->flags & NETLBL_SECATTR_CACHEABLE) &&
64 	    (secattr->flags & NETLBL_SECATTR_CACHE))
65 		netlbl_cache_add(skb, secattr);
66 
67 	return rc;
68 }
69 
70 /**
71  * selinux_netlbl_sock_genattr - Generate the NetLabel socket secattr
72  * @sk: the socket
73  *
74  * Description:
75  * Generate the NetLabel security attributes for a socket, making full use of
76  * the socket's attribute cache.  Returns a pointer to the security attributes
77  * on success, NULL on failure.
78  *
79  */
80 static struct netlbl_lsm_secattr *selinux_netlbl_sock_genattr(struct sock *sk)
81 {
82 	int rc;
83 	struct sk_security_struct *sksec = sk->sk_security;
84 	struct netlbl_lsm_secattr *secattr;
85 
86 	if (sksec->nlbl_secattr != NULL)
87 		return sksec->nlbl_secattr;
88 
89 	secattr = netlbl_secattr_alloc(GFP_ATOMIC);
90 	if (secattr == NULL)
91 		return NULL;
92 	rc = security_netlbl_sid_to_secattr(sksec->sid, secattr);
93 	if (rc != 0) {
94 		netlbl_secattr_free(secattr);
95 		return NULL;
96 	}
97 	sksec->nlbl_secattr = secattr;
98 
99 	return secattr;
100 }
101 
102 /**
103  * selinux_netlbl_cache_invalidate - Invalidate the NetLabel cache
104  *
105  * Description:
106  * Invalidate the NetLabel security attribute mapping cache.
107  *
108  */
109 void selinux_netlbl_cache_invalidate(void)
110 {
111 	netlbl_cache_invalidate();
112 }
113 
114 /**
115  * selinux_netlbl_err - Handle a NetLabel packet error
116  * @skb: the packet
117  * @error: the error code
118  * @gateway: true if host is acting as a gateway, false otherwise
119  *
120  * Description:
121  * When a packet is dropped due to a call to avc_has_perm() pass the error
122  * code to the NetLabel subsystem so any protocol specific processing can be
123  * done.  This is safe to call even if you are unsure if NetLabel labeling is
124  * present on the packet, NetLabel is smart enough to only act when it should.
125  *
126  */
127 void selinux_netlbl_err(struct sk_buff *skb, int error, int gateway)
128 {
129 	netlbl_skbuff_err(skb, error, gateway);
130 }
131 
132 /**
133  * selinux_netlbl_sk_security_free - Free the NetLabel fields
134  * @sssec: the sk_security_struct
135  *
136  * Description:
137  * Free all of the memory in the NetLabel fields of a sk_security_struct.
138  *
139  */
140 void selinux_netlbl_sk_security_free(struct sk_security_struct *ssec)
141 {
142 	if (ssec->nlbl_secattr != NULL)
143 		netlbl_secattr_free(ssec->nlbl_secattr);
144 }
145 
146 /**
147  * selinux_netlbl_sk_security_reset - Reset the NetLabel fields
148  * @ssec: the sk_security_struct
149  * @family: the socket family
150  *
151  * Description:
152  * Called when the NetLabel state of a sk_security_struct needs to be reset.
153  * The caller is responsibile for all the NetLabel sk_security_struct locking.
154  *
155  */
156 void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec)
157 {
158 	ssec->nlbl_state = NLBL_UNSET;
159 }
160 
161 /**
162  * selinux_netlbl_skbuff_getsid - Get the sid of a packet using NetLabel
163  * @skb: the packet
164  * @family: protocol family
165  * @type: NetLabel labeling protocol type
166  * @sid: the SID
167  *
168  * Description:
169  * Call the NetLabel mechanism to get the security attributes of the given
170  * packet and use those attributes to determine the correct context/SID to
171  * assign to the packet.  Returns zero on success, negative values on failure.
172  *
173  */
174 int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
175 				 u16 family,
176 				 u32 *type,
177 				 u32 *sid)
178 {
179 	int rc;
180 	struct netlbl_lsm_secattr secattr;
181 
182 	if (!netlbl_enabled()) {
183 		*sid = SECSID_NULL;
184 		return 0;
185 	}
186 
187 	netlbl_secattr_init(&secattr);
188 	rc = netlbl_skbuff_getattr(skb, family, &secattr);
189 	if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE)
190 		rc = selinux_netlbl_sidlookup_cached(skb, &secattr, sid);
191 	else
192 		*sid = SECSID_NULL;
193 	*type = secattr.type;
194 	netlbl_secattr_destroy(&secattr);
195 
196 	return rc;
197 }
198 
199 /**
200  * selinux_netlbl_skbuff_setsid - Set the NetLabel on a packet given a sid
201  * @skb: the packet
202  * @family: protocol family
203  * @sid: the SID
204  *
205  * Description
206  * Call the NetLabel mechanism to set the label of a packet using @sid.
207  * Returns zero on auccess, negative values on failure.
208  *
209  */
210 int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
211 				 u16 family,
212 				 u32 sid)
213 {
214 	int rc;
215 	struct netlbl_lsm_secattr secattr_storage;
216 	struct netlbl_lsm_secattr *secattr = NULL;
217 	struct sock *sk;
218 
219 	/* if this is a locally generated packet check to see if it is already
220 	 * being labeled by it's parent socket, if it is just exit */
221 	sk = skb->sk;
222 	if (sk != NULL) {
223 		struct sk_security_struct *sksec = sk->sk_security;
224 		if (sksec->nlbl_state != NLBL_REQSKB)
225 			return 0;
226 		secattr = sksec->nlbl_secattr;
227 	}
228 	if (secattr == NULL) {
229 		secattr = &secattr_storage;
230 		netlbl_secattr_init(secattr);
231 		rc = security_netlbl_sid_to_secattr(sid, secattr);
232 		if (rc != 0)
233 			goto skbuff_setsid_return;
234 	}
235 
236 	rc = netlbl_skbuff_setattr(skb, family, secattr);
237 
238 skbuff_setsid_return:
239 	if (secattr == &secattr_storage)
240 		netlbl_secattr_destroy(secattr);
241 	return rc;
242 }
243 
244 /**
245  * selinux_netlbl_inet_conn_request - Label an incoming stream connection
246  * @req: incoming connection request socket
247  *
248  * Description:
249  * A new incoming connection request is represented by @req, we need to label
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.
253  *
254  */
255 int selinux_netlbl_inet_conn_request(struct request_sock *req, u16 family)
256 {
257 	int rc;
258 	struct netlbl_lsm_secattr secattr;
259 
260 	if (family != PF_INET)
261 		return 0;
262 
263 	netlbl_secattr_init(&secattr);
264 	rc = security_netlbl_sid_to_secattr(req->secid, &secattr);
265 	if (rc != 0)
266 		goto inet_conn_request_return;
267 	rc = netlbl_req_setattr(req, &secattr);
268 inet_conn_request_return:
269 	netlbl_secattr_destroy(&secattr);
270 	return rc;
271 }
272 
273 /**
274  * selinux_netlbl_inet_csk_clone - Initialize the newly created sock
275  * @sk: the new sock
276  *
277  * Description:
278  * A new connection has been established using @sk, we've already labeled the
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.
281  *
282  */
283 void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family)
284 {
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;
291 }
292 
293 /**
294  * selinux_netlbl_socket_post_create - Label a socket using NetLabel
295  * @sock: the socket to label
296  * @family: protocol family
297  *
298  * Description:
299  * Attempt to label a socket using the NetLabel mechanism using the given
300  * SID.  Returns zero values on success, negative values on failure.
301  *
302  */
303 int selinux_netlbl_socket_post_create(struct sock *sk, u16 family)
304 {
305 	int rc;
306 	struct sk_security_struct *sksec = sk->sk_security;
307 	struct netlbl_lsm_secattr *secattr;
308 
309 	if (family != PF_INET)
310 		return 0;
311 
312 	secattr = selinux_netlbl_sock_genattr(sk);
313 	if (secattr == NULL)
314 		return -ENOMEM;
315 	rc = netlbl_sock_setattr(sk, family, secattr);
316 	switch (rc) {
317 	case 0:
318 		sksec->nlbl_state = NLBL_LABELED;
319 		break;
320 	case -EDESTADDRREQ:
321 		sksec->nlbl_state = NLBL_REQSKB;
322 		rc = 0;
323 		break;
324 	}
325 
326 	return rc;
327 }
328 
329 /**
330  * selinux_netlbl_sock_rcv_skb - Do an inbound access check using NetLabel
331  * @sksec: the sock's sk_security_struct
332  * @skb: the packet
333  * @family: protocol family
334  * @ad: the audit data
335  *
336  * Description:
337  * Fetch the NetLabel security attributes from @skb and perform an access check
338  * against the receiving socket.  Returns zero on success, negative values on
339  * error.
340  *
341  */
342 int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
343 				struct sk_buff *skb,
344 				u16 family,
345 				struct common_audit_data *ad)
346 {
347 	int rc;
348 	u32 nlbl_sid;
349 	u32 perm;
350 	struct netlbl_lsm_secattr secattr;
351 
352 	if (!netlbl_enabled())
353 		return 0;
354 
355 	netlbl_secattr_init(&secattr);
356 	rc = netlbl_skbuff_getattr(skb, family, &secattr);
357 	if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE)
358 		rc = selinux_netlbl_sidlookup_cached(skb, &secattr, &nlbl_sid);
359 	else
360 		nlbl_sid = SECINITSID_UNLABELED;
361 	netlbl_secattr_destroy(&secattr);
362 	if (rc != 0)
363 		return rc;
364 
365 	switch (sksec->sclass) {
366 	case SECCLASS_UDP_SOCKET:
367 		perm = UDP_SOCKET__RECVFROM;
368 		break;
369 	case SECCLASS_TCP_SOCKET:
370 		perm = TCP_SOCKET__RECVFROM;
371 		break;
372 	default:
373 		perm = RAWIP_SOCKET__RECVFROM;
374 	}
375 
376 	rc = avc_has_perm(sksec->sid, nlbl_sid, sksec->sclass, perm, ad);
377 	if (rc == 0)
378 		return 0;
379 
380 	if (nlbl_sid != SECINITSID_UNLABELED)
381 		netlbl_skbuff_err(skb, rc, 0);
382 	return rc;
383 }
384 
385 /**
386  * selinux_netlbl_socket_setsockopt - Do not allow users to remove a NetLabel
387  * @sock: the socket
388  * @level: the socket level or protocol
389  * @optname: the socket option name
390  *
391  * Description:
392  * Check the setsockopt() call and if the user is trying to replace the IP
393  * options on a socket and a NetLabel is in place for the socket deny the
394  * access; otherwise allow the access.  Returns zero when the access is
395  * allowed, -EACCES when denied, and other negative values on error.
396  *
397  */
398 int selinux_netlbl_socket_setsockopt(struct socket *sock,
399 				     int level,
400 				     int optname)
401 {
402 	int rc = 0;
403 	struct sock *sk = sock->sk;
404 	struct sk_security_struct *sksec = sk->sk_security;
405 	struct netlbl_lsm_secattr secattr;
406 
407 	if (level == IPPROTO_IP && optname == IP_OPTIONS &&
408 	    (sksec->nlbl_state == NLBL_LABELED ||
409 	     sksec->nlbl_state == NLBL_CONNLABELED)) {
410 		netlbl_secattr_init(&secattr);
411 		lock_sock(sk);
412 		rc = netlbl_sock_getattr(sk, &secattr);
413 		release_sock(sk);
414 		if (rc == 0)
415 			rc = -EACCES;
416 		else if (rc == -ENOMSG)
417 			rc = 0;
418 		netlbl_secattr_destroy(&secattr);
419 	}
420 
421 	return rc;
422 }
423 
424 /**
425  * selinux_netlbl_socket_connect - Label a client-side socket on connect
426  * @sk: the socket to label
427  * @addr: the destination address
428  *
429  * Description:
430  * Attempt to label a connected socket with NetLabel using the given address.
431  * Returns zero values on success, negative values on failure.
432  *
433  */
434 int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr)
435 {
436 	int rc;
437 	struct sk_security_struct *sksec = sk->sk_security;
438 	struct netlbl_lsm_secattr *secattr;
439 
440 	if (sksec->nlbl_state != NLBL_REQSKB &&
441 	    sksec->nlbl_state != NLBL_CONNLABELED)
442 		return 0;
443 
444 	local_bh_disable();
445 	bh_lock_sock_nested(sk);
446 
447 	/* connected sockets are allowed to disconnect when the address family
448 	 * is set to AF_UNSPEC, if that is what is happening we want to reset
449 	 * the socket */
450 	if (addr->sa_family == AF_UNSPEC) {
451 		netlbl_sock_delattr(sk);
452 		sksec->nlbl_state = NLBL_REQSKB;
453 		rc = 0;
454 		goto socket_connect_return;
455 	}
456 	secattr = selinux_netlbl_sock_genattr(sk);
457 	if (secattr == NULL) {
458 		rc = -ENOMEM;
459 		goto socket_connect_return;
460 	}
461 	rc = netlbl_conn_setattr(sk, addr, secattr);
462 	if (rc == 0)
463 		sksec->nlbl_state = NLBL_CONNLABELED;
464 
465 socket_connect_return:
466 	bh_unlock_sock(sk);
467 	local_bh_enable();
468 	return rc;
469 }
470