Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/net/netlabel/netlabel_kapi.c
26285 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
* NetLabel Kernel API
4
*
5
* This file defines the kernel API for the NetLabel system. The NetLabel
6
* system manages static and dynamic label mappings for network protocols such
7
* as CIPSO and RIPSO.
8
*
9
* Author: Paul Moore <[email protected]>
10
*/
11
12
/*
13
* (c) Copyright Hewlett-Packard Development Company, L.P., 2006, 2008
14
*/
15
16
#include <linux/init.h>
17
#include <linux/types.h>
18
#include <linux/slab.h>
19
#include <linux/audit.h>
20
#include <linux/in.h>
21
#include <linux/in6.h>
22
#include <net/ip.h>
23
#include <net/ipv6.h>
24
#include <net/netlabel.h>
25
#include <net/cipso_ipv4.h>
26
#include <net/calipso.h>
27
#include <asm/bug.h>
28
#include <linux/atomic.h>
29
30
#include "netlabel_domainhash.h"
31
#include "netlabel_unlabeled.h"
32
#include "netlabel_cipso_v4.h"
33
#include "netlabel_calipso.h"
34
#include "netlabel_user.h"
35
#include "netlabel_mgmt.h"
36
#include "netlabel_addrlist.h"
37
38
/*
39
* Configuration Functions
40
*/
41
42
/**
43
* netlbl_cfg_map_del - Remove a NetLabel/LSM domain mapping
44
* @domain: the domain mapping to remove
45
* @family: address family
46
* @addr: IP address
47
* @mask: IP address mask
48
* @audit_info: NetLabel audit information
49
*
50
* Description:
51
* Removes a NetLabel/LSM domain mapping. A @domain value of NULL causes the
52
* default domain mapping to be removed. Returns zero on success, negative
53
* values on failure.
54
*
55
*/
56
int netlbl_cfg_map_del(const char *domain,
57
u16 family,
58
const void *addr,
59
const void *mask,
60
struct netlbl_audit *audit_info)
61
{
62
if (addr == NULL && mask == NULL) {
63
return netlbl_domhsh_remove(domain, family, audit_info);
64
} else if (addr != NULL && mask != NULL) {
65
switch (family) {
66
case AF_INET:
67
return netlbl_domhsh_remove_af4(domain, addr, mask,
68
audit_info);
69
#if IS_ENABLED(CONFIG_IPV6)
70
case AF_INET6:
71
return netlbl_domhsh_remove_af6(domain, addr, mask,
72
audit_info);
73
#endif /* IPv6 */
74
default:
75
return -EPFNOSUPPORT;
76
}
77
} else
78
return -EINVAL;
79
}
80
81
/**
82
* netlbl_cfg_unlbl_map_add - Add a new unlabeled mapping
83
* @domain: the domain mapping to add
84
* @family: address family
85
* @addr: IP address
86
* @mask: IP address mask
87
* @audit_info: NetLabel audit information
88
*
89
* Description:
90
* Adds a new unlabeled NetLabel/LSM domain mapping. A @domain value of NULL
91
* causes a new default domain mapping to be added. Returns zero on success,
92
* negative values on failure.
93
*
94
*/
95
int netlbl_cfg_unlbl_map_add(const char *domain,
96
u16 family,
97
const void *addr,
98
const void *mask,
99
struct netlbl_audit *audit_info)
100
{
101
int ret_val = -ENOMEM;
102
struct netlbl_dom_map *entry;
103
struct netlbl_domaddr_map *addrmap = NULL;
104
struct netlbl_domaddr4_map *map4 = NULL;
105
struct netlbl_domaddr6_map *map6 = NULL;
106
107
entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
108
if (entry == NULL)
109
return -ENOMEM;
110
if (domain != NULL) {
111
entry->domain = kstrdup(domain, GFP_ATOMIC);
112
if (entry->domain == NULL)
113
goto cfg_unlbl_map_add_failure;
114
}
115
entry->family = family;
116
117
if (addr == NULL && mask == NULL)
118
entry->def.type = NETLBL_NLTYPE_UNLABELED;
119
else if (addr != NULL && mask != NULL) {
120
addrmap = kzalloc(sizeof(*addrmap), GFP_ATOMIC);
121
if (addrmap == NULL)
122
goto cfg_unlbl_map_add_failure;
123
INIT_LIST_HEAD(&addrmap->list4);
124
INIT_LIST_HEAD(&addrmap->list6);
125
126
switch (family) {
127
case AF_INET: {
128
const struct in_addr *addr4 = addr;
129
const struct in_addr *mask4 = mask;
130
map4 = kzalloc(sizeof(*map4), GFP_ATOMIC);
131
if (map4 == NULL)
132
goto cfg_unlbl_map_add_failure;
133
map4->def.type = NETLBL_NLTYPE_UNLABELED;
134
map4->list.addr = addr4->s_addr & mask4->s_addr;
135
map4->list.mask = mask4->s_addr;
136
map4->list.valid = 1;
137
ret_val = netlbl_af4list_add(&map4->list,
138
&addrmap->list4);
139
if (ret_val != 0)
140
goto cfg_unlbl_map_add_failure;
141
break;
142
}
143
#if IS_ENABLED(CONFIG_IPV6)
144
case AF_INET6: {
145
const struct in6_addr *addr6 = addr;
146
const struct in6_addr *mask6 = mask;
147
map6 = kzalloc(sizeof(*map6), GFP_ATOMIC);
148
if (map6 == NULL)
149
goto cfg_unlbl_map_add_failure;
150
map6->def.type = NETLBL_NLTYPE_UNLABELED;
151
map6->list.addr = *addr6;
152
map6->list.addr.s6_addr32[0] &= mask6->s6_addr32[0];
153
map6->list.addr.s6_addr32[1] &= mask6->s6_addr32[1];
154
map6->list.addr.s6_addr32[2] &= mask6->s6_addr32[2];
155
map6->list.addr.s6_addr32[3] &= mask6->s6_addr32[3];
156
map6->list.mask = *mask6;
157
map6->list.valid = 1;
158
ret_val = netlbl_af6list_add(&map6->list,
159
&addrmap->list6);
160
if (ret_val != 0)
161
goto cfg_unlbl_map_add_failure;
162
break;
163
}
164
#endif /* IPv6 */
165
default:
166
goto cfg_unlbl_map_add_failure;
167
}
168
169
entry->def.addrsel = addrmap;
170
entry->def.type = NETLBL_NLTYPE_ADDRSELECT;
171
} else {
172
ret_val = -EINVAL;
173
goto cfg_unlbl_map_add_failure;
174
}
175
176
ret_val = netlbl_domhsh_add(entry, audit_info);
177
if (ret_val != 0)
178
goto cfg_unlbl_map_add_failure;
179
180
return 0;
181
182
cfg_unlbl_map_add_failure:
183
kfree(entry->domain);
184
kfree(entry);
185
kfree(addrmap);
186
kfree(map4);
187
kfree(map6);
188
return ret_val;
189
}
190
191
192
/**
193
* netlbl_cfg_unlbl_static_add - Adds a new static label
194
* @net: network namespace
195
* @dev_name: interface name
196
* @addr: IP address in network byte order (struct in[6]_addr)
197
* @mask: address mask in network byte order (struct in[6]_addr)
198
* @family: address family
199
* @secid: LSM secid value for the entry
200
* @audit_info: NetLabel audit information
201
*
202
* Description:
203
* Adds a new NetLabel static label to be used when protocol provided labels
204
* are not present on incoming traffic. If @dev_name is NULL then the default
205
* interface will be used. Returns zero on success, negative values on failure.
206
*
207
*/
208
int netlbl_cfg_unlbl_static_add(struct net *net,
209
const char *dev_name,
210
const void *addr,
211
const void *mask,
212
u16 family,
213
u32 secid,
214
struct netlbl_audit *audit_info)
215
{
216
u32 addr_len;
217
218
switch (family) {
219
case AF_INET:
220
addr_len = sizeof(struct in_addr);
221
break;
222
#if IS_ENABLED(CONFIG_IPV6)
223
case AF_INET6:
224
addr_len = sizeof(struct in6_addr);
225
break;
226
#endif /* IPv6 */
227
default:
228
return -EPFNOSUPPORT;
229
}
230
231
return netlbl_unlhsh_add(net,
232
dev_name, addr, mask, addr_len,
233
secid, audit_info);
234
}
235
236
/**
237
* netlbl_cfg_unlbl_static_del - Removes an existing static label
238
* @net: network namespace
239
* @dev_name: interface name
240
* @addr: IP address in network byte order (struct in[6]_addr)
241
* @mask: address mask in network byte order (struct in[6]_addr)
242
* @family: address family
243
* @audit_info: NetLabel audit information
244
*
245
* Description:
246
* Removes an existing NetLabel static label used when protocol provided labels
247
* are not present on incoming traffic. If @dev_name is NULL then the default
248
* interface will be used. Returns zero on success, negative values on failure.
249
*
250
*/
251
int netlbl_cfg_unlbl_static_del(struct net *net,
252
const char *dev_name,
253
const void *addr,
254
const void *mask,
255
u16 family,
256
struct netlbl_audit *audit_info)
257
{
258
u32 addr_len;
259
260
switch (family) {
261
case AF_INET:
262
addr_len = sizeof(struct in_addr);
263
break;
264
#if IS_ENABLED(CONFIG_IPV6)
265
case AF_INET6:
266
addr_len = sizeof(struct in6_addr);
267
break;
268
#endif /* IPv6 */
269
default:
270
return -EPFNOSUPPORT;
271
}
272
273
return netlbl_unlhsh_remove(net,
274
dev_name, addr, mask, addr_len,
275
audit_info);
276
}
277
278
/**
279
* netlbl_cfg_cipsov4_add - Add a new CIPSOv4 DOI definition
280
* @doi_def: CIPSO DOI definition
281
* @audit_info: NetLabel audit information
282
*
283
* Description:
284
* Add a new CIPSO DOI definition as defined by @doi_def. Returns zero on
285
* success and negative values on failure.
286
*
287
*/
288
int netlbl_cfg_cipsov4_add(struct cipso_v4_doi *doi_def,
289
struct netlbl_audit *audit_info)
290
{
291
return cipso_v4_doi_add(doi_def, audit_info);
292
}
293
294
/**
295
* netlbl_cfg_cipsov4_del - Remove an existing CIPSOv4 DOI definition
296
* @doi: CIPSO DOI
297
* @audit_info: NetLabel audit information
298
*
299
* Description:
300
* Remove an existing CIPSO DOI definition matching @doi. Returns zero on
301
* success and negative values on failure.
302
*
303
*/
304
void netlbl_cfg_cipsov4_del(u32 doi, struct netlbl_audit *audit_info)
305
{
306
cipso_v4_doi_remove(doi, audit_info);
307
}
308
309
/**
310
* netlbl_cfg_cipsov4_map_add - Add a new CIPSOv4 DOI mapping
311
* @doi: the CIPSO DOI
312
* @domain: the domain mapping to add
313
* @addr: IP address
314
* @mask: IP address mask
315
* @audit_info: NetLabel audit information
316
*
317
* Description:
318
* Add a new NetLabel/LSM domain mapping for the given CIPSO DOI to the NetLabel
319
* subsystem. A @domain value of NULL adds a new default domain mapping.
320
* Returns zero on success, negative values on failure.
321
*
322
*/
323
int netlbl_cfg_cipsov4_map_add(u32 doi,
324
const char *domain,
325
const struct in_addr *addr,
326
const struct in_addr *mask,
327
struct netlbl_audit *audit_info)
328
{
329
int ret_val = -ENOMEM;
330
struct cipso_v4_doi *doi_def;
331
struct netlbl_dom_map *entry;
332
struct netlbl_domaddr_map *addrmap = NULL;
333
struct netlbl_domaddr4_map *addrinfo = NULL;
334
335
doi_def = cipso_v4_doi_getdef(doi);
336
if (doi_def == NULL)
337
return -ENOENT;
338
339
entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
340
if (entry == NULL)
341
goto out_entry;
342
entry->family = AF_INET;
343
if (domain != NULL) {
344
entry->domain = kstrdup(domain, GFP_ATOMIC);
345
if (entry->domain == NULL)
346
goto out_domain;
347
}
348
349
if (addr == NULL && mask == NULL) {
350
entry->def.cipso = doi_def;
351
entry->def.type = NETLBL_NLTYPE_CIPSOV4;
352
} else if (addr != NULL && mask != NULL) {
353
addrmap = kzalloc(sizeof(*addrmap), GFP_ATOMIC);
354
if (addrmap == NULL)
355
goto out_addrmap;
356
INIT_LIST_HEAD(&addrmap->list4);
357
INIT_LIST_HEAD(&addrmap->list6);
358
359
addrinfo = kzalloc(sizeof(*addrinfo), GFP_ATOMIC);
360
if (addrinfo == NULL)
361
goto out_addrinfo;
362
addrinfo->def.cipso = doi_def;
363
addrinfo->def.type = NETLBL_NLTYPE_CIPSOV4;
364
addrinfo->list.addr = addr->s_addr & mask->s_addr;
365
addrinfo->list.mask = mask->s_addr;
366
addrinfo->list.valid = 1;
367
ret_val = netlbl_af4list_add(&addrinfo->list, &addrmap->list4);
368
if (ret_val != 0)
369
goto cfg_cipsov4_map_add_failure;
370
371
entry->def.addrsel = addrmap;
372
entry->def.type = NETLBL_NLTYPE_ADDRSELECT;
373
} else {
374
ret_val = -EINVAL;
375
goto out_addrmap;
376
}
377
378
ret_val = netlbl_domhsh_add(entry, audit_info);
379
if (ret_val != 0)
380
goto cfg_cipsov4_map_add_failure;
381
382
return 0;
383
384
cfg_cipsov4_map_add_failure:
385
kfree(addrinfo);
386
out_addrinfo:
387
kfree(addrmap);
388
out_addrmap:
389
kfree(entry->domain);
390
out_domain:
391
kfree(entry);
392
out_entry:
393
cipso_v4_doi_putdef(doi_def);
394
return ret_val;
395
}
396
397
/**
398
* netlbl_cfg_calipso_add - Add a new CALIPSO DOI definition
399
* @doi_def: CALIPSO DOI definition
400
* @audit_info: NetLabel audit information
401
*
402
* Description:
403
* Add a new CALIPSO DOI definition as defined by @doi_def. Returns zero on
404
* success and negative values on failure.
405
*
406
*/
407
int netlbl_cfg_calipso_add(struct calipso_doi *doi_def,
408
struct netlbl_audit *audit_info)
409
{
410
#if IS_ENABLED(CONFIG_IPV6)
411
return calipso_doi_add(doi_def, audit_info);
412
#else /* IPv6 */
413
return -ENOSYS;
414
#endif /* IPv6 */
415
}
416
417
/**
418
* netlbl_cfg_calipso_del - Remove an existing CALIPSO DOI definition
419
* @doi: CALIPSO DOI
420
* @audit_info: NetLabel audit information
421
*
422
* Description:
423
* Remove an existing CALIPSO DOI definition matching @doi. Returns zero on
424
* success and negative values on failure.
425
*
426
*/
427
void netlbl_cfg_calipso_del(u32 doi, struct netlbl_audit *audit_info)
428
{
429
#if IS_ENABLED(CONFIG_IPV6)
430
calipso_doi_remove(doi, audit_info);
431
#endif /* IPv6 */
432
}
433
434
/**
435
* netlbl_cfg_calipso_map_add - Add a new CALIPSO DOI mapping
436
* @doi: the CALIPSO DOI
437
* @domain: the domain mapping to add
438
* @addr: IP address
439
* @mask: IP address mask
440
* @audit_info: NetLabel audit information
441
*
442
* Description:
443
* Add a new NetLabel/LSM domain mapping for the given CALIPSO DOI to the
444
* NetLabel subsystem. A @domain value of NULL adds a new default domain
445
* mapping. Returns zero on success, negative values on failure.
446
*
447
*/
448
int netlbl_cfg_calipso_map_add(u32 doi,
449
const char *domain,
450
const struct in6_addr *addr,
451
const struct in6_addr *mask,
452
struct netlbl_audit *audit_info)
453
{
454
#if IS_ENABLED(CONFIG_IPV6)
455
int ret_val = -ENOMEM;
456
struct calipso_doi *doi_def;
457
struct netlbl_dom_map *entry;
458
struct netlbl_domaddr_map *addrmap = NULL;
459
struct netlbl_domaddr6_map *addrinfo = NULL;
460
461
doi_def = calipso_doi_getdef(doi);
462
if (doi_def == NULL)
463
return -ENOENT;
464
465
entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
466
if (entry == NULL)
467
goto out_entry;
468
entry->family = AF_INET6;
469
if (domain != NULL) {
470
entry->domain = kstrdup(domain, GFP_ATOMIC);
471
if (entry->domain == NULL)
472
goto out_domain;
473
}
474
475
if (addr == NULL && mask == NULL) {
476
entry->def.calipso = doi_def;
477
entry->def.type = NETLBL_NLTYPE_CALIPSO;
478
} else if (addr != NULL && mask != NULL) {
479
addrmap = kzalloc(sizeof(*addrmap), GFP_ATOMIC);
480
if (addrmap == NULL)
481
goto out_addrmap;
482
INIT_LIST_HEAD(&addrmap->list4);
483
INIT_LIST_HEAD(&addrmap->list6);
484
485
addrinfo = kzalloc(sizeof(*addrinfo), GFP_ATOMIC);
486
if (addrinfo == NULL)
487
goto out_addrinfo;
488
addrinfo->def.calipso = doi_def;
489
addrinfo->def.type = NETLBL_NLTYPE_CALIPSO;
490
addrinfo->list.addr = *addr;
491
addrinfo->list.addr.s6_addr32[0] &= mask->s6_addr32[0];
492
addrinfo->list.addr.s6_addr32[1] &= mask->s6_addr32[1];
493
addrinfo->list.addr.s6_addr32[2] &= mask->s6_addr32[2];
494
addrinfo->list.addr.s6_addr32[3] &= mask->s6_addr32[3];
495
addrinfo->list.mask = *mask;
496
addrinfo->list.valid = 1;
497
ret_val = netlbl_af6list_add(&addrinfo->list, &addrmap->list6);
498
if (ret_val != 0)
499
goto cfg_calipso_map_add_failure;
500
501
entry->def.addrsel = addrmap;
502
entry->def.type = NETLBL_NLTYPE_ADDRSELECT;
503
} else {
504
ret_val = -EINVAL;
505
goto out_addrmap;
506
}
507
508
ret_val = netlbl_domhsh_add(entry, audit_info);
509
if (ret_val != 0)
510
goto cfg_calipso_map_add_failure;
511
512
return 0;
513
514
cfg_calipso_map_add_failure:
515
kfree(addrinfo);
516
out_addrinfo:
517
kfree(addrmap);
518
out_addrmap:
519
kfree(entry->domain);
520
out_domain:
521
kfree(entry);
522
out_entry:
523
calipso_doi_putdef(doi_def);
524
return ret_val;
525
#else /* IPv6 */
526
return -ENOSYS;
527
#endif /* IPv6 */
528
}
529
530
/*
531
* Security Attribute Functions
532
*/
533
534
#define _CM_F_NONE 0x00000000
535
#define _CM_F_ALLOC 0x00000001
536
#define _CM_F_WALK 0x00000002
537
538
/**
539
* _netlbl_catmap_getnode - Get a individual node from a catmap
540
* @catmap: pointer to the category bitmap
541
* @offset: the requested offset
542
* @cm_flags: catmap flags, see _CM_F_*
543
* @gfp_flags: memory allocation flags
544
*
545
* Description:
546
* Iterate through the catmap looking for the node associated with @offset.
547
* If the _CM_F_ALLOC flag is set in @cm_flags and there is no associated node,
548
* one will be created and inserted into the catmap. If the _CM_F_WALK flag is
549
* set in @cm_flags and there is no associated node, the next highest node will
550
* be returned. Returns a pointer to the node on success, NULL on failure.
551
*
552
*/
553
static struct netlbl_lsm_catmap *_netlbl_catmap_getnode(
554
struct netlbl_lsm_catmap **catmap,
555
u32 offset,
556
unsigned int cm_flags,
557
gfp_t gfp_flags)
558
{
559
struct netlbl_lsm_catmap *iter = *catmap;
560
struct netlbl_lsm_catmap *prev = NULL;
561
562
if (iter == NULL)
563
goto catmap_getnode_alloc;
564
if (offset < iter->startbit)
565
goto catmap_getnode_walk;
566
while (iter && offset >= (iter->startbit + NETLBL_CATMAP_SIZE)) {
567
prev = iter;
568
iter = iter->next;
569
}
570
if (iter == NULL || offset < iter->startbit)
571
goto catmap_getnode_walk;
572
573
return iter;
574
575
catmap_getnode_walk:
576
if (cm_flags & _CM_F_WALK)
577
return iter;
578
catmap_getnode_alloc:
579
if (!(cm_flags & _CM_F_ALLOC))
580
return NULL;
581
582
iter = netlbl_catmap_alloc(gfp_flags);
583
if (iter == NULL)
584
return NULL;
585
iter->startbit = offset & ~(NETLBL_CATMAP_SIZE - 1);
586
587
if (prev == NULL) {
588
iter->next = *catmap;
589
*catmap = iter;
590
} else {
591
iter->next = prev->next;
592
prev->next = iter;
593
}
594
595
return iter;
596
}
597
598
/**
599
* netlbl_catmap_walk - Walk a LSM secattr catmap looking for a bit
600
* @catmap: the category bitmap
601
* @offset: the offset to start searching at, in bits
602
*
603
* Description:
604
* This function walks a LSM secattr category bitmap starting at @offset and
605
* returns the spot of the first set bit or -ENOENT if no bits are set.
606
*
607
*/
608
int netlbl_catmap_walk(struct netlbl_lsm_catmap *catmap, u32 offset)
609
{
610
struct netlbl_lsm_catmap *iter;
611
u32 idx;
612
u32 bit;
613
u64 bitmap;
614
615
iter = _netlbl_catmap_getnode(&catmap, offset, _CM_F_WALK, 0);
616
if (iter == NULL)
617
return -ENOENT;
618
if (offset > iter->startbit) {
619
offset -= iter->startbit;
620
idx = offset / NETLBL_CATMAP_MAPSIZE;
621
bit = offset % NETLBL_CATMAP_MAPSIZE;
622
} else {
623
idx = 0;
624
bit = 0;
625
}
626
bitmap = iter->bitmap[idx] >> bit;
627
628
for (;;) {
629
if (bitmap != 0) {
630
while ((bitmap & NETLBL_CATMAP_BIT) == 0) {
631
bitmap >>= 1;
632
bit++;
633
}
634
return iter->startbit +
635
(NETLBL_CATMAP_MAPSIZE * idx) + bit;
636
}
637
if (++idx >= NETLBL_CATMAP_MAPCNT) {
638
if (iter->next != NULL) {
639
iter = iter->next;
640
idx = 0;
641
} else
642
return -ENOENT;
643
}
644
bitmap = iter->bitmap[idx];
645
bit = 0;
646
}
647
648
return -ENOENT;
649
}
650
EXPORT_SYMBOL(netlbl_catmap_walk);
651
652
/**
653
* netlbl_catmap_walkrng - Find the end of a string of set bits
654
* @catmap: the category bitmap
655
* @offset: the offset to start searching at, in bits
656
*
657
* Description:
658
* This function walks a LSM secattr category bitmap starting at @offset and
659
* returns the spot of the first cleared bit or -ENOENT if the offset is past
660
* the end of the bitmap.
661
*
662
*/
663
int netlbl_catmap_walkrng(struct netlbl_lsm_catmap *catmap, u32 offset)
664
{
665
struct netlbl_lsm_catmap *iter;
666
struct netlbl_lsm_catmap *prev = NULL;
667
u32 idx;
668
u32 bit;
669
u64 bitmask;
670
u64 bitmap;
671
672
iter = _netlbl_catmap_getnode(&catmap, offset, _CM_F_WALK, 0);
673
if (iter == NULL)
674
return -ENOENT;
675
if (offset > iter->startbit) {
676
offset -= iter->startbit;
677
idx = offset / NETLBL_CATMAP_MAPSIZE;
678
bit = offset % NETLBL_CATMAP_MAPSIZE;
679
} else {
680
idx = 0;
681
bit = 0;
682
}
683
bitmask = NETLBL_CATMAP_BIT << bit;
684
685
for (;;) {
686
bitmap = iter->bitmap[idx];
687
while (bitmask != 0 && (bitmap & bitmask) != 0) {
688
bitmask <<= 1;
689
bit++;
690
}
691
692
if (prev && idx == 0 && bit == 0)
693
return prev->startbit + NETLBL_CATMAP_SIZE - 1;
694
else if (bitmask != 0)
695
return iter->startbit +
696
(NETLBL_CATMAP_MAPSIZE * idx) + bit - 1;
697
else if (++idx >= NETLBL_CATMAP_MAPCNT) {
698
if (iter->next == NULL)
699
return iter->startbit + NETLBL_CATMAP_SIZE - 1;
700
prev = iter;
701
iter = iter->next;
702
idx = 0;
703
}
704
bitmask = NETLBL_CATMAP_BIT;
705
bit = 0;
706
}
707
708
return -ENOENT;
709
}
710
711
/**
712
* netlbl_catmap_getlong - Export an unsigned long bitmap
713
* @catmap: pointer to the category bitmap
714
* @offset: pointer to the requested offset
715
* @bitmap: the exported bitmap
716
*
717
* Description:
718
* Export a bitmap with an offset greater than or equal to @offset and return
719
* it in @bitmap. The @offset must be aligned to an unsigned long and will be
720
* updated on return if different from what was requested; if the catmap is
721
* empty at the requested offset and beyond, the @offset is set to (u32)-1.
722
* Returns zero on success, negative values on failure.
723
*
724
*/
725
int netlbl_catmap_getlong(struct netlbl_lsm_catmap *catmap,
726
u32 *offset,
727
unsigned long *bitmap)
728
{
729
struct netlbl_lsm_catmap *iter;
730
u32 off = *offset;
731
u32 idx;
732
733
/* only allow aligned offsets */
734
if ((off & (BITS_PER_LONG - 1)) != 0)
735
return -EINVAL;
736
737
/* a null catmap is equivalent to an empty one */
738
if (!catmap) {
739
*offset = (u32)-1;
740
return 0;
741
}
742
743
if (off < catmap->startbit) {
744
off = catmap->startbit;
745
*offset = off;
746
}
747
iter = _netlbl_catmap_getnode(&catmap, off, _CM_F_WALK, 0);
748
if (iter == NULL) {
749
*offset = (u32)-1;
750
return 0;
751
}
752
753
if (off < iter->startbit) {
754
*offset = iter->startbit;
755
off = 0;
756
} else
757
off -= iter->startbit;
758
idx = off / NETLBL_CATMAP_MAPSIZE;
759
*bitmap = iter->bitmap[idx] >> (off % NETLBL_CATMAP_MAPSIZE);
760
761
return 0;
762
}
763
764
/**
765
* netlbl_catmap_setbit - Set a bit in a LSM secattr catmap
766
* @catmap: pointer to the category bitmap
767
* @bit: the bit to set
768
* @flags: memory allocation flags
769
*
770
* Description:
771
* Set the bit specified by @bit in @catmap. Returns zero on success,
772
* negative values on failure.
773
*
774
*/
775
int netlbl_catmap_setbit(struct netlbl_lsm_catmap **catmap,
776
u32 bit,
777
gfp_t flags)
778
{
779
struct netlbl_lsm_catmap *iter;
780
u32 idx;
781
782
iter = _netlbl_catmap_getnode(catmap, bit, _CM_F_ALLOC, flags);
783
if (iter == NULL)
784
return -ENOMEM;
785
786
bit -= iter->startbit;
787
idx = bit / NETLBL_CATMAP_MAPSIZE;
788
iter->bitmap[idx] |= NETLBL_CATMAP_BIT << (bit % NETLBL_CATMAP_MAPSIZE);
789
790
return 0;
791
}
792
EXPORT_SYMBOL(netlbl_catmap_setbit);
793
794
/**
795
* netlbl_catmap_setrng - Set a range of bits in a LSM secattr catmap
796
* @catmap: pointer to the category bitmap
797
* @start: the starting bit
798
* @end: the last bit in the string
799
* @flags: memory allocation flags
800
*
801
* Description:
802
* Set a range of bits, starting at @start and ending with @end. Returns zero
803
* on success, negative values on failure.
804
*
805
*/
806
int netlbl_catmap_setrng(struct netlbl_lsm_catmap **catmap,
807
u32 start,
808
u32 end,
809
gfp_t flags)
810
{
811
int rc = 0;
812
u32 spot = start;
813
814
while (rc == 0 && spot <= end) {
815
if (((spot & (BITS_PER_LONG - 1)) == 0) &&
816
((end - spot) > BITS_PER_LONG)) {
817
rc = netlbl_catmap_setlong(catmap,
818
spot,
819
(unsigned long)-1,
820
flags);
821
spot += BITS_PER_LONG;
822
} else
823
rc = netlbl_catmap_setbit(catmap, spot++, flags);
824
}
825
826
return rc;
827
}
828
829
/**
830
* netlbl_catmap_setlong - Import an unsigned long bitmap
831
* @catmap: pointer to the category bitmap
832
* @offset: offset to the start of the imported bitmap
833
* @bitmap: the bitmap to import
834
* @flags: memory allocation flags
835
*
836
* Description:
837
* Import the bitmap specified in @bitmap into @catmap, using the offset
838
* in @offset. The offset must be aligned to an unsigned long. Returns zero
839
* on success, negative values on failure.
840
*
841
*/
842
int netlbl_catmap_setlong(struct netlbl_lsm_catmap **catmap,
843
u32 offset,
844
unsigned long bitmap,
845
gfp_t flags)
846
{
847
struct netlbl_lsm_catmap *iter;
848
u32 idx;
849
850
/* only allow aligned offsets */
851
if ((offset & (BITS_PER_LONG - 1)) != 0)
852
return -EINVAL;
853
854
iter = _netlbl_catmap_getnode(catmap, offset, _CM_F_ALLOC, flags);
855
if (iter == NULL)
856
return -ENOMEM;
857
858
offset -= iter->startbit;
859
idx = offset / NETLBL_CATMAP_MAPSIZE;
860
iter->bitmap[idx] |= (u64)bitmap
861
<< (offset % NETLBL_CATMAP_MAPSIZE);
862
863
return 0;
864
}
865
866
/* Bitmap functions
867
*/
868
869
/**
870
* netlbl_bitmap_walk - Walk a bitmap looking for a bit
871
* @bitmap: the bitmap
872
* @bitmap_len: length in bits
873
* @offset: starting offset
874
* @state: if non-zero, look for a set (1) bit else look for a cleared (0) bit
875
*
876
* Description:
877
* Starting at @offset, walk the bitmap from left to right until either the
878
* desired bit is found or we reach the end. Return the bit offset, -1 if
879
* not found.
880
*/
881
int netlbl_bitmap_walk(const unsigned char *bitmap, u32 bitmap_len,
882
u32 offset, u8 state)
883
{
884
u32 bit_spot;
885
u32 byte_offset;
886
unsigned char bitmask;
887
unsigned char byte;
888
889
if (offset >= bitmap_len)
890
return -1;
891
byte_offset = offset / 8;
892
byte = bitmap[byte_offset];
893
bit_spot = offset;
894
bitmask = 0x80 >> (offset % 8);
895
896
while (bit_spot < bitmap_len) {
897
if ((state && (byte & bitmask) == bitmask) ||
898
(state == 0 && (byte & bitmask) == 0))
899
return bit_spot;
900
901
if (++bit_spot >= bitmap_len)
902
return -1;
903
bitmask >>= 1;
904
if (bitmask == 0) {
905
byte = bitmap[++byte_offset];
906
bitmask = 0x80;
907
}
908
}
909
910
return -1;
911
}
912
EXPORT_SYMBOL(netlbl_bitmap_walk);
913
914
/**
915
* netlbl_bitmap_setbit - Sets a single bit in a bitmap
916
* @bitmap: the bitmap
917
* @bit: the bit
918
* @state: if non-zero, set the bit (1) else clear the bit (0)
919
*
920
* Description:
921
* Set a single bit in the bitmask. Returns zero on success, negative values
922
* on error.
923
*/
924
void netlbl_bitmap_setbit(unsigned char *bitmap, u32 bit, u8 state)
925
{
926
u32 byte_spot;
927
u8 bitmask;
928
929
/* gcc always rounds to zero when doing integer division */
930
byte_spot = bit / 8;
931
bitmask = 0x80 >> (bit % 8);
932
if (state)
933
bitmap[byte_spot] |= bitmask;
934
else
935
bitmap[byte_spot] &= ~bitmask;
936
}
937
EXPORT_SYMBOL(netlbl_bitmap_setbit);
938
939
/*
940
* LSM Functions
941
*/
942
943
/**
944
* netlbl_enabled - Determine if the NetLabel subsystem is enabled
945
*
946
* Description:
947
* The LSM can use this function to determine if it should use NetLabel
948
* security attributes in it's enforcement mechanism. Currently, NetLabel is
949
* considered to be enabled when it's configuration contains a valid setup for
950
* at least one labeled protocol (i.e. NetLabel can understand incoming
951
* labeled packets of at least one type); otherwise NetLabel is considered to
952
* be disabled.
953
*
954
*/
955
int netlbl_enabled(void)
956
{
957
/* At some point we probably want to expose this mechanism to the user
958
* as well so that admins can toggle NetLabel regardless of the
959
* configuration */
960
return (atomic_read(&netlabel_mgmt_protocount) > 0);
961
}
962
963
/**
964
* netlbl_sock_setattr - Label a socket using the correct protocol
965
* @sk: the socket to label
966
* @family: protocol family
967
* @secattr: the security attributes
968
* @sk_locked: true if caller holds the socket lock
969
*
970
* Description:
971
* Attach the correct label to the given socket using the security attributes
972
* specified in @secattr. This function requires exclusive access to @sk,
973
* which means it either needs to be in the process of being created or locked.
974
* Returns zero on success, -EDESTADDRREQ if the domain is configured to use
975
* network address selectors (can't blindly label the socket), and negative
976
* values on all other failures.
977
*
978
*/
979
int netlbl_sock_setattr(struct sock *sk,
980
u16 family,
981
const struct netlbl_lsm_secattr *secattr,
982
bool sk_locked)
983
{
984
int ret_val;
985
struct netlbl_dom_map *dom_entry;
986
987
rcu_read_lock();
988
dom_entry = netlbl_domhsh_getentry(secattr->domain, family);
989
if (dom_entry == NULL) {
990
ret_val = -ENOENT;
991
goto socket_setattr_return;
992
}
993
switch (family) {
994
case AF_INET:
995
switch (dom_entry->def.type) {
996
case NETLBL_NLTYPE_ADDRSELECT:
997
ret_val = -EDESTADDRREQ;
998
break;
999
case NETLBL_NLTYPE_CIPSOV4:
1000
ret_val = cipso_v4_sock_setattr(sk,
1001
dom_entry->def.cipso,
1002
secattr, sk_locked);
1003
break;
1004
case NETLBL_NLTYPE_UNLABELED:
1005
ret_val = 0;
1006
break;
1007
default:
1008
ret_val = -ENOENT;
1009
}
1010
break;
1011
#if IS_ENABLED(CONFIG_IPV6)
1012
case AF_INET6:
1013
switch (dom_entry->def.type) {
1014
case NETLBL_NLTYPE_ADDRSELECT:
1015
ret_val = -EDESTADDRREQ;
1016
break;
1017
case NETLBL_NLTYPE_CALIPSO:
1018
ret_val = calipso_sock_setattr(sk,
1019
dom_entry->def.calipso,
1020
secattr);
1021
break;
1022
case NETLBL_NLTYPE_UNLABELED:
1023
ret_val = 0;
1024
break;
1025
default:
1026
ret_val = -ENOENT;
1027
}
1028
break;
1029
#endif /* IPv6 */
1030
default:
1031
ret_val = -EPROTONOSUPPORT;
1032
}
1033
1034
socket_setattr_return:
1035
rcu_read_unlock();
1036
return ret_val;
1037
}
1038
1039
/**
1040
* netlbl_sock_delattr - Delete all the NetLabel labels on a socket
1041
* @sk: the socket
1042
*
1043
* Description:
1044
* Remove all the NetLabel labeling from @sk. The caller is responsible for
1045
* ensuring that @sk is locked.
1046
*
1047
*/
1048
void netlbl_sock_delattr(struct sock *sk)
1049
{
1050
switch (sk->sk_family) {
1051
case AF_INET:
1052
cipso_v4_sock_delattr(sk);
1053
break;
1054
#if IS_ENABLED(CONFIG_IPV6)
1055
case AF_INET6:
1056
calipso_sock_delattr(sk);
1057
break;
1058
#endif /* IPv6 */
1059
}
1060
}
1061
1062
/**
1063
* netlbl_sock_getattr - Determine the security attributes of a sock
1064
* @sk: the sock
1065
* @secattr: the security attributes
1066
*
1067
* Description:
1068
* Examines the given sock to see if any NetLabel style labeling has been
1069
* applied to the sock, if so it parses the socket label and returns the
1070
* security attributes in @secattr. Returns zero on success, negative values
1071
* on failure.
1072
*
1073
*/
1074
int netlbl_sock_getattr(struct sock *sk,
1075
struct netlbl_lsm_secattr *secattr)
1076
{
1077
int ret_val;
1078
1079
switch (sk->sk_family) {
1080
case AF_INET:
1081
ret_val = cipso_v4_sock_getattr(sk, secattr);
1082
break;
1083
#if IS_ENABLED(CONFIG_IPV6)
1084
case AF_INET6:
1085
ret_val = calipso_sock_getattr(sk, secattr);
1086
break;
1087
#endif /* IPv6 */
1088
default:
1089
ret_val = -EPROTONOSUPPORT;
1090
}
1091
1092
return ret_val;
1093
}
1094
1095
/**
1096
* netlbl_sk_lock_check - Check if the socket lock has been acquired.
1097
* @sk: the socket to be checked
1098
*
1099
* Return: true if socket @sk is locked or if lock debugging is disabled at
1100
* runtime or compile-time; false otherwise
1101
*
1102
*/
1103
#ifdef CONFIG_LOCKDEP
1104
bool netlbl_sk_lock_check(struct sock *sk)
1105
{
1106
if (debug_locks)
1107
return lockdep_sock_is_held(sk);
1108
return true;
1109
}
1110
#else
1111
bool netlbl_sk_lock_check(struct sock *sk)
1112
{
1113
return true;
1114
}
1115
#endif
1116
1117
/**
1118
* netlbl_conn_setattr - Label a connected socket using the correct protocol
1119
* @sk: the socket to label
1120
* @addr: the destination address
1121
* @secattr: the security attributes
1122
*
1123
* Description:
1124
* Attach the correct label to the given connected socket using the security
1125
* attributes specified in @secattr. The caller is responsible for ensuring
1126
* that @sk is locked. Returns zero on success, negative values on failure.
1127
*
1128
*/
1129
int netlbl_conn_setattr(struct sock *sk,
1130
struct sockaddr *addr,
1131
const struct netlbl_lsm_secattr *secattr)
1132
{
1133
int ret_val;
1134
struct sockaddr_in *addr4;
1135
#if IS_ENABLED(CONFIG_IPV6)
1136
struct sockaddr_in6 *addr6;
1137
#endif
1138
struct netlbl_dommap_def *entry;
1139
1140
rcu_read_lock();
1141
switch (addr->sa_family) {
1142
case AF_INET:
1143
addr4 = (struct sockaddr_in *)addr;
1144
entry = netlbl_domhsh_getentry_af4(secattr->domain,
1145
addr4->sin_addr.s_addr);
1146
if (entry == NULL) {
1147
ret_val = -ENOENT;
1148
goto conn_setattr_return;
1149
}
1150
switch (entry->type) {
1151
case NETLBL_NLTYPE_CIPSOV4:
1152
ret_val = cipso_v4_sock_setattr(sk,
1153
entry->cipso, secattr,
1154
netlbl_sk_lock_check(sk));
1155
break;
1156
case NETLBL_NLTYPE_UNLABELED:
1157
/* just delete the protocols we support for right now
1158
* but we could remove other protocols if needed */
1159
netlbl_sock_delattr(sk);
1160
ret_val = 0;
1161
break;
1162
default:
1163
ret_val = -ENOENT;
1164
}
1165
break;
1166
#if IS_ENABLED(CONFIG_IPV6)
1167
case AF_INET6:
1168
if (sk->sk_family != AF_INET6) {
1169
ret_val = -EAFNOSUPPORT;
1170
goto conn_setattr_return;
1171
}
1172
1173
addr6 = (struct sockaddr_in6 *)addr;
1174
entry = netlbl_domhsh_getentry_af6(secattr->domain,
1175
&addr6->sin6_addr);
1176
if (entry == NULL) {
1177
ret_val = -ENOENT;
1178
goto conn_setattr_return;
1179
}
1180
switch (entry->type) {
1181
case NETLBL_NLTYPE_CALIPSO:
1182
ret_val = calipso_sock_setattr(sk,
1183
entry->calipso, secattr);
1184
break;
1185
case NETLBL_NLTYPE_UNLABELED:
1186
/* just delete the protocols we support for right now
1187
* but we could remove other protocols if needed */
1188
netlbl_sock_delattr(sk);
1189
ret_val = 0;
1190
break;
1191
default:
1192
ret_val = -ENOENT;
1193
}
1194
break;
1195
#endif /* IPv6 */
1196
default:
1197
ret_val = -EPROTONOSUPPORT;
1198
}
1199
1200
conn_setattr_return:
1201
rcu_read_unlock();
1202
return ret_val;
1203
}
1204
1205
/**
1206
* netlbl_req_setattr - Label a request socket using the correct protocol
1207
* @req: the request socket to label
1208
* @secattr: the security attributes
1209
*
1210
* Description:
1211
* Attach the correct label to the given socket using the security attributes
1212
* specified in @secattr. Returns zero on success, negative values on failure.
1213
*
1214
*/
1215
int netlbl_req_setattr(struct request_sock *req,
1216
const struct netlbl_lsm_secattr *secattr)
1217
{
1218
int ret_val;
1219
struct netlbl_dommap_def *entry;
1220
struct inet_request_sock *ireq = inet_rsk(req);
1221
1222
rcu_read_lock();
1223
switch (req->rsk_ops->family) {
1224
case AF_INET:
1225
entry = netlbl_domhsh_getentry_af4(secattr->domain,
1226
ireq->ir_rmt_addr);
1227
if (entry == NULL) {
1228
ret_val = -ENOENT;
1229
goto req_setattr_return;
1230
}
1231
switch (entry->type) {
1232
case NETLBL_NLTYPE_CIPSOV4:
1233
ret_val = cipso_v4_req_setattr(req,
1234
entry->cipso, secattr);
1235
break;
1236
case NETLBL_NLTYPE_UNLABELED:
1237
netlbl_req_delattr(req);
1238
ret_val = 0;
1239
break;
1240
default:
1241
ret_val = -ENOENT;
1242
}
1243
break;
1244
#if IS_ENABLED(CONFIG_IPV6)
1245
case AF_INET6:
1246
entry = netlbl_domhsh_getentry_af6(secattr->domain,
1247
&ireq->ir_v6_rmt_addr);
1248
if (entry == NULL) {
1249
ret_val = -ENOENT;
1250
goto req_setattr_return;
1251
}
1252
switch (entry->type) {
1253
case NETLBL_NLTYPE_CALIPSO:
1254
ret_val = calipso_req_setattr(req,
1255
entry->calipso, secattr);
1256
break;
1257
case NETLBL_NLTYPE_UNLABELED:
1258
netlbl_req_delattr(req);
1259
ret_val = 0;
1260
break;
1261
default:
1262
ret_val = -ENOENT;
1263
}
1264
break;
1265
#endif /* IPv6 */
1266
default:
1267
ret_val = -EPROTONOSUPPORT;
1268
}
1269
1270
req_setattr_return:
1271
rcu_read_unlock();
1272
return ret_val;
1273
}
1274
1275
/**
1276
* netlbl_req_delattr - Delete all the NetLabel labels on a socket
1277
* @req: the socket
1278
*
1279
* Description:
1280
* Remove all the NetLabel labeling from @req.
1281
*
1282
*/
1283
void netlbl_req_delattr(struct request_sock *req)
1284
{
1285
switch (req->rsk_ops->family) {
1286
case AF_INET:
1287
cipso_v4_req_delattr(req);
1288
break;
1289
#if IS_ENABLED(CONFIG_IPV6)
1290
case AF_INET6:
1291
calipso_req_delattr(req);
1292
break;
1293
#endif /* IPv6 */
1294
}
1295
}
1296
1297
/**
1298
* netlbl_skbuff_setattr - Label a packet using the correct protocol
1299
* @skb: the packet
1300
* @family: protocol family
1301
* @secattr: the security attributes
1302
*
1303
* Description:
1304
* Attach the correct label to the given packet using the security attributes
1305
* specified in @secattr. Returns zero on success, negative values on failure.
1306
*
1307
*/
1308
int netlbl_skbuff_setattr(struct sk_buff *skb,
1309
u16 family,
1310
const struct netlbl_lsm_secattr *secattr)
1311
{
1312
int ret_val;
1313
struct iphdr *hdr4;
1314
#if IS_ENABLED(CONFIG_IPV6)
1315
struct ipv6hdr *hdr6;
1316
#endif
1317
struct netlbl_dommap_def *entry;
1318
1319
rcu_read_lock();
1320
switch (family) {
1321
case AF_INET:
1322
hdr4 = ip_hdr(skb);
1323
entry = netlbl_domhsh_getentry_af4(secattr->domain,
1324
hdr4->daddr);
1325
if (entry == NULL) {
1326
ret_val = -ENOENT;
1327
goto skbuff_setattr_return;
1328
}
1329
switch (entry->type) {
1330
case NETLBL_NLTYPE_CIPSOV4:
1331
ret_val = cipso_v4_skbuff_setattr(skb, entry->cipso,
1332
secattr);
1333
break;
1334
case NETLBL_NLTYPE_UNLABELED:
1335
/* just delete the protocols we support for right now
1336
* but we could remove other protocols if needed */
1337
ret_val = cipso_v4_skbuff_delattr(skb);
1338
break;
1339
default:
1340
ret_val = -ENOENT;
1341
}
1342
break;
1343
#if IS_ENABLED(CONFIG_IPV6)
1344
case AF_INET6:
1345
hdr6 = ipv6_hdr(skb);
1346
entry = netlbl_domhsh_getentry_af6(secattr->domain,
1347
&hdr6->daddr);
1348
if (entry == NULL) {
1349
ret_val = -ENOENT;
1350
goto skbuff_setattr_return;
1351
}
1352
switch (entry->type) {
1353
case NETLBL_NLTYPE_CALIPSO:
1354
ret_val = calipso_skbuff_setattr(skb, entry->calipso,
1355
secattr);
1356
break;
1357
case NETLBL_NLTYPE_UNLABELED:
1358
/* just delete the protocols we support for right now
1359
* but we could remove other protocols if needed */
1360
ret_val = calipso_skbuff_delattr(skb);
1361
break;
1362
default:
1363
ret_val = -ENOENT;
1364
}
1365
break;
1366
#endif /* IPv6 */
1367
default:
1368
ret_val = -EPROTONOSUPPORT;
1369
}
1370
1371
skbuff_setattr_return:
1372
rcu_read_unlock();
1373
return ret_val;
1374
}
1375
1376
/**
1377
* netlbl_skbuff_getattr - Determine the security attributes of a packet
1378
* @skb: the packet
1379
* @family: protocol family
1380
* @secattr: the security attributes
1381
*
1382
* Description:
1383
* Examines the given packet to see if a recognized form of packet labeling
1384
* is present, if so it parses the packet label and returns the security
1385
* attributes in @secattr. Returns zero on success, negative values on
1386
* failure.
1387
*
1388
*/
1389
int netlbl_skbuff_getattr(const struct sk_buff *skb,
1390
u16 family,
1391
struct netlbl_lsm_secattr *secattr)
1392
{
1393
unsigned char *ptr;
1394
1395
switch (family) {
1396
case AF_INET:
1397
ptr = cipso_v4_optptr(skb);
1398
if (ptr && cipso_v4_getattr(ptr, secattr) == 0)
1399
return 0;
1400
break;
1401
#if IS_ENABLED(CONFIG_IPV6)
1402
case AF_INET6:
1403
ptr = calipso_optptr(skb);
1404
if (ptr && calipso_getattr(ptr, secattr) == 0)
1405
return 0;
1406
break;
1407
#endif /* IPv6 */
1408
}
1409
1410
return netlbl_unlabel_getattr(skb, family, secattr);
1411
}
1412
1413
/**
1414
* netlbl_skbuff_err - Handle a LSM error on a sk_buff
1415
* @skb: the packet
1416
* @family: the family
1417
* @error: the error code
1418
* @gateway: true if host is acting as a gateway, false otherwise
1419
*
1420
* Description:
1421
* Deal with a LSM problem when handling the packet in @skb, typically this is
1422
* a permission denied problem (-EACCES). The correct action is determined
1423
* according to the packet's labeling protocol.
1424
*
1425
*/
1426
void netlbl_skbuff_err(struct sk_buff *skb, u16 family, int error, int gateway)
1427
{
1428
switch (family) {
1429
case AF_INET:
1430
if (cipso_v4_optptr(skb))
1431
cipso_v4_error(skb, error, gateway);
1432
break;
1433
}
1434
}
1435
1436
/**
1437
* netlbl_cache_invalidate - Invalidate all of the NetLabel protocol caches
1438
*
1439
* Description:
1440
* For all of the NetLabel protocols that support some form of label mapping
1441
* cache, invalidate the cache. Returns zero on success, negative values on
1442
* error.
1443
*
1444
*/
1445
void netlbl_cache_invalidate(void)
1446
{
1447
cipso_v4_cache_invalidate();
1448
#if IS_ENABLED(CONFIG_IPV6)
1449
calipso_cache_invalidate();
1450
#endif /* IPv6 */
1451
}
1452
1453
/**
1454
* netlbl_cache_add - Add an entry to a NetLabel protocol cache
1455
* @skb: the packet
1456
* @family: the family
1457
* @secattr: the packet's security attributes
1458
*
1459
* Description:
1460
* Add the LSM security attributes for the given packet to the underlying
1461
* NetLabel protocol's label mapping cache. Returns zero on success, negative
1462
* values on error.
1463
*
1464
*/
1465
int netlbl_cache_add(const struct sk_buff *skb, u16 family,
1466
const struct netlbl_lsm_secattr *secattr)
1467
{
1468
unsigned char *ptr;
1469
1470
if ((secattr->flags & NETLBL_SECATTR_CACHE) == 0)
1471
return -ENOMSG;
1472
1473
switch (family) {
1474
case AF_INET:
1475
ptr = cipso_v4_optptr(skb);
1476
if (ptr)
1477
return cipso_v4_cache_add(ptr, secattr);
1478
break;
1479
#if IS_ENABLED(CONFIG_IPV6)
1480
case AF_INET6:
1481
ptr = calipso_optptr(skb);
1482
if (ptr)
1483
return calipso_cache_add(ptr, secattr);
1484
break;
1485
#endif /* IPv6 */
1486
}
1487
return -ENOMSG;
1488
}
1489
1490
/*
1491
* Protocol Engine Functions
1492
*/
1493
1494
/**
1495
* netlbl_audit_start - Start an audit message
1496
* @type: audit message type
1497
* @audit_info: NetLabel audit information
1498
*
1499
* Description:
1500
* Start an audit message using the type specified in @type and fill the audit
1501
* message with some fields common to all NetLabel audit messages. This
1502
* function should only be used by protocol engines, not LSMs. Returns a
1503
* pointer to the audit buffer on success, NULL on failure.
1504
*
1505
*/
1506
struct audit_buffer *netlbl_audit_start(int type,
1507
struct netlbl_audit *audit_info)
1508
{
1509
return netlbl_audit_start_common(type, audit_info);
1510
}
1511
EXPORT_SYMBOL(netlbl_audit_start);
1512
1513
/*
1514
* Setup Functions
1515
*/
1516
1517
/**
1518
* netlbl_init - Initialize NetLabel
1519
*
1520
* Description:
1521
* Perform the required NetLabel initialization before first use.
1522
*
1523
*/
1524
static int __init netlbl_init(void)
1525
{
1526
int ret_val;
1527
1528
printk(KERN_INFO "NetLabel: Initializing\n");
1529
printk(KERN_INFO "NetLabel: domain hash size = %u\n",
1530
(1 << NETLBL_DOMHSH_BITSIZE));
1531
printk(KERN_INFO "NetLabel: protocols = UNLABELED CIPSOv4 CALIPSO\n");
1532
1533
ret_val = netlbl_domhsh_init(NETLBL_DOMHSH_BITSIZE);
1534
if (ret_val != 0)
1535
goto init_failure;
1536
1537
ret_val = netlbl_unlabel_init(NETLBL_UNLHSH_BITSIZE);
1538
if (ret_val != 0)
1539
goto init_failure;
1540
1541
ret_val = netlbl_netlink_init();
1542
if (ret_val != 0)
1543
goto init_failure;
1544
1545
ret_val = netlbl_unlabel_defconf();
1546
if (ret_val != 0)
1547
goto init_failure;
1548
printk(KERN_INFO "NetLabel: unlabeled traffic allowed by default\n");
1549
1550
return 0;
1551
1552
init_failure:
1553
panic("NetLabel: failed to initialize properly (%d)\n", ret_val);
1554
}
1555
1556
subsys_initcall(netlbl_init);
1557
1558