Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/net/netlabel/netlabel_kapi.c
15109 views
1
/*
2
* NetLabel Kernel API
3
*
4
* This file defines the kernel API for the NetLabel system. The NetLabel
5
* system manages static and dynamic label mappings for network protocols such
6
* as CIPSO and RIPSO.
7
*
8
* Author: Paul Moore <[email protected]>
9
*
10
*/
11
12
/*
13
* (c) Copyright Hewlett-Packard Development Company, L.P., 2006, 2008
14
*
15
* This program is free software; you can redistribute it and/or modify
16
* it under the terms of the GNU General Public License as published by
17
* the Free Software Foundation; either version 2 of the License, or
18
* (at your option) any later version.
19
*
20
* This program is distributed in the hope that it will be useful,
21
* but WITHOUT ANY WARRANTY; without even the implied warranty of
22
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
23
* the GNU General Public License for more details.
24
*
25
* You should have received a copy of the GNU General Public License
26
* along with this program; if not, write to the Free Software
27
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28
*
29
*/
30
31
#include <linux/init.h>
32
#include <linux/types.h>
33
#include <linux/slab.h>
34
#include <linux/audit.h>
35
#include <linux/in.h>
36
#include <linux/in6.h>
37
#include <net/ip.h>
38
#include <net/ipv6.h>
39
#include <net/netlabel.h>
40
#include <net/cipso_ipv4.h>
41
#include <asm/bug.h>
42
#include <asm/atomic.h>
43
44
#include "netlabel_domainhash.h"
45
#include "netlabel_unlabeled.h"
46
#include "netlabel_cipso_v4.h"
47
#include "netlabel_user.h"
48
#include "netlabel_mgmt.h"
49
#include "netlabel_addrlist.h"
50
51
/*
52
* Configuration Functions
53
*/
54
55
/**
56
* netlbl_cfg_map_del - Remove a NetLabel/LSM domain mapping
57
* @domain: the domain mapping to remove
58
* @family: address family
59
* @addr: IP address
60
* @mask: IP address mask
61
* @audit_info: NetLabel audit information
62
*
63
* Description:
64
* Removes a NetLabel/LSM domain mapping. A @domain value of NULL causes the
65
* default domain mapping to be removed. Returns zero on success, negative
66
* values on failure.
67
*
68
*/
69
int netlbl_cfg_map_del(const char *domain,
70
u16 family,
71
const void *addr,
72
const void *mask,
73
struct netlbl_audit *audit_info)
74
{
75
if (addr == NULL && mask == NULL) {
76
return netlbl_domhsh_remove(domain, audit_info);
77
} else if (addr != NULL && mask != NULL) {
78
switch (family) {
79
case AF_INET:
80
return netlbl_domhsh_remove_af4(domain, addr, mask,
81
audit_info);
82
default:
83
return -EPFNOSUPPORT;
84
}
85
} else
86
return -EINVAL;
87
}
88
89
/**
90
* netlbl_cfg_unlbl_map_add - Add a new unlabeled mapping
91
* @domain: the domain mapping to add
92
* @family: address family
93
* @addr: IP address
94
* @mask: IP address mask
95
* @audit_info: NetLabel audit information
96
*
97
* Description:
98
* Adds a new unlabeled NetLabel/LSM domain mapping. A @domain value of NULL
99
* causes a new default domain mapping to be added. Returns zero on success,
100
* negative values on failure.
101
*
102
*/
103
int netlbl_cfg_unlbl_map_add(const char *domain,
104
u16 family,
105
const void *addr,
106
const void *mask,
107
struct netlbl_audit *audit_info)
108
{
109
int ret_val = -ENOMEM;
110
struct netlbl_dom_map *entry;
111
struct netlbl_domaddr_map *addrmap = NULL;
112
struct netlbl_domaddr4_map *map4 = NULL;
113
struct netlbl_domaddr6_map *map6 = NULL;
114
const struct in_addr *addr4, *mask4;
115
const struct in6_addr *addr6, *mask6;
116
117
entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
118
if (entry == NULL)
119
return -ENOMEM;
120
if (domain != NULL) {
121
entry->domain = kstrdup(domain, GFP_ATOMIC);
122
if (entry->domain == NULL)
123
goto cfg_unlbl_map_add_failure;
124
}
125
126
if (addr == NULL && mask == NULL)
127
entry->type = NETLBL_NLTYPE_UNLABELED;
128
else if (addr != NULL && mask != NULL) {
129
addrmap = kzalloc(sizeof(*addrmap), GFP_ATOMIC);
130
if (addrmap == NULL)
131
goto cfg_unlbl_map_add_failure;
132
INIT_LIST_HEAD(&addrmap->list4);
133
INIT_LIST_HEAD(&addrmap->list6);
134
135
switch (family) {
136
case AF_INET:
137
addr4 = addr;
138
mask4 = mask;
139
map4 = kzalloc(sizeof(*map4), GFP_ATOMIC);
140
if (map4 == NULL)
141
goto cfg_unlbl_map_add_failure;
142
map4->type = NETLBL_NLTYPE_UNLABELED;
143
map4->list.addr = addr4->s_addr & mask4->s_addr;
144
map4->list.mask = mask4->s_addr;
145
map4->list.valid = 1;
146
ret_val = netlbl_af4list_add(&map4->list,
147
&addrmap->list4);
148
if (ret_val != 0)
149
goto cfg_unlbl_map_add_failure;
150
break;
151
case AF_INET6:
152
addr6 = addr;
153
mask6 = mask;
154
map6 = kzalloc(sizeof(*map6), GFP_ATOMIC);
155
if (map6 == NULL)
156
goto cfg_unlbl_map_add_failure;
157
map6->type = NETLBL_NLTYPE_UNLABELED;
158
ipv6_addr_copy(&map6->list.addr, addr6);
159
map6->list.addr.s6_addr32[0] &= mask6->s6_addr32[0];
160
map6->list.addr.s6_addr32[1] &= mask6->s6_addr32[1];
161
map6->list.addr.s6_addr32[2] &= mask6->s6_addr32[2];
162
map6->list.addr.s6_addr32[3] &= mask6->s6_addr32[3];
163
ipv6_addr_copy(&map6->list.mask, mask6);
164
map6->list.valid = 1;
165
ret_val = netlbl_af4list_add(&map4->list,
166
&addrmap->list4);
167
if (ret_val != 0)
168
goto cfg_unlbl_map_add_failure;
169
break;
170
default:
171
goto cfg_unlbl_map_add_failure;
172
break;
173
}
174
175
entry->type_def.addrsel = addrmap;
176
entry->type = NETLBL_NLTYPE_ADDRSELECT;
177
} else {
178
ret_val = -EINVAL;
179
goto cfg_unlbl_map_add_failure;
180
}
181
182
ret_val = netlbl_domhsh_add(entry, audit_info);
183
if (ret_val != 0)
184
goto cfg_unlbl_map_add_failure;
185
186
return 0;
187
188
cfg_unlbl_map_add_failure:
189
kfree(entry->domain);
190
kfree(entry);
191
kfree(addrmap);
192
kfree(map4);
193
kfree(map6);
194
return ret_val;
195
}
196
197
198
/**
199
* netlbl_cfg_unlbl_static_add - Adds a new static label
200
* @net: network namespace
201
* @dev_name: interface name
202
* @addr: IP address in network byte order (struct in[6]_addr)
203
* @mask: address mask in network byte order (struct in[6]_addr)
204
* @family: address family
205
* @secid: LSM secid value for the entry
206
* @audit_info: NetLabel audit information
207
*
208
* Description:
209
* Adds a new NetLabel static label to be used when protocol provided labels
210
* are not present on incoming traffic. If @dev_name is NULL then the default
211
* interface will be used. Returns zero on success, negative values on failure.
212
*
213
*/
214
int netlbl_cfg_unlbl_static_add(struct net *net,
215
const char *dev_name,
216
const void *addr,
217
const void *mask,
218
u16 family,
219
u32 secid,
220
struct netlbl_audit *audit_info)
221
{
222
u32 addr_len;
223
224
switch (family) {
225
case AF_INET:
226
addr_len = sizeof(struct in_addr);
227
break;
228
case AF_INET6:
229
addr_len = sizeof(struct in6_addr);
230
break;
231
default:
232
return -EPFNOSUPPORT;
233
}
234
235
return netlbl_unlhsh_add(net,
236
dev_name, addr, mask, addr_len,
237
secid, audit_info);
238
}
239
240
/**
241
* netlbl_cfg_unlbl_static_del - Removes an existing static label
242
* @net: network namespace
243
* @dev_name: interface name
244
* @addr: IP address in network byte order (struct in[6]_addr)
245
* @mask: address mask in network byte order (struct in[6]_addr)
246
* @family: address family
247
* @secid: LSM secid value for the entry
248
* @audit_info: NetLabel audit information
249
*
250
* Description:
251
* Removes an existing NetLabel static label used when protocol provided labels
252
* are not present on incoming traffic. If @dev_name is NULL then the default
253
* interface will be used. Returns zero on success, negative values on failure.
254
*
255
*/
256
int netlbl_cfg_unlbl_static_del(struct net *net,
257
const char *dev_name,
258
const void *addr,
259
const void *mask,
260
u16 family,
261
struct netlbl_audit *audit_info)
262
{
263
u32 addr_len;
264
265
switch (family) {
266
case AF_INET:
267
addr_len = sizeof(struct in_addr);
268
break;
269
case AF_INET6:
270
addr_len = sizeof(struct in6_addr);
271
break;
272
default:
273
return -EPFNOSUPPORT;
274
}
275
276
return netlbl_unlhsh_remove(net,
277
dev_name, addr, mask, addr_len,
278
audit_info);
279
}
280
281
/**
282
* netlbl_cfg_cipsov4_add - Add a new CIPSOv4 DOI definition
283
* @doi_def: CIPSO DOI definition
284
* @audit_info: NetLabel audit information
285
*
286
* Description:
287
* Add a new CIPSO DOI definition as defined by @doi_def. Returns zero on
288
* success and negative values on failure.
289
*
290
*/
291
int netlbl_cfg_cipsov4_add(struct cipso_v4_doi *doi_def,
292
struct netlbl_audit *audit_info)
293
{
294
return cipso_v4_doi_add(doi_def, audit_info);
295
}
296
297
/**
298
* netlbl_cfg_cipsov4_del - Remove an existing CIPSOv4 DOI definition
299
* @doi: CIPSO DOI
300
* @audit_info: NetLabel audit information
301
*
302
* Description:
303
* Remove an existing CIPSO DOI definition matching @doi. Returns zero on
304
* success and negative values on failure.
305
*
306
*/
307
void netlbl_cfg_cipsov4_del(u32 doi, struct netlbl_audit *audit_info)
308
{
309
cipso_v4_doi_remove(doi, audit_info);
310
}
311
312
/**
313
* netlbl_cfg_cipsov4_map_add - Add a new CIPSOv4 DOI mapping
314
* @doi: the CIPSO DOI
315
* @domain: the domain mapping to add
316
* @addr: IP address
317
* @mask: IP address mask
318
* @audit_info: NetLabel audit information
319
*
320
* Description:
321
* Add a new NetLabel/LSM domain mapping for the given CIPSO DOI to the NetLabel
322
* subsystem. A @domain value of NULL adds a new default domain mapping.
323
* Returns zero on success, negative values on failure.
324
*
325
*/
326
int netlbl_cfg_cipsov4_map_add(u32 doi,
327
const char *domain,
328
const struct in_addr *addr,
329
const struct in_addr *mask,
330
struct netlbl_audit *audit_info)
331
{
332
int ret_val = -ENOMEM;
333
struct cipso_v4_doi *doi_def;
334
struct netlbl_dom_map *entry;
335
struct netlbl_domaddr_map *addrmap = NULL;
336
struct netlbl_domaddr4_map *addrinfo = NULL;
337
338
doi_def = cipso_v4_doi_getdef(doi);
339
if (doi_def == NULL)
340
return -ENOENT;
341
342
entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
343
if (entry == NULL)
344
return -ENOMEM;
345
if (domain != NULL) {
346
entry->domain = kstrdup(domain, GFP_ATOMIC);
347
if (entry->domain == NULL)
348
goto cfg_cipsov4_map_add_failure;
349
}
350
351
if (addr == NULL && mask == NULL) {
352
entry->type_def.cipsov4 = doi_def;
353
entry->type = NETLBL_NLTYPE_CIPSOV4;
354
} else if (addr != NULL && mask != NULL) {
355
addrmap = kzalloc(sizeof(*addrmap), GFP_ATOMIC);
356
if (addrmap == NULL)
357
goto cfg_cipsov4_map_add_failure;
358
INIT_LIST_HEAD(&addrmap->list4);
359
INIT_LIST_HEAD(&addrmap->list6);
360
361
addrinfo = kzalloc(sizeof(*addrinfo), GFP_ATOMIC);
362
if (addrinfo == NULL)
363
goto cfg_cipsov4_map_add_failure;
364
addrinfo->type_def.cipsov4 = doi_def;
365
addrinfo->type = NETLBL_NLTYPE_CIPSOV4;
366
addrinfo->list.addr = addr->s_addr & mask->s_addr;
367
addrinfo->list.mask = mask->s_addr;
368
addrinfo->list.valid = 1;
369
ret_val = netlbl_af4list_add(&addrinfo->list, &addrmap->list4);
370
if (ret_val != 0)
371
goto cfg_cipsov4_map_add_failure;
372
373
entry->type_def.addrsel = addrmap;
374
entry->type = NETLBL_NLTYPE_ADDRSELECT;
375
} else {
376
ret_val = -EINVAL;
377
goto cfg_cipsov4_map_add_failure;
378
}
379
380
ret_val = netlbl_domhsh_add(entry, audit_info);
381
if (ret_val != 0)
382
goto cfg_cipsov4_map_add_failure;
383
384
return 0;
385
386
cfg_cipsov4_map_add_failure:
387
cipso_v4_doi_putdef(doi_def);
388
kfree(entry->domain);
389
kfree(entry);
390
kfree(addrmap);
391
kfree(addrinfo);
392
return ret_val;
393
}
394
395
/*
396
* Security Attribute Functions
397
*/
398
399
/**
400
* netlbl_secattr_catmap_walk - Walk a LSM secattr catmap looking for a bit
401
* @catmap: the category bitmap
402
* @offset: the offset to start searching at, in bits
403
*
404
* Description:
405
* This function walks a LSM secattr category bitmap starting at @offset and
406
* returns the spot of the first set bit or -ENOENT if no bits are set.
407
*
408
*/
409
int netlbl_secattr_catmap_walk(struct netlbl_lsm_secattr_catmap *catmap,
410
u32 offset)
411
{
412
struct netlbl_lsm_secattr_catmap *iter = catmap;
413
u32 node_idx;
414
u32 node_bit;
415
NETLBL_CATMAP_MAPTYPE bitmap;
416
417
if (offset > iter->startbit) {
418
while (offset >= (iter->startbit + NETLBL_CATMAP_SIZE)) {
419
iter = iter->next;
420
if (iter == NULL)
421
return -ENOENT;
422
}
423
node_idx = (offset - iter->startbit) / NETLBL_CATMAP_MAPSIZE;
424
node_bit = offset - iter->startbit -
425
(NETLBL_CATMAP_MAPSIZE * node_idx);
426
} else {
427
node_idx = 0;
428
node_bit = 0;
429
}
430
bitmap = iter->bitmap[node_idx] >> node_bit;
431
432
for (;;) {
433
if (bitmap != 0) {
434
while ((bitmap & NETLBL_CATMAP_BIT) == 0) {
435
bitmap >>= 1;
436
node_bit++;
437
}
438
return iter->startbit +
439
(NETLBL_CATMAP_MAPSIZE * node_idx) + node_bit;
440
}
441
if (++node_idx >= NETLBL_CATMAP_MAPCNT) {
442
if (iter->next != NULL) {
443
iter = iter->next;
444
node_idx = 0;
445
} else
446
return -ENOENT;
447
}
448
bitmap = iter->bitmap[node_idx];
449
node_bit = 0;
450
}
451
452
return -ENOENT;
453
}
454
455
/**
456
* netlbl_secattr_catmap_walk_rng - Find the end of a string of set bits
457
* @catmap: the category bitmap
458
* @offset: the offset to start searching at, in bits
459
*
460
* Description:
461
* This function walks a LSM secattr category bitmap starting at @offset and
462
* returns the spot of the first cleared bit or -ENOENT if the offset is past
463
* the end of the bitmap.
464
*
465
*/
466
int netlbl_secattr_catmap_walk_rng(struct netlbl_lsm_secattr_catmap *catmap,
467
u32 offset)
468
{
469
struct netlbl_lsm_secattr_catmap *iter = catmap;
470
u32 node_idx;
471
u32 node_bit;
472
NETLBL_CATMAP_MAPTYPE bitmask;
473
NETLBL_CATMAP_MAPTYPE bitmap;
474
475
if (offset > iter->startbit) {
476
while (offset >= (iter->startbit + NETLBL_CATMAP_SIZE)) {
477
iter = iter->next;
478
if (iter == NULL)
479
return -ENOENT;
480
}
481
node_idx = (offset - iter->startbit) / NETLBL_CATMAP_MAPSIZE;
482
node_bit = offset - iter->startbit -
483
(NETLBL_CATMAP_MAPSIZE * node_idx);
484
} else {
485
node_idx = 0;
486
node_bit = 0;
487
}
488
bitmask = NETLBL_CATMAP_BIT << node_bit;
489
490
for (;;) {
491
bitmap = iter->bitmap[node_idx];
492
while (bitmask != 0 && (bitmap & bitmask) != 0) {
493
bitmask <<= 1;
494
node_bit++;
495
}
496
497
if (bitmask != 0)
498
return iter->startbit +
499
(NETLBL_CATMAP_MAPSIZE * node_idx) +
500
node_bit - 1;
501
else if (++node_idx >= NETLBL_CATMAP_MAPCNT) {
502
if (iter->next == NULL)
503
return iter->startbit + NETLBL_CATMAP_SIZE - 1;
504
iter = iter->next;
505
node_idx = 0;
506
}
507
bitmask = NETLBL_CATMAP_BIT;
508
node_bit = 0;
509
}
510
511
return -ENOENT;
512
}
513
514
/**
515
* netlbl_secattr_catmap_setbit - Set a bit in a LSM secattr catmap
516
* @catmap: the category bitmap
517
* @bit: the bit to set
518
* @flags: memory allocation flags
519
*
520
* Description:
521
* Set the bit specified by @bit in @catmap. Returns zero on success,
522
* negative values on failure.
523
*
524
*/
525
int netlbl_secattr_catmap_setbit(struct netlbl_lsm_secattr_catmap *catmap,
526
u32 bit,
527
gfp_t flags)
528
{
529
struct netlbl_lsm_secattr_catmap *iter = catmap;
530
u32 node_bit;
531
u32 node_idx;
532
533
while (iter->next != NULL &&
534
bit >= (iter->startbit + NETLBL_CATMAP_SIZE))
535
iter = iter->next;
536
if (bit >= (iter->startbit + NETLBL_CATMAP_SIZE)) {
537
iter->next = netlbl_secattr_catmap_alloc(flags);
538
if (iter->next == NULL)
539
return -ENOMEM;
540
iter = iter->next;
541
iter->startbit = bit & ~(NETLBL_CATMAP_SIZE - 1);
542
}
543
544
/* gcc always rounds to zero when doing integer division */
545
node_idx = (bit - iter->startbit) / NETLBL_CATMAP_MAPSIZE;
546
node_bit = bit - iter->startbit - (NETLBL_CATMAP_MAPSIZE * node_idx);
547
iter->bitmap[node_idx] |= NETLBL_CATMAP_BIT << node_bit;
548
549
return 0;
550
}
551
552
/**
553
* netlbl_secattr_catmap_setrng - Set a range of bits in a LSM secattr catmap
554
* @catmap: the category bitmap
555
* @start: the starting bit
556
* @end: the last bit in the string
557
* @flags: memory allocation flags
558
*
559
* Description:
560
* Set a range of bits, starting at @start and ending with @end. Returns zero
561
* on success, negative values on failure.
562
*
563
*/
564
int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap *catmap,
565
u32 start,
566
u32 end,
567
gfp_t flags)
568
{
569
int ret_val = 0;
570
struct netlbl_lsm_secattr_catmap *iter = catmap;
571
u32 iter_max_spot;
572
u32 spot;
573
574
/* XXX - This could probably be made a bit faster by combining writes
575
* to the catmap instead of setting a single bit each time, but for
576
* right now skipping to the start of the range in the catmap should
577
* be a nice improvement over calling the individual setbit function
578
* repeatedly from a loop. */
579
580
while (iter->next != NULL &&
581
start >= (iter->startbit + NETLBL_CATMAP_SIZE))
582
iter = iter->next;
583
iter_max_spot = iter->startbit + NETLBL_CATMAP_SIZE;
584
585
for (spot = start; spot <= end && ret_val == 0; spot++) {
586
if (spot >= iter_max_spot && iter->next != NULL) {
587
iter = iter->next;
588
iter_max_spot = iter->startbit + NETLBL_CATMAP_SIZE;
589
}
590
ret_val = netlbl_secattr_catmap_setbit(iter, spot, GFP_ATOMIC);
591
}
592
593
return ret_val;
594
}
595
596
/*
597
* LSM Functions
598
*/
599
600
/**
601
* netlbl_enabled - Determine if the NetLabel subsystem is enabled
602
*
603
* Description:
604
* The LSM can use this function to determine if it should use NetLabel
605
* security attributes in it's enforcement mechanism. Currently, NetLabel is
606
* considered to be enabled when it's configuration contains a valid setup for
607
* at least one labeled protocol (i.e. NetLabel can understand incoming
608
* labeled packets of at least one type); otherwise NetLabel is considered to
609
* be disabled.
610
*
611
*/
612
int netlbl_enabled(void)
613
{
614
/* At some point we probably want to expose this mechanism to the user
615
* as well so that admins can toggle NetLabel regardless of the
616
* configuration */
617
return (atomic_read(&netlabel_mgmt_protocount) > 0);
618
}
619
620
/**
621
* netlbl_sock_setattr - Label a socket using the correct protocol
622
* @sk: the socket to label
623
* @family: protocol family
624
* @secattr: the security attributes
625
*
626
* Description:
627
* Attach the correct label to the given socket using the security attributes
628
* specified in @secattr. This function requires exclusive access to @sk,
629
* which means it either needs to be in the process of being created or locked.
630
* Returns zero on success, -EDESTADDRREQ if the domain is configured to use
631
* network address selectors (can't blindly label the socket), and negative
632
* values on all other failures.
633
*
634
*/
635
int netlbl_sock_setattr(struct sock *sk,
636
u16 family,
637
const struct netlbl_lsm_secattr *secattr)
638
{
639
int ret_val;
640
struct netlbl_dom_map *dom_entry;
641
642
rcu_read_lock();
643
dom_entry = netlbl_domhsh_getentry(secattr->domain);
644
if (dom_entry == NULL) {
645
ret_val = -ENOENT;
646
goto socket_setattr_return;
647
}
648
switch (family) {
649
case AF_INET:
650
switch (dom_entry->type) {
651
case NETLBL_NLTYPE_ADDRSELECT:
652
ret_val = -EDESTADDRREQ;
653
break;
654
case NETLBL_NLTYPE_CIPSOV4:
655
ret_val = cipso_v4_sock_setattr(sk,
656
dom_entry->type_def.cipsov4,
657
secattr);
658
break;
659
case NETLBL_NLTYPE_UNLABELED:
660
ret_val = 0;
661
break;
662
default:
663
ret_val = -ENOENT;
664
}
665
break;
666
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
667
case AF_INET6:
668
/* since we don't support any IPv6 labeling protocols right
669
* now we can optimize everything away until we do */
670
ret_val = 0;
671
break;
672
#endif /* IPv6 */
673
default:
674
ret_val = -EPROTONOSUPPORT;
675
}
676
677
socket_setattr_return:
678
rcu_read_unlock();
679
return ret_val;
680
}
681
682
/**
683
* netlbl_sock_delattr - Delete all the NetLabel labels on a socket
684
* @sk: the socket
685
*
686
* Description:
687
* Remove all the NetLabel labeling from @sk. The caller is responsible for
688
* ensuring that @sk is locked.
689
*
690
*/
691
void netlbl_sock_delattr(struct sock *sk)
692
{
693
cipso_v4_sock_delattr(sk);
694
}
695
696
/**
697
* netlbl_sock_getattr - Determine the security attributes of a sock
698
* @sk: the sock
699
* @secattr: the security attributes
700
*
701
* Description:
702
* Examines the given sock to see if any NetLabel style labeling has been
703
* applied to the sock, if so it parses the socket label and returns the
704
* security attributes in @secattr. Returns zero on success, negative values
705
* on failure.
706
*
707
*/
708
int netlbl_sock_getattr(struct sock *sk,
709
struct netlbl_lsm_secattr *secattr)
710
{
711
int ret_val;
712
713
switch (sk->sk_family) {
714
case AF_INET:
715
ret_val = cipso_v4_sock_getattr(sk, secattr);
716
break;
717
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
718
case AF_INET6:
719
ret_val = -ENOMSG;
720
break;
721
#endif /* IPv6 */
722
default:
723
ret_val = -EPROTONOSUPPORT;
724
}
725
726
return ret_val;
727
}
728
729
/**
730
* netlbl_conn_setattr - Label a connected socket using the correct protocol
731
* @sk: the socket to label
732
* @addr: the destination address
733
* @secattr: the security attributes
734
*
735
* Description:
736
* Attach the correct label to the given connected socket using the security
737
* attributes specified in @secattr. The caller is responsible for ensuring
738
* that @sk is locked. Returns zero on success, negative values on failure.
739
*
740
*/
741
int netlbl_conn_setattr(struct sock *sk,
742
struct sockaddr *addr,
743
const struct netlbl_lsm_secattr *secattr)
744
{
745
int ret_val;
746
struct sockaddr_in *addr4;
747
struct netlbl_domaddr4_map *af4_entry;
748
749
rcu_read_lock();
750
switch (addr->sa_family) {
751
case AF_INET:
752
addr4 = (struct sockaddr_in *)addr;
753
af4_entry = netlbl_domhsh_getentry_af4(secattr->domain,
754
addr4->sin_addr.s_addr);
755
if (af4_entry == NULL) {
756
ret_val = -ENOENT;
757
goto conn_setattr_return;
758
}
759
switch (af4_entry->type) {
760
case NETLBL_NLTYPE_CIPSOV4:
761
ret_val = cipso_v4_sock_setattr(sk,
762
af4_entry->type_def.cipsov4,
763
secattr);
764
break;
765
case NETLBL_NLTYPE_UNLABELED:
766
/* just delete the protocols we support for right now
767
* but we could remove other protocols if needed */
768
cipso_v4_sock_delattr(sk);
769
ret_val = 0;
770
break;
771
default:
772
ret_val = -ENOENT;
773
}
774
break;
775
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
776
case AF_INET6:
777
/* since we don't support any IPv6 labeling protocols right
778
* now we can optimize everything away until we do */
779
ret_val = 0;
780
break;
781
#endif /* IPv6 */
782
default:
783
ret_val = -EPROTONOSUPPORT;
784
}
785
786
conn_setattr_return:
787
rcu_read_unlock();
788
return ret_val;
789
}
790
791
/**
792
* netlbl_req_setattr - Label a request socket using the correct protocol
793
* @req: the request socket to label
794
* @secattr: the security attributes
795
*
796
* Description:
797
* Attach the correct label to the given socket using the security attributes
798
* specified in @secattr. Returns zero on success, negative values on failure.
799
*
800
*/
801
int netlbl_req_setattr(struct request_sock *req,
802
const struct netlbl_lsm_secattr *secattr)
803
{
804
int ret_val;
805
struct netlbl_dom_map *dom_entry;
806
struct netlbl_domaddr4_map *af4_entry;
807
u32 proto_type;
808
struct cipso_v4_doi *proto_cv4;
809
810
rcu_read_lock();
811
dom_entry = netlbl_domhsh_getentry(secattr->domain);
812
if (dom_entry == NULL) {
813
ret_val = -ENOENT;
814
goto req_setattr_return;
815
}
816
switch (req->rsk_ops->family) {
817
case AF_INET:
818
if (dom_entry->type == NETLBL_NLTYPE_ADDRSELECT) {
819
struct inet_request_sock *req_inet = inet_rsk(req);
820
af4_entry = netlbl_domhsh_getentry_af4(secattr->domain,
821
req_inet->rmt_addr);
822
if (af4_entry == NULL) {
823
ret_val = -ENOENT;
824
goto req_setattr_return;
825
}
826
proto_type = af4_entry->type;
827
proto_cv4 = af4_entry->type_def.cipsov4;
828
} else {
829
proto_type = dom_entry->type;
830
proto_cv4 = dom_entry->type_def.cipsov4;
831
}
832
switch (proto_type) {
833
case NETLBL_NLTYPE_CIPSOV4:
834
ret_val = cipso_v4_req_setattr(req, proto_cv4, secattr);
835
break;
836
case NETLBL_NLTYPE_UNLABELED:
837
/* just delete the protocols we support for right now
838
* but we could remove other protocols if needed */
839
cipso_v4_req_delattr(req);
840
ret_val = 0;
841
break;
842
default:
843
ret_val = -ENOENT;
844
}
845
break;
846
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
847
case AF_INET6:
848
/* since we don't support any IPv6 labeling protocols right
849
* now we can optimize everything away until we do */
850
ret_val = 0;
851
break;
852
#endif /* IPv6 */
853
default:
854
ret_val = -EPROTONOSUPPORT;
855
}
856
857
req_setattr_return:
858
rcu_read_unlock();
859
return ret_val;
860
}
861
862
/**
863
* netlbl_req_delattr - Delete all the NetLabel labels on a socket
864
* @req: the socket
865
*
866
* Description:
867
* Remove all the NetLabel labeling from @req.
868
*
869
*/
870
void netlbl_req_delattr(struct request_sock *req)
871
{
872
cipso_v4_req_delattr(req);
873
}
874
875
/**
876
* netlbl_skbuff_setattr - Label a packet using the correct protocol
877
* @skb: the packet
878
* @family: protocol family
879
* @secattr: the security attributes
880
*
881
* Description:
882
* Attach the correct label to the given packet using the security attributes
883
* specified in @secattr. Returns zero on success, negative values on failure.
884
*
885
*/
886
int netlbl_skbuff_setattr(struct sk_buff *skb,
887
u16 family,
888
const struct netlbl_lsm_secattr *secattr)
889
{
890
int ret_val;
891
struct iphdr *hdr4;
892
struct netlbl_domaddr4_map *af4_entry;
893
894
rcu_read_lock();
895
switch (family) {
896
case AF_INET:
897
hdr4 = ip_hdr(skb);
898
af4_entry = netlbl_domhsh_getentry_af4(secattr->domain,
899
hdr4->daddr);
900
if (af4_entry == NULL) {
901
ret_val = -ENOENT;
902
goto skbuff_setattr_return;
903
}
904
switch (af4_entry->type) {
905
case NETLBL_NLTYPE_CIPSOV4:
906
ret_val = cipso_v4_skbuff_setattr(skb,
907
af4_entry->type_def.cipsov4,
908
secattr);
909
break;
910
case NETLBL_NLTYPE_UNLABELED:
911
/* just delete the protocols we support for right now
912
* but we could remove other protocols if needed */
913
ret_val = cipso_v4_skbuff_delattr(skb);
914
break;
915
default:
916
ret_val = -ENOENT;
917
}
918
break;
919
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
920
case AF_INET6:
921
/* since we don't support any IPv6 labeling protocols right
922
* now we can optimize everything away until we do */
923
ret_val = 0;
924
break;
925
#endif /* IPv6 */
926
default:
927
ret_val = -EPROTONOSUPPORT;
928
}
929
930
skbuff_setattr_return:
931
rcu_read_unlock();
932
return ret_val;
933
}
934
935
/**
936
* netlbl_skbuff_getattr - Determine the security attributes of a packet
937
* @skb: the packet
938
* @family: protocol family
939
* @secattr: the security attributes
940
*
941
* Description:
942
* Examines the given packet to see if a recognized form of packet labeling
943
* is present, if so it parses the packet label and returns the security
944
* attributes in @secattr. Returns zero on success, negative values on
945
* failure.
946
*
947
*/
948
int netlbl_skbuff_getattr(const struct sk_buff *skb,
949
u16 family,
950
struct netlbl_lsm_secattr *secattr)
951
{
952
switch (family) {
953
case AF_INET:
954
if (CIPSO_V4_OPTEXIST(skb) &&
955
cipso_v4_skbuff_getattr(skb, secattr) == 0)
956
return 0;
957
break;
958
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
959
case AF_INET6:
960
break;
961
#endif /* IPv6 */
962
}
963
964
return netlbl_unlabel_getattr(skb, family, secattr);
965
}
966
967
/**
968
* netlbl_skbuff_err - Handle a LSM error on a sk_buff
969
* @skb: the packet
970
* @error: the error code
971
* @gateway: true if host is acting as a gateway, false otherwise
972
*
973
* Description:
974
* Deal with a LSM problem when handling the packet in @skb, typically this is
975
* a permission denied problem (-EACCES). The correct action is determined
976
* according to the packet's labeling protocol.
977
*
978
*/
979
void netlbl_skbuff_err(struct sk_buff *skb, int error, int gateway)
980
{
981
if (CIPSO_V4_OPTEXIST(skb))
982
cipso_v4_error(skb, error, gateway);
983
}
984
985
/**
986
* netlbl_cache_invalidate - Invalidate all of the NetLabel protocol caches
987
*
988
* Description:
989
* For all of the NetLabel protocols that support some form of label mapping
990
* cache, invalidate the cache. Returns zero on success, negative values on
991
* error.
992
*
993
*/
994
void netlbl_cache_invalidate(void)
995
{
996
cipso_v4_cache_invalidate();
997
}
998
999
/**
1000
* netlbl_cache_add - Add an entry to a NetLabel protocol cache
1001
* @skb: the packet
1002
* @secattr: the packet's security attributes
1003
*
1004
* Description:
1005
* Add the LSM security attributes for the given packet to the underlying
1006
* NetLabel protocol's label mapping cache. Returns zero on success, negative
1007
* values on error.
1008
*
1009
*/
1010
int netlbl_cache_add(const struct sk_buff *skb,
1011
const struct netlbl_lsm_secattr *secattr)
1012
{
1013
if ((secattr->flags & NETLBL_SECATTR_CACHE) == 0)
1014
return -ENOMSG;
1015
1016
if (CIPSO_V4_OPTEXIST(skb))
1017
return cipso_v4_cache_add(skb, secattr);
1018
1019
return -ENOMSG;
1020
}
1021
1022
/*
1023
* Protocol Engine Functions
1024
*/
1025
1026
/**
1027
* netlbl_audit_start - Start an audit message
1028
* @type: audit message type
1029
* @audit_info: NetLabel audit information
1030
*
1031
* Description:
1032
* Start an audit message using the type specified in @type and fill the audit
1033
* message with some fields common to all NetLabel audit messages. This
1034
* function should only be used by protocol engines, not LSMs. Returns a
1035
* pointer to the audit buffer on success, NULL on failure.
1036
*
1037
*/
1038
struct audit_buffer *netlbl_audit_start(int type,
1039
struct netlbl_audit *audit_info)
1040
{
1041
return netlbl_audit_start_common(type, audit_info);
1042
}
1043
1044
/*
1045
* Setup Functions
1046
*/
1047
1048
/**
1049
* netlbl_init - Initialize NetLabel
1050
*
1051
* Description:
1052
* Perform the required NetLabel initialization before first use.
1053
*
1054
*/
1055
static int __init netlbl_init(void)
1056
{
1057
int ret_val;
1058
1059
printk(KERN_INFO "NetLabel: Initializing\n");
1060
printk(KERN_INFO "NetLabel: domain hash size = %u\n",
1061
(1 << NETLBL_DOMHSH_BITSIZE));
1062
printk(KERN_INFO "NetLabel: protocols ="
1063
" UNLABELED"
1064
" CIPSOv4"
1065
"\n");
1066
1067
ret_val = netlbl_domhsh_init(NETLBL_DOMHSH_BITSIZE);
1068
if (ret_val != 0)
1069
goto init_failure;
1070
1071
ret_val = netlbl_unlabel_init(NETLBL_UNLHSH_BITSIZE);
1072
if (ret_val != 0)
1073
goto init_failure;
1074
1075
ret_val = netlbl_netlink_init();
1076
if (ret_val != 0)
1077
goto init_failure;
1078
1079
ret_val = netlbl_unlabel_defconf();
1080
if (ret_val != 0)
1081
goto init_failure;
1082
printk(KERN_INFO "NetLabel: unlabeled traffic allowed by default\n");
1083
1084
return 0;
1085
1086
init_failure:
1087
panic("NetLabel: failed to initialize properly (%d)\n", ret_val);
1088
}
1089
1090
subsys_initcall(netlbl_init);
1091
1092