Blame view
security/selinux/netlabel.c
12.2 KB
5778eabd9 SELinux: extract ... |
1 2 3 4 5 6 |
/* * SELinux NetLabel Support * * This file provides the necessary glue to tie NetLabel into the SELinux * subsystem. * |
82c21bfab doc: Update the e... |
7 |
* Author: Paul Moore <paul@paul-moore.com> |
5778eabd9 SELinux: extract ... |
8 9 10 11 |
* */ /* |
948bf85c1 netlabel: Add fun... |
12 |
* (c) Copyright Hewlett-Packard Development Company, L.P., 2007, 2008 |
5778eabd9 SELinux: extract ... |
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See * the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include <linux/spinlock.h> #include <linux/rcupdate.h> |
5a0e3ad6a include cleanup: ... |
32 |
#include <linux/gfp.h> |
014ab19a6 selinux: Set sock... |
33 34 |
#include <linux/ip.h> #include <linux/ipv6.h> |
5778eabd9 SELinux: extract ... |
35 36 |
#include <net/sock.h> #include <net/netlabel.h> |
014ab19a6 selinux: Set sock... |
37 38 |
#include <net/ip.h> #include <net/ipv6.h> |
5778eabd9 SELinux: extract ... |
39 40 41 |
#include "objsec.h" #include "security.h" |
d4ee4231a selinux: selinux/... |
42 |
#include "netlabel.h" |
5778eabd9 SELinux: extract ... |
43 44 |
/** |
5dbe1eb0c SELinux: Allow Ne... |
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
* selinux_netlbl_sidlookup_cached - Cache a SID lookup * @skb: the packet * @secattr: the NetLabel security attributes * @sid: the SID * * Description: * Query the SELinux security server to lookup the correct SID for the given * security attributes. If the query is successful, cache the result to speed * up future lookups. Returns zero on success, negative values on failure. * */ static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb, struct netlbl_lsm_secattr *secattr, u32 *sid) { int rc; rc = security_netlbl_secattr_to_sid(secattr, sid); if (rc == 0 && (secattr->flags & NETLBL_SECATTR_CACHEABLE) && (secattr->flags & NETLBL_SECATTR_CACHE)) netlbl_cache_add(skb, secattr); return rc; } /** |
6c5b3fc01 selinux: Cache Ne... |
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
* selinux_netlbl_sock_genattr - Generate the NetLabel socket secattr * @sk: the socket * * Description: * Generate the NetLabel security attributes for a socket, making full use of * the socket's attribute cache. Returns a pointer to the security attributes * on success, NULL on failure. * */ static struct netlbl_lsm_secattr *selinux_netlbl_sock_genattr(struct sock *sk) { int rc; struct sk_security_struct *sksec = sk->sk_security; struct netlbl_lsm_secattr *secattr; if (sksec->nlbl_secattr != NULL) return sksec->nlbl_secattr; secattr = netlbl_secattr_alloc(GFP_ATOMIC); if (secattr == NULL) return NULL; rc = security_netlbl_sid_to_secattr(sksec->sid, secattr); if (rc != 0) { netlbl_secattr_free(secattr); return NULL; } sksec->nlbl_secattr = secattr; return secattr; } /** |
5778eabd9 SELinux: extract ... |
104 105 106 107 108 109 110 111 112 113 114 115 |
* selinux_netlbl_cache_invalidate - Invalidate the NetLabel cache * * Description: * Invalidate the NetLabel security attribute mapping cache. * */ void selinux_netlbl_cache_invalidate(void) { netlbl_cache_invalidate(); } /** |
dfaebe982 selinux: Fix miss... |
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
* selinux_netlbl_err - Handle a NetLabel packet error * @skb: the packet * @error: the error code * @gateway: true if host is acting as a gateway, false otherwise * * Description: * When a packet is dropped due to a call to avc_has_perm() pass the error * code to the NetLabel subsystem so any protocol specific processing can be * done. This is safe to call even if you are unsure if NetLabel labeling is * present on the packet, NetLabel is smart enough to only act when it should. * */ void selinux_netlbl_err(struct sk_buff *skb, int error, int gateway) { netlbl_skbuff_err(skb, error, gateway); } /** |
6c5b3fc01 selinux: Cache Ne... |
134 |
* selinux_netlbl_sk_security_free - Free the NetLabel fields |
dd3e7836b selinux: always c... |
135 |
* @sksec: the sk_security_struct |
6c5b3fc01 selinux: Cache Ne... |
136 137 138 139 140 |
* * Description: * Free all of the memory in the NetLabel fields of a sk_security_struct. * */ |
dd3e7836b selinux: always c... |
141 |
void selinux_netlbl_sk_security_free(struct sk_security_struct *sksec) |
6c5b3fc01 selinux: Cache Ne... |
142 |
{ |
dd3e7836b selinux: always c... |
143 144 |
if (sksec->nlbl_secattr != NULL) netlbl_secattr_free(sksec->nlbl_secattr); |
6c5b3fc01 selinux: Cache Ne... |
145 146 147 |
} /** |
5778eabd9 SELinux: extract ... |
148 |
* selinux_netlbl_sk_security_reset - Reset the NetLabel fields |
dd3e7836b selinux: always c... |
149 |
* @sksec: the sk_security_struct |
5778eabd9 SELinux: extract ... |
150 151 152 153 |
* @family: the socket family * * Description: * Called when the NetLabel state of a sk_security_struct needs to be reset. |
25985edce Fix common misspe... |
154 |
* The caller is responsible for all the NetLabel sk_security_struct locking. |
5778eabd9 SELinux: extract ... |
155 156 |
* */ |
dd3e7836b selinux: always c... |
157 |
void selinux_netlbl_sk_security_reset(struct sk_security_struct *sksec) |
5778eabd9 SELinux: extract ... |
158 |
{ |
dd3e7836b selinux: always c... |
159 |
sksec->nlbl_state = NLBL_UNSET; |
5778eabd9 SELinux: extract ... |
160 161 162 |
} /** |
5778eabd9 SELinux: extract ... |
163 164 |
* selinux_netlbl_skbuff_getsid - Get the sid of a packet using NetLabel * @skb: the packet |
75e22910c NetLabel: Add IP ... |
165 |
* @family: protocol family |
220deb966 SELinux: Better i... |
166 |
* @type: NetLabel labeling protocol type |
5778eabd9 SELinux: extract ... |
167 168 169 170 171 172 173 174 |
* @sid: the SID * * Description: * Call the NetLabel mechanism to get the security attributes of the given * packet and use those attributes to determine the correct context/SID to * assign to the packet. Returns zero on success, negative values on failure. * */ |
75e22910c NetLabel: Add IP ... |
175 176 |
int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u16 family, |
220deb966 SELinux: Better i... |
177 |
u32 *type, |
75e22910c NetLabel: Add IP ... |
178 |
u32 *sid) |
5778eabd9 SELinux: extract ... |
179 180 181 |
{ int rc; struct netlbl_lsm_secattr secattr; |
23bcdc1ad SELinux: enable d... |
182 183 184 185 |
if (!netlbl_enabled()) { *sid = SECSID_NULL; return 0; } |
5778eabd9 SELinux: extract ... |
186 |
netlbl_secattr_init(&secattr); |
75e22910c NetLabel: Add IP ... |
187 |
rc = netlbl_skbuff_getattr(skb, family, &secattr); |
5dbe1eb0c SELinux: Allow Ne... |
188 189 190 |
if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE) rc = selinux_netlbl_sidlookup_cached(skb, &secattr, sid); else |
5778eabd9 SELinux: extract ... |
191 |
*sid = SECSID_NULL; |
220deb966 SELinux: Better i... |
192 |
*type = secattr.type; |
5778eabd9 SELinux: extract ... |
193 194 195 196 197 198 |
netlbl_secattr_destroy(&secattr); return rc; } /** |
948bf85c1 netlabel: Add fun... |
199 200 201 202 203 204 205 |
* selinux_netlbl_skbuff_setsid - Set the NetLabel on a packet given a sid * @skb: the packet * @family: protocol family * @sid: the SID * * Description * Call the NetLabel mechanism to set the label of a packet using @sid. |
af901ca18 tree-wide: fix as... |
206 |
* Returns zero on success, negative values on failure. |
948bf85c1 netlabel: Add fun... |
207 208 209 210 211 212 213 |
* */ int selinux_netlbl_skbuff_setsid(struct sk_buff *skb, u16 family, u32 sid) { int rc; |
6c5b3fc01 selinux: Cache Ne... |
214 215 |
struct netlbl_lsm_secattr secattr_storage; struct netlbl_lsm_secattr *secattr = NULL; |
948bf85c1 netlabel: Add fun... |
216 217 218 219 220 221 222 223 224 |
struct sock *sk; /* if this is a locally generated packet check to see if it is already * being labeled by it's parent socket, if it is just exit */ sk = skb->sk; if (sk != NULL) { struct sk_security_struct *sksec = sk->sk_security; if (sksec->nlbl_state != NLBL_REQSKB) return 0; |
6c5b3fc01 selinux: Cache Ne... |
225 226 227 228 229 230 231 232 |
secattr = sksec->nlbl_secattr; } if (secattr == NULL) { secattr = &secattr_storage; netlbl_secattr_init(secattr); rc = security_netlbl_sid_to_secattr(sid, secattr); if (rc != 0) goto skbuff_setsid_return; |
948bf85c1 netlabel: Add fun... |
233 |
} |
6c5b3fc01 selinux: Cache Ne... |
234 |
rc = netlbl_skbuff_setattr(skb, family, secattr); |
948bf85c1 netlabel: Add fun... |
235 236 |
skbuff_setsid_return: |
6c5b3fc01 selinux: Cache Ne... |
237 238 |
if (secattr == &secattr_storage) netlbl_secattr_destroy(secattr); |
948bf85c1 netlabel: Add fun... |
239 240 241 242 |
return rc; } /** |
389fb800a netlabel: Label i... |
243 244 |
* selinux_netlbl_inet_conn_request - Label an incoming stream connection * @req: incoming connection request socket |
5778eabd9 SELinux: extract ... |
245 246 |
* * Description: |
389fb800a netlabel: Label i... |
247 248 249 250 |
* A new incoming connection request is represented by @req, we need to label * the new request_sock here and the stack will ensure the on-the-wire label * will get preserved when a full sock is created once the connection handshake * is complete. Returns zero on success, negative values on failure. |
5778eabd9 SELinux: extract ... |
251 252 |
* */ |
389fb800a netlabel: Label i... |
253 |
int selinux_netlbl_inet_conn_request(struct request_sock *req, u16 family) |
5778eabd9 SELinux: extract ... |
254 |
{ |
014ab19a6 selinux: Set sock... |
255 |
int rc; |
389fb800a netlabel: Label i... |
256 |
struct netlbl_lsm_secattr secattr; |
014ab19a6 selinux: Set sock... |
257 |
|
389fb800a netlabel: Label i... |
258 259 |
if (family != PF_INET) return 0; |
014ab19a6 selinux: Set sock... |
260 |
|
389fb800a netlabel: Label i... |
261 262 263 264 265 266 267 268 |
netlbl_secattr_init(&secattr); rc = security_netlbl_sid_to_secattr(req->secid, &secattr); if (rc != 0) goto inet_conn_request_return; rc = netlbl_req_setattr(req, &secattr); inet_conn_request_return: netlbl_secattr_destroy(&secattr); return rc; |
5778eabd9 SELinux: extract ... |
269 270 271 |
} /** |
389fb800a netlabel: Label i... |
272 273 |
* selinux_netlbl_inet_csk_clone - Initialize the newly created sock * @sk: the new sock |
5778eabd9 SELinux: extract ... |
274 275 |
* * Description: |
389fb800a netlabel: Label i... |
276 277 278 |
* A new connection has been established using @sk, we've already labeled the * socket via the request_sock struct in selinux_netlbl_inet_conn_request() but * we need to set the NetLabel state here since we now have a sock structure. |
5778eabd9 SELinux: extract ... |
279 280 |
* */ |
389fb800a netlabel: Label i... |
281 |
void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family) |
5778eabd9 SELinux: extract ... |
282 |
{ |
389fb800a netlabel: Label i... |
283 284 285 286 287 288 |
struct sk_security_struct *sksec = sk->sk_security; if (family == PF_INET) sksec->nlbl_state = NLBL_LABELED; else sksec->nlbl_state = NLBL_UNSET; |
5778eabd9 SELinux: extract ... |
289 290 291 |
} /** |
389fb800a netlabel: Label i... |
292 293 294 |
* selinux_netlbl_socket_post_create - Label a socket using NetLabel * @sock: the socket to label * @family: protocol family |
5778eabd9 SELinux: extract ... |
295 296 |
* * Description: |
389fb800a netlabel: Label i... |
297 298 |
* Attempt to label a socket using the NetLabel mechanism using the given * SID. Returns zero values on success, negative values on failure. |
5778eabd9 SELinux: extract ... |
299 300 |
* */ |
389fb800a netlabel: Label i... |
301 |
int selinux_netlbl_socket_post_create(struct sock *sk, u16 family) |
5778eabd9 SELinux: extract ... |
302 303 |
{ int rc; |
389fb800a netlabel: Label i... |
304 305 |
struct sk_security_struct *sksec = sk->sk_security; struct netlbl_lsm_secattr *secattr; |
5778eabd9 SELinux: extract ... |
306 |
|
389fb800a netlabel: Label i... |
307 |
if (family != PF_INET) |
5778eabd9 SELinux: extract ... |
308 |
return 0; |
f74af6e81 SELinux: Correct ... |
309 |
|
389fb800a netlabel: Label i... |
310 311 312 313 314 315 316 317 318 319 |
secattr = selinux_netlbl_sock_genattr(sk); if (secattr == NULL) return -ENOMEM; rc = netlbl_sock_setattr(sk, family, secattr); switch (rc) { case 0: sksec->nlbl_state = NLBL_LABELED; break; case -EDESTADDRREQ: sksec->nlbl_state = NLBL_REQSKB; |
f74af6e81 SELinux: Correct ... |
320 |
rc = 0; |
389fb800a netlabel: Label i... |
321 322 |
break; } |
5778eabd9 SELinux: extract ... |
323 324 325 326 327 328 329 330 |
return rc; } /** * selinux_netlbl_sock_rcv_skb - Do an inbound access check using NetLabel * @sksec: the sock's sk_security_struct * @skb: the packet |
75e22910c NetLabel: Add IP ... |
331 |
* @family: protocol family |
5778eabd9 SELinux: extract ... |
332 333 334 335 336 337 338 339 340 341 |
* @ad: the audit data * * Description: * Fetch the NetLabel security attributes from @skb and perform an access check * against the receiving socket. Returns zero on success, negative values on * error. * */ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, struct sk_buff *skb, |
75e22910c NetLabel: Add IP ... |
342 |
u16 family, |
2bf496903 SELinux: Convert ... |
343 |
struct common_audit_data *ad) |
5778eabd9 SELinux: extract ... |
344 345 |
{ int rc; |
f36158c41 SELinux: use SECI... |
346 347 348 |
u32 nlbl_sid; u32 perm; struct netlbl_lsm_secattr secattr; |
5778eabd9 SELinux: extract ... |
349 |
|
23bcdc1ad SELinux: enable d... |
350 351 |
if (!netlbl_enabled()) return 0; |
f36158c41 SELinux: use SECI... |
352 |
netlbl_secattr_init(&secattr); |
75e22910c NetLabel: Add IP ... |
353 |
rc = netlbl_skbuff_getattr(skb, family, &secattr); |
5dbe1eb0c SELinux: Allow Ne... |
354 355 356 |
if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE) rc = selinux_netlbl_sidlookup_cached(skb, &secattr, &nlbl_sid); else |
f36158c41 SELinux: use SECI... |
357 358 |
nlbl_sid = SECINITSID_UNLABELED; netlbl_secattr_destroy(&secattr); |
5778eabd9 SELinux: extract ... |
359 360 |
if (rc != 0) return rc; |
8d9107e8c Revert "SELinux: ... |
361 |
|
5778eabd9 SELinux: extract ... |
362 363 |
switch (sksec->sclass) { case SECCLASS_UDP_SOCKET: |
f36158c41 SELinux: use SECI... |
364 |
perm = UDP_SOCKET__RECVFROM; |
5778eabd9 SELinux: extract ... |
365 366 |
break; case SECCLASS_TCP_SOCKET: |
f36158c41 SELinux: use SECI... |
367 |
perm = TCP_SOCKET__RECVFROM; |
5778eabd9 SELinux: extract ... |
368 369 |
break; default: |
f36158c41 SELinux: use SECI... |
370 |
perm = RAWIP_SOCKET__RECVFROM; |
5778eabd9 SELinux: extract ... |
371 |
} |
f36158c41 SELinux: use SECI... |
372 |
rc = avc_has_perm(sksec->sid, nlbl_sid, sksec->sclass, perm, ad); |
5778eabd9 SELinux: extract ... |
373 374 |
if (rc == 0) return 0; |
f36158c41 SELinux: use SECI... |
375 |
if (nlbl_sid != SECINITSID_UNLABELED) |
dfaebe982 selinux: Fix miss... |
376 |
netlbl_skbuff_err(skb, rc, 0); |
5778eabd9 SELinux: extract ... |
377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 |
return rc; } /** * selinux_netlbl_socket_setsockopt - Do not allow users to remove a NetLabel * @sock: the socket * @level: the socket level or protocol * @optname: the socket option name * * Description: * Check the setsockopt() call and if the user is trying to replace the IP * options on a socket and a NetLabel is in place for the socket deny the * access; otherwise allow the access. Returns zero when the access is * allowed, -EACCES when denied, and other negative values on error. * */ int selinux_netlbl_socket_setsockopt(struct socket *sock, int level, int optname) { int rc = 0; |
ba6ff9f2b [NetLabel]: conso... |
398 399 |
struct sock *sk = sock->sk; struct sk_security_struct *sksec = sk->sk_security; |
5778eabd9 SELinux: extract ... |
400 |
struct netlbl_lsm_secattr secattr; |
5778eabd9 SELinux: extract ... |
401 |
if (level == IPPROTO_IP && optname == IP_OPTIONS && |
014ab19a6 selinux: Set sock... |
402 403 |
(sksec->nlbl_state == NLBL_LABELED || sksec->nlbl_state == NLBL_CONNLABELED)) { |
5778eabd9 SELinux: extract ... |
404 |
netlbl_secattr_init(&secattr); |
ba6ff9f2b [NetLabel]: conso... |
405 406 407 |
lock_sock(sk); rc = netlbl_sock_getattr(sk, &secattr); release_sock(sk); |
09c50b4a5 selinux: Fix the ... |
408 |
if (rc == 0) |
5778eabd9 SELinux: extract ... |
409 |
rc = -EACCES; |
09c50b4a5 selinux: Fix the ... |
410 411 |
else if (rc == -ENOMSG) rc = 0; |
5778eabd9 SELinux: extract ... |
412 413 |
netlbl_secattr_destroy(&secattr); } |
5778eabd9 SELinux: extract ... |
414 415 416 |
return rc; } |
014ab19a6 selinux: Set sock... |
417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 |
/** * selinux_netlbl_socket_connect - Label a client-side socket on connect * @sk: the socket to label * @addr: the destination address * * Description: * Attempt to label a connected socket with NetLabel using the given address. * Returns zero values on success, negative values on failure. * */ int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr) { int rc; struct sk_security_struct *sksec = sk->sk_security; |
6c5b3fc01 selinux: Cache Ne... |
432 |
struct netlbl_lsm_secattr *secattr; |
014ab19a6 selinux: Set sock... |
433 434 435 436 |
if (sksec->nlbl_state != NLBL_REQSKB && sksec->nlbl_state != NLBL_CONNLABELED) return 0; |
014ab19a6 selinux: Set sock... |
437 438 439 440 441 442 443 444 445 446 447 448 |
local_bh_disable(); bh_lock_sock_nested(sk); /* connected sockets are allowed to disconnect when the address family * is set to AF_UNSPEC, if that is what is happening we want to reset * the socket */ if (addr->sa_family == AF_UNSPEC) { netlbl_sock_delattr(sk); sksec->nlbl_state = NLBL_REQSKB; rc = 0; goto socket_connect_return; } |
6c5b3fc01 selinux: Cache Ne... |
449 450 451 |
secattr = selinux_netlbl_sock_genattr(sk); if (secattr == NULL) { rc = -ENOMEM; |
014ab19a6 selinux: Set sock... |
452 |
goto socket_connect_return; |
6c5b3fc01 selinux: Cache Ne... |
453 454 455 456 |
} rc = netlbl_conn_setattr(sk, addr, secattr); if (rc == 0) sksec->nlbl_state = NLBL_CONNLABELED; |
014ab19a6 selinux: Set sock... |
457 458 459 460 |
socket_connect_return: bh_unlock_sock(sk); local_bh_enable(); |
014ab19a6 selinux: Set sock... |
461 462 |
return rc; } |