This source file includes following definitions.
- selinux_netlbl_sidlookup_cached
- selinux_netlbl_sock_genattr
- selinux_netlbl_sock_getattr
- selinux_netlbl_cache_invalidate
- selinux_netlbl_err
- selinux_netlbl_sk_security_free
- selinux_netlbl_sk_security_reset
- selinux_netlbl_skbuff_getsid
- selinux_netlbl_skbuff_setsid
- selinux_netlbl_sctp_assoc_request
- selinux_netlbl_inet_conn_request
- selinux_netlbl_inet_csk_clone
- selinux_netlbl_sctp_sk_clone
- selinux_netlbl_socket_post_create
- selinux_netlbl_sock_rcv_skb
- selinux_netlbl_option
- selinux_netlbl_socket_setsockopt
- selinux_netlbl_socket_connect_helper
- selinux_netlbl_socket_connect_locked
- selinux_netlbl_socket_connect
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 #include <linux/spinlock.h>
16 #include <linux/rcupdate.h>
17 #include <linux/gfp.h>
18 #include <linux/ip.h>
19 #include <linux/ipv6.h>
20 #include <net/sock.h>
21 #include <net/netlabel.h>
22 #include <net/ip.h>
23 #include <net/ipv6.h>
24
25 #include "objsec.h"
26 #include "security.h"
27 #include "netlabel.h"
28
29
30
31
32
33
34
35
36
37
38
39
40
41 static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb,
42 u16 family,
43 struct netlbl_lsm_secattr *secattr,
44 u32 *sid)
45 {
46 int rc;
47
48 rc = security_netlbl_secattr_to_sid(&selinux_state, secattr, sid);
49 if (rc == 0 &&
50 (secattr->flags & NETLBL_SECATTR_CACHEABLE) &&
51 (secattr->flags & NETLBL_SECATTR_CACHE))
52 netlbl_cache_add(skb, family, secattr);
53
54 return rc;
55 }
56
57
58
59
60
61
62
63
64
65
66
67 static struct netlbl_lsm_secattr *selinux_netlbl_sock_genattr(struct sock *sk)
68 {
69 int rc;
70 struct sk_security_struct *sksec = sk->sk_security;
71 struct netlbl_lsm_secattr *secattr;
72
73 if (sksec->nlbl_secattr != NULL)
74 return sksec->nlbl_secattr;
75
76 secattr = netlbl_secattr_alloc(GFP_ATOMIC);
77 if (secattr == NULL)
78 return NULL;
79 rc = security_netlbl_sid_to_secattr(&selinux_state, sksec->sid,
80 secattr);
81 if (rc != 0) {
82 netlbl_secattr_free(secattr);
83 return NULL;
84 }
85 sksec->nlbl_secattr = secattr;
86
87 return secattr;
88 }
89
90
91
92
93
94
95
96
97
98
99 static struct netlbl_lsm_secattr *selinux_netlbl_sock_getattr(
100 const struct sock *sk,
101 u32 sid)
102 {
103 struct sk_security_struct *sksec = sk->sk_security;
104 struct netlbl_lsm_secattr *secattr = sksec->nlbl_secattr;
105
106 if (secattr == NULL)
107 return NULL;
108
109 if ((secattr->flags & NETLBL_SECATTR_SECID) &&
110 (secattr->attr.secid == sid))
111 return secattr;
112
113 return NULL;
114 }
115
116
117
118
119
120
121
122
123 void selinux_netlbl_cache_invalidate(void)
124 {
125 netlbl_cache_invalidate();
126 }
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141 void selinux_netlbl_err(struct sk_buff *skb, u16 family, int error, int gateway)
142 {
143 netlbl_skbuff_err(skb, family, error, gateway);
144 }
145
146
147
148
149
150
151
152
153
154 void selinux_netlbl_sk_security_free(struct sk_security_struct *sksec)
155 {
156 if (sksec->nlbl_secattr != NULL)
157 netlbl_secattr_free(sksec->nlbl_secattr);
158 }
159
160
161
162
163
164
165
166
167
168
169
170 void selinux_netlbl_sk_security_reset(struct sk_security_struct *sksec)
171 {
172 sksec->nlbl_state = NLBL_UNSET;
173 }
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188 int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
189 u16 family,
190 u32 *type,
191 u32 *sid)
192 {
193 int rc;
194 struct netlbl_lsm_secattr secattr;
195
196 if (!netlbl_enabled()) {
197 *sid = SECSID_NULL;
198 return 0;
199 }
200
201 netlbl_secattr_init(&secattr);
202 rc = netlbl_skbuff_getattr(skb, family, &secattr);
203 if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE)
204 rc = selinux_netlbl_sidlookup_cached(skb, family,
205 &secattr, sid);
206 else
207 *sid = SECSID_NULL;
208 *type = secattr.type;
209 netlbl_secattr_destroy(&secattr);
210
211 return rc;
212 }
213
214
215
216
217
218
219
220
221
222
223
224
225 int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
226 u16 family,
227 u32 sid)
228 {
229 int rc;
230 struct netlbl_lsm_secattr secattr_storage;
231 struct netlbl_lsm_secattr *secattr = NULL;
232 struct sock *sk;
233
234
235
236 sk = skb_to_full_sk(skb);
237 if (sk != NULL) {
238 struct sk_security_struct *sksec = sk->sk_security;
239
240 if (sksec->nlbl_state != NLBL_REQSKB)
241 return 0;
242 secattr = selinux_netlbl_sock_getattr(sk, sid);
243 }
244 if (secattr == NULL) {
245 secattr = &secattr_storage;
246 netlbl_secattr_init(secattr);
247 rc = security_netlbl_sid_to_secattr(&selinux_state, sid,
248 secattr);
249 if (rc != 0)
250 goto skbuff_setsid_return;
251 }
252
253 rc = netlbl_skbuff_setattr(skb, family, secattr);
254
255 skbuff_setsid_return:
256 if (secattr == &secattr_storage)
257 netlbl_secattr_destroy(secattr);
258 return rc;
259 }
260
261
262
263
264
265
266
267
268
269
270
271 int selinux_netlbl_sctp_assoc_request(struct sctp_endpoint *ep,
272 struct sk_buff *skb)
273 {
274 int rc;
275 struct netlbl_lsm_secattr secattr;
276 struct sk_security_struct *sksec = ep->base.sk->sk_security;
277 struct sockaddr_in addr4;
278 struct sockaddr_in6 addr6;
279
280 if (ep->base.sk->sk_family != PF_INET &&
281 ep->base.sk->sk_family != PF_INET6)
282 return 0;
283
284 netlbl_secattr_init(&secattr);
285 rc = security_netlbl_sid_to_secattr(&selinux_state,
286 ep->secid, &secattr);
287 if (rc != 0)
288 goto assoc_request_return;
289
290
291
292
293 if (ip_hdr(skb)->version == 4) {
294 addr4.sin_family = AF_INET;
295 addr4.sin_addr.s_addr = ip_hdr(skb)->saddr;
296 rc = netlbl_conn_setattr(ep->base.sk, (void *)&addr4, &secattr);
297 } else if (IS_ENABLED(CONFIG_IPV6) && ip_hdr(skb)->version == 6) {
298 addr6.sin6_family = AF_INET6;
299 addr6.sin6_addr = ipv6_hdr(skb)->saddr;
300 rc = netlbl_conn_setattr(ep->base.sk, (void *)&addr6, &secattr);
301 } else {
302 rc = -EAFNOSUPPORT;
303 }
304
305 if (rc == 0)
306 sksec->nlbl_state = NLBL_LABELED;
307
308 assoc_request_return:
309 netlbl_secattr_destroy(&secattr);
310 return rc;
311 }
312
313
314
315
316
317
318
319
320
321
322
323
324 int selinux_netlbl_inet_conn_request(struct request_sock *req, u16 family)
325 {
326 int rc;
327 struct netlbl_lsm_secattr secattr;
328
329 if (family != PF_INET && family != PF_INET6)
330 return 0;
331
332 netlbl_secattr_init(&secattr);
333 rc = security_netlbl_sid_to_secattr(&selinux_state, req->secid,
334 &secattr);
335 if (rc != 0)
336 goto inet_conn_request_return;
337 rc = netlbl_req_setattr(req, &secattr);
338 inet_conn_request_return:
339 netlbl_secattr_destroy(&secattr);
340 return rc;
341 }
342
343
344
345
346
347
348
349
350
351
352
353 void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family)
354 {
355 struct sk_security_struct *sksec = sk->sk_security;
356
357 if (family == PF_INET)
358 sksec->nlbl_state = NLBL_LABELED;
359 else
360 sksec->nlbl_state = NLBL_UNSET;
361 }
362
363
364
365
366
367
368
369
370
371 void selinux_netlbl_sctp_sk_clone(struct sock *sk, struct sock *newsk)
372 {
373 struct sk_security_struct *sksec = sk->sk_security;
374 struct sk_security_struct *newsksec = newsk->sk_security;
375
376 newsksec->nlbl_state = sksec->nlbl_state;
377 }
378
379
380
381
382
383
384
385
386
387
388
389 int selinux_netlbl_socket_post_create(struct sock *sk, u16 family)
390 {
391 int rc;
392 struct sk_security_struct *sksec = sk->sk_security;
393 struct netlbl_lsm_secattr *secattr;
394
395 if (family != PF_INET && family != PF_INET6)
396 return 0;
397
398 secattr = selinux_netlbl_sock_genattr(sk);
399 if (secattr == NULL)
400 return -ENOMEM;
401 rc = netlbl_sock_setattr(sk, family, secattr);
402 switch (rc) {
403 case 0:
404 sksec->nlbl_state = NLBL_LABELED;
405 break;
406 case -EDESTADDRREQ:
407 sksec->nlbl_state = NLBL_REQSKB;
408 rc = 0;
409 break;
410 }
411
412 return rc;
413 }
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428 int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
429 struct sk_buff *skb,
430 u16 family,
431 struct common_audit_data *ad)
432 {
433 int rc;
434 u32 nlbl_sid;
435 u32 perm;
436 struct netlbl_lsm_secattr secattr;
437
438 if (!netlbl_enabled())
439 return 0;
440
441 netlbl_secattr_init(&secattr);
442 rc = netlbl_skbuff_getattr(skb, family, &secattr);
443 if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE)
444 rc = selinux_netlbl_sidlookup_cached(skb, family,
445 &secattr, &nlbl_sid);
446 else
447 nlbl_sid = SECINITSID_UNLABELED;
448 netlbl_secattr_destroy(&secattr);
449 if (rc != 0)
450 return rc;
451
452 switch (sksec->sclass) {
453 case SECCLASS_UDP_SOCKET:
454 perm = UDP_SOCKET__RECVFROM;
455 break;
456 case SECCLASS_TCP_SOCKET:
457 perm = TCP_SOCKET__RECVFROM;
458 break;
459 default:
460 perm = RAWIP_SOCKET__RECVFROM;
461 }
462
463 rc = avc_has_perm(&selinux_state,
464 sksec->sid, nlbl_sid, sksec->sclass, perm, ad);
465 if (rc == 0)
466 return 0;
467
468 if (nlbl_sid != SECINITSID_UNLABELED)
469 netlbl_skbuff_err(skb, family, rc, 0);
470 return rc;
471 }
472
473
474
475
476
477
478
479
480
481
482 static inline int selinux_netlbl_option(int level, int optname)
483 {
484 return (level == IPPROTO_IP && optname == IP_OPTIONS) ||
485 (level == IPPROTO_IPV6 && optname == IPV6_HOPOPTS);
486 }
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501 int selinux_netlbl_socket_setsockopt(struct socket *sock,
502 int level,
503 int optname)
504 {
505 int rc = 0;
506 struct sock *sk = sock->sk;
507 struct sk_security_struct *sksec = sk->sk_security;
508 struct netlbl_lsm_secattr secattr;
509
510 if (selinux_netlbl_option(level, optname) &&
511 (sksec->nlbl_state == NLBL_LABELED ||
512 sksec->nlbl_state == NLBL_CONNLABELED)) {
513 netlbl_secattr_init(&secattr);
514 lock_sock(sk);
515
516
517
518 rc = netlbl_sock_getattr(sk, &secattr);
519 release_sock(sk);
520 if (rc == 0)
521 rc = -EACCES;
522 else if (rc == -ENOMSG)
523 rc = 0;
524 netlbl_secattr_destroy(&secattr);
525 }
526
527 return rc;
528 }
529
530
531
532
533
534
535
536
537
538
539
540
541 static int selinux_netlbl_socket_connect_helper(struct sock *sk,
542 struct sockaddr *addr)
543 {
544 int rc;
545 struct sk_security_struct *sksec = sk->sk_security;
546 struct netlbl_lsm_secattr *secattr;
547
548
549
550
551 if (addr->sa_family == AF_UNSPEC) {
552 netlbl_sock_delattr(sk);
553 sksec->nlbl_state = NLBL_REQSKB;
554 rc = 0;
555 return rc;
556 }
557 secattr = selinux_netlbl_sock_genattr(sk);
558 if (secattr == NULL) {
559 rc = -ENOMEM;
560 return rc;
561 }
562 rc = netlbl_conn_setattr(sk, addr, secattr);
563 if (rc == 0)
564 sksec->nlbl_state = NLBL_CONNLABELED;
565
566 return rc;
567 }
568
569
570
571
572
573
574
575
576
577
578
579
580
581 int selinux_netlbl_socket_connect_locked(struct sock *sk,
582 struct sockaddr *addr)
583 {
584 struct sk_security_struct *sksec = sk->sk_security;
585
586 if (sksec->nlbl_state != NLBL_REQSKB &&
587 sksec->nlbl_state != NLBL_CONNLABELED)
588 return 0;
589
590 return selinux_netlbl_socket_connect_helper(sk, addr);
591 }
592
593
594
595
596
597
598
599
600
601
602
603 int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr)
604 {
605 int rc;
606
607 lock_sock(sk);
608 rc = selinux_netlbl_socket_connect_locked(sk, addr);
609 release_sock(sk);
610
611 return rc;
612 }