Blame view

net/netlabel/netlabel_kapi.c 28.1 KB
d15c345fe   Paul Moore   [NetLabel]: core ...
1
2
3
4
5
6
7
  /*
   * NetLabel Kernel API
   *
   * This file defines the kernel API for the NetLabel system.  The NetLabel
   * system manages static and dynamic label mappings for network protocols such
   * as CIPSO and RIPSO.
   *
82c21bfab   Paul Moore   doc: Update the e...
8
   * Author: Paul Moore <paul@paul-moore.com>
d15c345fe   Paul Moore   [NetLabel]: core ...
9
10
11
12
   *
   */
  
  /*
014ab19a6   Paul Moore   selinux: Set sock...
13
   * (c) Copyright Hewlett-Packard Development Company, L.P., 2006, 2008
d15c345fe   Paul Moore   [NetLabel]: core ...
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
   *
   * 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/init.h>
  #include <linux/types.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
33
  #include <linux/slab.h>
eda61d32e   Paul Moore   NetLabel: introdu...
34
  #include <linux/audit.h>
6c2e8ac09   Paul Moore   netlabel: Update ...
35
36
  #include <linux/in.h>
  #include <linux/in6.h>
d15c345fe   Paul Moore   [NetLabel]: core ...
37
  #include <net/ip.h>
6c2e8ac09   Paul Moore   netlabel: Update ...
38
  #include <net/ipv6.h>
d15c345fe   Paul Moore   [NetLabel]: core ...
39
40
41
  #include <net/netlabel.h>
  #include <net/cipso_ipv4.h>
  #include <asm/bug.h>
60063497a   Arun Sharma   atomic: use <linu...
42
  #include <linux/atomic.h>
d15c345fe   Paul Moore   [NetLabel]: core ...
43
44
45
  
  #include "netlabel_domainhash.h"
  #include "netlabel_unlabeled.h"
eda61d32e   Paul Moore   NetLabel: introdu...
46
  #include "netlabel_cipso_v4.h"
d15c345fe   Paul Moore   [NetLabel]: core ...
47
  #include "netlabel_user.h"
23bcdc1ad   Paul Moore   SELinux: enable d...
48
  #include "netlabel_mgmt.h"
6c2e8ac09   Paul Moore   netlabel: Update ...
49
  #include "netlabel_addrlist.h"
d15c345fe   Paul Moore   [NetLabel]: core ...
50
51
  
  /*
eda61d32e   Paul Moore   NetLabel: introdu...
52
53
54
55
56
57
   * Configuration Functions
   */
  
  /**
   * netlbl_cfg_map_del - Remove a NetLabel/LSM domain mapping
   * @domain: the domain mapping to remove
6c2e8ac09   Paul Moore   netlabel: Update ...
58
59
60
   * @family: address family
   * @addr: IP address
   * @mask: IP address mask
eda61d32e   Paul Moore   NetLabel: introdu...
61
62
63
64
65
66
67
68
   * @audit_info: NetLabel audit information
   *
   * Description:
   * Removes a NetLabel/LSM domain mapping.  A @domain value of NULL causes the
   * default domain mapping to be removed.  Returns zero on success, negative
   * values on failure.
   *
   */
6c2e8ac09   Paul Moore   netlabel: Update ...
69
70
71
72
73
  int netlbl_cfg_map_del(const char *domain,
  		       u16 family,
  		       const void *addr,
  		       const void *mask,
  		       struct netlbl_audit *audit_info)
eda61d32e   Paul Moore   NetLabel: introdu...
74
  {
6c2e8ac09   Paul Moore   netlabel: Update ...
75
76
77
78
79
80
81
82
83
84
85
86
  	if (addr == NULL && mask == NULL) {
  		return netlbl_domhsh_remove(domain, audit_info);
  	} else if (addr != NULL && mask != NULL) {
  		switch (family) {
  		case AF_INET:
  			return netlbl_domhsh_remove_af4(domain, addr, mask,
  							audit_info);
  		default:
  			return -EPFNOSUPPORT;
  		}
  	} else
  		return -EINVAL;
eda61d32e   Paul Moore   NetLabel: introdu...
87
88
89
  }
  
  /**
6c2e8ac09   Paul Moore   netlabel: Update ...
90
   * netlbl_cfg_unlbl_map_add - Add a new unlabeled mapping
eda61d32e   Paul Moore   NetLabel: introdu...
91
   * @domain: the domain mapping to add
6c2e8ac09   Paul Moore   netlabel: Update ...
92
93
94
   * @family: address family
   * @addr: IP address
   * @mask: IP address mask
eda61d32e   Paul Moore   NetLabel: introdu...
95
96
97
98
99
100
101
102
   * @audit_info: NetLabel audit information
   *
   * Description:
   * Adds a new unlabeled NetLabel/LSM domain mapping.  A @domain value of NULL
   * causes a new default domain mapping to be added.  Returns zero on success,
   * negative values on failure.
   *
   */
6c2e8ac09   Paul Moore   netlabel: Update ...
103
104
105
106
  int netlbl_cfg_unlbl_map_add(const char *domain,
  			     u16 family,
  			     const void *addr,
  			     const void *mask,
eda61d32e   Paul Moore   NetLabel: introdu...
107
108
109
110
  			     struct netlbl_audit *audit_info)
  {
  	int ret_val = -ENOMEM;
  	struct netlbl_dom_map *entry;
6c2e8ac09   Paul Moore   netlabel: Update ...
111
112
113
  	struct netlbl_domaddr_map *addrmap = NULL;
  	struct netlbl_domaddr4_map *map4 = NULL;
  	struct netlbl_domaddr6_map *map6 = NULL;
eda61d32e   Paul Moore   NetLabel: introdu...
114
115
116
  
  	entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
  	if (entry == NULL)
948a72438   Paul Moore   netlabel: Remove ...
117
  		return -ENOMEM;
eda61d32e   Paul Moore   NetLabel: introdu...
118
119
120
  	if (domain != NULL) {
  		entry->domain = kstrdup(domain, GFP_ATOMIC);
  		if (entry->domain == NULL)
6c2e8ac09   Paul Moore   netlabel: Update ...
121
122
123
124
125
126
127
128
129
130
131
132
133
  			goto cfg_unlbl_map_add_failure;
  	}
  
  	if (addr == NULL && mask == NULL)
  		entry->type = NETLBL_NLTYPE_UNLABELED;
  	else if (addr != NULL && mask != NULL) {
  		addrmap = kzalloc(sizeof(*addrmap), GFP_ATOMIC);
  		if (addrmap == NULL)
  			goto cfg_unlbl_map_add_failure;
  		INIT_LIST_HEAD(&addrmap->list4);
  		INIT_LIST_HEAD(&addrmap->list6);
  
  		switch (family) {
1281bc256   Paul Moore   netlabel: Fix bui...
134
135
136
  		case AF_INET: {
  			const struct in_addr *addr4 = addr;
  			const struct in_addr *mask4 = mask;
6c2e8ac09   Paul Moore   netlabel: Update ...
137
138
139
140
141
142
143
144
145
146
147
148
  			map4 = kzalloc(sizeof(*map4), GFP_ATOMIC);
  			if (map4 == NULL)
  				goto cfg_unlbl_map_add_failure;
  			map4->type = NETLBL_NLTYPE_UNLABELED;
  			map4->list.addr = addr4->s_addr & mask4->s_addr;
  			map4->list.mask = mask4->s_addr;
  			map4->list.valid = 1;
  			ret_val = netlbl_af4list_add(&map4->list,
  						     &addrmap->list4);
  			if (ret_val != 0)
  				goto cfg_unlbl_map_add_failure;
  			break;
1281bc256   Paul Moore   netlabel: Fix bui...
149
  			}
dfd56b8b3   Eric Dumazet   net: use IS_ENABL...
150
  #if IS_ENABLED(CONFIG_IPV6)
1281bc256   Paul Moore   netlabel: Fix bui...
151
152
153
  		case AF_INET6: {
  			const struct in6_addr *addr6 = addr;
  			const struct in6_addr *mask6 = mask;
6c2e8ac09   Paul Moore   netlabel: Update ...
154
  			map6 = kzalloc(sizeof(*map6), GFP_ATOMIC);
ca7daea61   Julia Lawall   net/netlabel: Add...
155
  			if (map6 == NULL)
6c2e8ac09   Paul Moore   netlabel: Update ...
156
157
  				goto cfg_unlbl_map_add_failure;
  			map6->type = NETLBL_NLTYPE_UNLABELED;
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
158
  			map6->list.addr = *addr6;
6c2e8ac09   Paul Moore   netlabel: Update ...
159
160
161
162
  			map6->list.addr.s6_addr32[0] &= mask6->s6_addr32[0];
  			map6->list.addr.s6_addr32[1] &= mask6->s6_addr32[1];
  			map6->list.addr.s6_addr32[2] &= mask6->s6_addr32[2];
  			map6->list.addr.s6_addr32[3] &= mask6->s6_addr32[3];
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
163
  			map6->list.mask = *mask6;
6c2e8ac09   Paul Moore   netlabel: Update ...
164
  			map6->list.valid = 1;
42ca0203f   Dan Carpenter   net/netlabel: cop...
165
166
  			ret_val = netlbl_af6list_add(&map6->list,
  						     &addrmap->list6);
6c2e8ac09   Paul Moore   netlabel: Update ...
167
168
169
  			if (ret_val != 0)
  				goto cfg_unlbl_map_add_failure;
  			break;
1281bc256   Paul Moore   netlabel: Fix bui...
170
171
  			}
  #endif /* IPv6 */
6c2e8ac09   Paul Moore   netlabel: Update ...
172
173
174
175
176
177
178
179
180
181
  		default:
  			goto cfg_unlbl_map_add_failure;
  			break;
  		}
  
  		entry->type_def.addrsel = addrmap;
  		entry->type = NETLBL_NLTYPE_ADDRSELECT;
  	} else {
  		ret_val = -EINVAL;
  		goto cfg_unlbl_map_add_failure;
eda61d32e   Paul Moore   NetLabel: introdu...
182
  	}
eda61d32e   Paul Moore   NetLabel: introdu...
183
184
185
  
  	ret_val = netlbl_domhsh_add(entry, audit_info);
  	if (ret_val != 0)
6c2e8ac09   Paul Moore   netlabel: Update ...
186
  		goto cfg_unlbl_map_add_failure;
eda61d32e   Paul Moore   NetLabel: introdu...
187
188
  
  	return 0;
6c2e8ac09   Paul Moore   netlabel: Update ...
189
  cfg_unlbl_map_add_failure:
479432344   Julia Lawall   net/netlabel: Cor...
190
  	kfree(entry->domain);
eda61d32e   Paul Moore   NetLabel: introdu...
191
  	kfree(entry);
6c2e8ac09   Paul Moore   netlabel: Update ...
192
193
194
  	kfree(addrmap);
  	kfree(map4);
  	kfree(map6);
eda61d32e   Paul Moore   NetLabel: introdu...
195
196
  	return ret_val;
  }
6c2e8ac09   Paul Moore   netlabel: Update ...
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
  
  /**
   * netlbl_cfg_unlbl_static_add - Adds a new static label
   * @net: network namespace
   * @dev_name: interface name
   * @addr: IP address in network byte order (struct in[6]_addr)
   * @mask: address mask in network byte order (struct in[6]_addr)
   * @family: address family
   * @secid: LSM secid value for the entry
   * @audit_info: NetLabel audit information
   *
   * Description:
   * Adds a new NetLabel static label to be used when protocol provided labels
   * are not present on incoming traffic.  If @dev_name is NULL then the default
   * interface will be used.  Returns zero on success, negative values on failure.
   *
   */
  int netlbl_cfg_unlbl_static_add(struct net *net,
  				const char *dev_name,
  				const void *addr,
  				const void *mask,
  				u16 family,
  				u32 secid,
  				struct netlbl_audit *audit_info)
  {
  	u32 addr_len;
  
  	switch (family) {
  	case AF_INET:
  		addr_len = sizeof(struct in_addr);
  		break;
dfd56b8b3   Eric Dumazet   net: use IS_ENABL...
228
  #if IS_ENABLED(CONFIG_IPV6)
6c2e8ac09   Paul Moore   netlabel: Update ...
229
230
231
  	case AF_INET6:
  		addr_len = sizeof(struct in6_addr);
  		break;
1281bc256   Paul Moore   netlabel: Fix bui...
232
  #endif /* IPv6 */
6c2e8ac09   Paul Moore   netlabel: Update ...
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
  	default:
  		return -EPFNOSUPPORT;
  	}
  
  	return netlbl_unlhsh_add(net,
  				 dev_name, addr, mask, addr_len,
  				 secid, audit_info);
  }
  
  /**
   * netlbl_cfg_unlbl_static_del - Removes an existing static label
   * @net: network namespace
   * @dev_name: interface name
   * @addr: IP address in network byte order (struct in[6]_addr)
   * @mask: address mask in network byte order (struct in[6]_addr)
   * @family: address family
   * @secid: LSM secid value for the entry
   * @audit_info: NetLabel audit information
   *
   * Description:
   * Removes an existing NetLabel static label used when protocol provided labels
   * are not present on incoming traffic.  If @dev_name is NULL then the default
   * interface will be used.  Returns zero on success, negative values on failure.
   *
   */
  int netlbl_cfg_unlbl_static_del(struct net *net,
  				const char *dev_name,
  				const void *addr,
  				const void *mask,
  				u16 family,
  				struct netlbl_audit *audit_info)
  {
  	u32 addr_len;
  
  	switch (family) {
  	case AF_INET:
  		addr_len = sizeof(struct in_addr);
  		break;
dfd56b8b3   Eric Dumazet   net: use IS_ENABL...
271
  #if IS_ENABLED(CONFIG_IPV6)
6c2e8ac09   Paul Moore   netlabel: Update ...
272
273
274
  	case AF_INET6:
  		addr_len = sizeof(struct in6_addr);
  		break;
1281bc256   Paul Moore   netlabel: Fix bui...
275
  #endif /* IPv6 */
6c2e8ac09   Paul Moore   netlabel: Update ...
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
  	default:
  		return -EPFNOSUPPORT;
  	}
  
  	return netlbl_unlhsh_remove(net,
  				    dev_name, addr, mask, addr_len,
  				    audit_info);
  }
  
  /**
   * netlbl_cfg_cipsov4_add - Add a new CIPSOv4 DOI definition
   * @doi_def: CIPSO DOI definition
   * @audit_info: NetLabel audit information
   *
   * Description:
   * Add a new CIPSO DOI definition as defined by @doi_def.  Returns zero on
   * success and negative values on failure.
   *
   */
  int netlbl_cfg_cipsov4_add(struct cipso_v4_doi *doi_def,
  			   struct netlbl_audit *audit_info)
  {
  	return cipso_v4_doi_add(doi_def, audit_info);
  }
  
  /**
   * netlbl_cfg_cipsov4_del - Remove an existing CIPSOv4 DOI definition
   * @doi: CIPSO DOI
   * @audit_info: NetLabel audit information
   *
   * Description:
   * Remove an existing CIPSO DOI definition matching @doi.  Returns zero on
   * success and negative values on failure.
   *
   */
  void netlbl_cfg_cipsov4_del(u32 doi, struct netlbl_audit *audit_info)
  {
  	cipso_v4_doi_remove(doi, audit_info);
  }
eda61d32e   Paul Moore   NetLabel: introdu...
315
  /**
6c2e8ac09   Paul Moore   netlabel: Update ...
316
317
   * netlbl_cfg_cipsov4_map_add - Add a new CIPSOv4 DOI mapping
   * @doi: the CIPSO DOI
eda61d32e   Paul Moore   NetLabel: introdu...
318
   * @domain: the domain mapping to add
6c2e8ac09   Paul Moore   netlabel: Update ...
319
320
   * @addr: IP address
   * @mask: IP address mask
eda61d32e   Paul Moore   NetLabel: introdu...
321
322
323
   * @audit_info: NetLabel audit information
   *
   * Description:
6c2e8ac09   Paul Moore   netlabel: Update ...
324
325
326
   * Add a new NetLabel/LSM domain mapping for the given CIPSO DOI to the NetLabel
   * subsystem.  A @domain value of NULL adds a new default domain mapping.
   * Returns zero on success, negative values on failure.
eda61d32e   Paul Moore   NetLabel: introdu...
327
328
   *
   */
6c2e8ac09   Paul Moore   netlabel: Update ...
329
  int netlbl_cfg_cipsov4_map_add(u32 doi,
eda61d32e   Paul Moore   NetLabel: introdu...
330
  			       const char *domain,
6c2e8ac09   Paul Moore   netlabel: Update ...
331
332
  			       const struct in_addr *addr,
  			       const struct in_addr *mask,
eda61d32e   Paul Moore   NetLabel: introdu...
333
334
335
  			       struct netlbl_audit *audit_info)
  {
  	int ret_val = -ENOMEM;
6c2e8ac09   Paul Moore   netlabel: Update ...
336
  	struct cipso_v4_doi *doi_def;
eda61d32e   Paul Moore   NetLabel: introdu...
337
  	struct netlbl_dom_map *entry;
6c2e8ac09   Paul Moore   netlabel: Update ...
338
339
  	struct netlbl_domaddr_map *addrmap = NULL;
  	struct netlbl_domaddr4_map *addrinfo = NULL;
eda61d32e   Paul Moore   NetLabel: introdu...
340

6c2e8ac09   Paul Moore   netlabel: Update ...
341
342
343
  	doi_def = cipso_v4_doi_getdef(doi);
  	if (doi_def == NULL)
  		return -ENOENT;
b1edeb102   Paul Moore   netlabel: Replace...
344

eda61d32e   Paul Moore   NetLabel: introdu...
345
346
  	entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
  	if (entry == NULL)
94a80d63b   Julia Lawall   net/netlabel/netl...
347
  		goto out_entry;
eda61d32e   Paul Moore   NetLabel: introdu...
348
349
350
  	if (domain != NULL) {
  		entry->domain = kstrdup(domain, GFP_ATOMIC);
  		if (entry->domain == NULL)
94a80d63b   Julia Lawall   net/netlabel/netl...
351
  			goto out_domain;
eda61d32e   Paul Moore   NetLabel: introdu...
352
  	}
eda61d32e   Paul Moore   NetLabel: introdu...
353

6c2e8ac09   Paul Moore   netlabel: Update ...
354
355
356
357
358
359
  	if (addr == NULL && mask == NULL) {
  		entry->type_def.cipsov4 = doi_def;
  		entry->type = NETLBL_NLTYPE_CIPSOV4;
  	} else if (addr != NULL && mask != NULL) {
  		addrmap = kzalloc(sizeof(*addrmap), GFP_ATOMIC);
  		if (addrmap == NULL)
94a80d63b   Julia Lawall   net/netlabel/netl...
360
  			goto out_addrmap;
6c2e8ac09   Paul Moore   netlabel: Update ...
361
362
363
364
365
  		INIT_LIST_HEAD(&addrmap->list4);
  		INIT_LIST_HEAD(&addrmap->list6);
  
  		addrinfo = kzalloc(sizeof(*addrinfo), GFP_ATOMIC);
  		if (addrinfo == NULL)
94a80d63b   Julia Lawall   net/netlabel/netl...
366
  			goto out_addrinfo;
6c2e8ac09   Paul Moore   netlabel: Update ...
367
368
369
370
371
372
373
374
375
376
377
378
379
  		addrinfo->type_def.cipsov4 = doi_def;
  		addrinfo->type = NETLBL_NLTYPE_CIPSOV4;
  		addrinfo->list.addr = addr->s_addr & mask->s_addr;
  		addrinfo->list.mask = mask->s_addr;
  		addrinfo->list.valid = 1;
  		ret_val = netlbl_af4list_add(&addrinfo->list, &addrmap->list4);
  		if (ret_val != 0)
  			goto cfg_cipsov4_map_add_failure;
  
  		entry->type_def.addrsel = addrmap;
  		entry->type = NETLBL_NLTYPE_ADDRSELECT;
  	} else {
  		ret_val = -EINVAL;
94a80d63b   Julia Lawall   net/netlabel/netl...
380
  		goto out_addrmap;
b1edeb102   Paul Moore   netlabel: Replace...
381
  	}
6c2e8ac09   Paul Moore   netlabel: Update ...
382

eda61d32e   Paul Moore   NetLabel: introdu...
383
384
  	ret_val = netlbl_domhsh_add(entry, audit_info);
  	if (ret_val != 0)
6c2e8ac09   Paul Moore   netlabel: Update ...
385
  		goto cfg_cipsov4_map_add_failure;
b1edeb102   Paul Moore   netlabel: Replace...
386

6c2e8ac09   Paul Moore   netlabel: Update ...
387
  	return 0;
b1edeb102   Paul Moore   netlabel: Replace...
388

6c2e8ac09   Paul Moore   netlabel: Update ...
389
  cfg_cipsov4_map_add_failure:
94a80d63b   Julia Lawall   net/netlabel/netl...
390
391
392
393
  	kfree(addrinfo);
  out_addrinfo:
  	kfree(addrmap);
  out_addrmap:
479432344   Julia Lawall   net/netlabel: Cor...
394
  	kfree(entry->domain);
94a80d63b   Julia Lawall   net/netlabel/netl...
395
  out_domain:
eda61d32e   Paul Moore   NetLabel: introdu...
396
  	kfree(entry);
94a80d63b   Julia Lawall   net/netlabel/netl...
397
398
  out_entry:
  	cipso_v4_doi_putdef(doi_def);
6c2e8ac09   Paul Moore   netlabel: Update ...
399
  	return ret_val;
eda61d32e   Paul Moore   NetLabel: introdu...
400
  }
eda61d32e   Paul Moore   NetLabel: introdu...
401
  /*
027527603   Paul Moore   NetLabel: convert...
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
   * Security Attribute Functions
   */
  
  /**
   * netlbl_secattr_catmap_walk - Walk a LSM secattr catmap looking for a bit
   * @catmap: the category bitmap
   * @offset: the offset to start searching at, in bits
   *
   * Description:
   * This function walks a LSM secattr category bitmap starting at @offset and
   * returns the spot of the first set bit or -ENOENT if no bits are set.
   *
   */
  int netlbl_secattr_catmap_walk(struct netlbl_lsm_secattr_catmap *catmap,
  			       u32 offset)
  {
  	struct netlbl_lsm_secattr_catmap *iter = catmap;
  	u32 node_idx;
  	u32 node_bit;
  	NETLBL_CATMAP_MAPTYPE bitmap;
  
  	if (offset > iter->startbit) {
  		while (offset >= (iter->startbit + NETLBL_CATMAP_SIZE)) {
  			iter = iter->next;
  			if (iter == NULL)
  				return -ENOENT;
  		}
  		node_idx = (offset - iter->startbit) / NETLBL_CATMAP_MAPSIZE;
  		node_bit = offset - iter->startbit -
  			   (NETLBL_CATMAP_MAPSIZE * node_idx);
  	} else {
  		node_idx = 0;
  		node_bit = 0;
  	}
  	bitmap = iter->bitmap[node_idx] >> node_bit;
  
  	for (;;) {
  		if (bitmap != 0) {
  			while ((bitmap & NETLBL_CATMAP_BIT) == 0) {
  				bitmap >>= 1;
  				node_bit++;
  			}
  			return iter->startbit +
  				(NETLBL_CATMAP_MAPSIZE * node_idx) + node_bit;
  		}
  		if (++node_idx >= NETLBL_CATMAP_MAPCNT) {
  			if (iter->next != NULL) {
  				iter = iter->next;
  				node_idx = 0;
  			} else
  				return -ENOENT;
  		}
  		bitmap = iter->bitmap[node_idx];
  		node_bit = 0;
  	}
  
  	return -ENOENT;
  }
  
  /**
   * netlbl_secattr_catmap_walk_rng - Find the end of a string of set bits
   * @catmap: the category bitmap
   * @offset: the offset to start searching at, in bits
   *
   * Description:
   * This function walks a LSM secattr category bitmap starting at @offset and
   * returns the spot of the first cleared bit or -ENOENT if the offset is past
   * the end of the bitmap.
   *
   */
  int netlbl_secattr_catmap_walk_rng(struct netlbl_lsm_secattr_catmap *catmap,
  				   u32 offset)
  {
  	struct netlbl_lsm_secattr_catmap *iter = catmap;
  	u32 node_idx;
  	u32 node_bit;
  	NETLBL_CATMAP_MAPTYPE bitmask;
  	NETLBL_CATMAP_MAPTYPE bitmap;
  
  	if (offset > iter->startbit) {
  		while (offset >= (iter->startbit + NETLBL_CATMAP_SIZE)) {
  			iter = iter->next;
  			if (iter == NULL)
  				return -ENOENT;
  		}
  		node_idx = (offset - iter->startbit) / NETLBL_CATMAP_MAPSIZE;
  		node_bit = offset - iter->startbit -
  			   (NETLBL_CATMAP_MAPSIZE * node_idx);
  	} else {
  		node_idx = 0;
  		node_bit = 0;
  	}
  	bitmask = NETLBL_CATMAP_BIT << node_bit;
  
  	for (;;) {
  		bitmap = iter->bitmap[node_idx];
  		while (bitmask != 0 && (bitmap & bitmask) != 0) {
  			bitmask <<= 1;
  			node_bit++;
  		}
  
  		if (bitmask != 0)
  			return iter->startbit +
  				(NETLBL_CATMAP_MAPSIZE * node_idx) +
  				node_bit - 1;
  		else if (++node_idx >= NETLBL_CATMAP_MAPCNT) {
  			if (iter->next == NULL)
  				return iter->startbit +	NETLBL_CATMAP_SIZE - 1;
  			iter = iter->next;
  			node_idx = 0;
  		}
  		bitmask = NETLBL_CATMAP_BIT;
  		node_bit = 0;
  	}
  
  	return -ENOENT;
  }
  
  /**
   * netlbl_secattr_catmap_setbit - Set a bit in a LSM secattr catmap
   * @catmap: the category bitmap
   * @bit: the bit to set
   * @flags: memory allocation flags
   *
   * Description:
   * Set the bit specified by @bit in @catmap.  Returns zero on success,
   * negative values on failure.
   *
   */
  int netlbl_secattr_catmap_setbit(struct netlbl_lsm_secattr_catmap *catmap,
  				 u32 bit,
  				 gfp_t flags)
  {
  	struct netlbl_lsm_secattr_catmap *iter = catmap;
  	u32 node_bit;
  	u32 node_idx;
  
  	while (iter->next != NULL &&
  	       bit >= (iter->startbit + NETLBL_CATMAP_SIZE))
  		iter = iter->next;
  	if (bit >= (iter->startbit + NETLBL_CATMAP_SIZE)) {
  		iter->next = netlbl_secattr_catmap_alloc(flags);
  		if (iter->next == NULL)
  			return -ENOMEM;
  		iter = iter->next;
  		iter->startbit = bit & ~(NETLBL_CATMAP_SIZE - 1);
  	}
  
  	/* gcc always rounds to zero when doing integer division */
  	node_idx = (bit - iter->startbit) / NETLBL_CATMAP_MAPSIZE;
  	node_bit = bit - iter->startbit - (NETLBL_CATMAP_MAPSIZE * node_idx);
  	iter->bitmap[node_idx] |= NETLBL_CATMAP_BIT << node_bit;
  
  	return 0;
  }
  
  /**
   * netlbl_secattr_catmap_setrng - Set a range of bits in a LSM secattr catmap
   * @catmap: the category bitmap
   * @start: the starting bit
   * @end: the last bit in the string
   * @flags: memory allocation flags
   *
   * Description:
   * Set a range of bits, starting at @start and ending with @end.  Returns zero
   * on success, negative values on failure.
   *
   */
  int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap *catmap,
  				 u32 start,
  				 u32 end,
  				 gfp_t flags)
  {
  	int ret_val = 0;
  	struct netlbl_lsm_secattr_catmap *iter = catmap;
  	u32 iter_max_spot;
  	u32 spot;
  
  	/* XXX - This could probably be made a bit faster by combining writes
  	 * to the catmap instead of setting a single bit each time, but for
  	 * right now skipping to the start of the range in the catmap should
  	 * be a nice improvement over calling the individual setbit function
  	 * repeatedly from a loop. */
  
  	while (iter->next != NULL &&
  	       start >= (iter->startbit + NETLBL_CATMAP_SIZE))
  		iter = iter->next;
  	iter_max_spot = iter->startbit + NETLBL_CATMAP_SIZE;
  
  	for (spot = start; spot <= end && ret_val == 0; spot++) {
  		if (spot >= iter_max_spot && iter->next != NULL) {
  			iter = iter->next;
  			iter_max_spot = iter->startbit + NETLBL_CATMAP_SIZE;
  		}
64b5fad52   Dan Carpenter   netlabel: use GFP...
596
  		ret_val = netlbl_secattr_catmap_setbit(iter, spot, flags);
027527603   Paul Moore   NetLabel: convert...
597
598
599
600
601
602
  	}
  
  	return ret_val;
  }
  
  /*
d15c345fe   Paul Moore   [NetLabel]: core ...
603
604
605
606
   * LSM Functions
   */
  
  /**
23bcdc1ad   Paul Moore   SELinux: enable d...
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
   * netlbl_enabled - Determine if the NetLabel subsystem is enabled
   *
   * Description:
   * The LSM can use this function to determine if it should use NetLabel
   * security attributes in it's enforcement mechanism.  Currently, NetLabel is
   * considered to be enabled when it's configuration contains a valid setup for
   * at least one labeled protocol (i.e. NetLabel can understand incoming
   * labeled packets of at least one type); otherwise NetLabel is considered to
   * be disabled.
   *
   */
  int netlbl_enabled(void)
  {
  	/* At some point we probably want to expose this mechanism to the user
  	 * as well so that admins can toggle NetLabel regardless of the
  	 * configuration */
c783f1ce5   Paul Moore   NetLabel: Remove ...
623
  	return (atomic_read(&netlabel_mgmt_protocount) > 0);
23bcdc1ad   Paul Moore   SELinux: enable d...
624
625
626
  }
  
  /**
389fb800a   Paul Moore   netlabel: Label i...
627
   * netlbl_sock_setattr - Label a socket using the correct protocol
ba6ff9f2b   Paul Moore   [NetLabel]: conso...
628
   * @sk: the socket to label
389fb800a   Paul Moore   netlabel: Label i...
629
   * @family: protocol family
d15c345fe   Paul Moore   [NetLabel]: core ...
630
631
632
633
   * @secattr: the security attributes
   *
   * Description:
   * Attach the correct label to the given socket using the security attributes
ba6ff9f2b   Paul Moore   [NetLabel]: conso...
634
635
   * specified in @secattr.  This function requires exclusive access to @sk,
   * which means it either needs to be in the process of being created or locked.
63c416887   Paul Moore   netlabel: Add net...
636
637
638
   * Returns zero on success, -EDESTADDRREQ if the domain is configured to use
   * network address selectors (can't blindly label the socket), and negative
   * values on all other failures.
d15c345fe   Paul Moore   [NetLabel]: core ...
639
640
   *
   */
ba6ff9f2b   Paul Moore   [NetLabel]: conso...
641
  int netlbl_sock_setattr(struct sock *sk,
389fb800a   Paul Moore   netlabel: Label i...
642
  			u16 family,
ba6ff9f2b   Paul Moore   [NetLabel]: conso...
643
  			const struct netlbl_lsm_secattr *secattr)
d15c345fe   Paul Moore   [NetLabel]: core ...
644
  {
389fb800a   Paul Moore   netlabel: Label i...
645
  	int ret_val;
d15c345fe   Paul Moore   [NetLabel]: core ...
646
647
648
649
  	struct netlbl_dom_map *dom_entry;
  
  	rcu_read_lock();
  	dom_entry = netlbl_domhsh_getentry(secattr->domain);
389fb800a   Paul Moore   netlabel: Label i...
650
651
  	if (dom_entry == NULL) {
  		ret_val = -ENOENT;
d15c345fe   Paul Moore   [NetLabel]: core ...
652
  		goto socket_setattr_return;
389fb800a   Paul Moore   netlabel: Label i...
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
  	}
  	switch (family) {
  	case AF_INET:
  		switch (dom_entry->type) {
  		case NETLBL_NLTYPE_ADDRSELECT:
  			ret_val = -EDESTADDRREQ;
  			break;
  		case NETLBL_NLTYPE_CIPSOV4:
  			ret_val = cipso_v4_sock_setattr(sk,
  						    dom_entry->type_def.cipsov4,
  						    secattr);
  			break;
  		case NETLBL_NLTYPE_UNLABELED:
  			ret_val = 0;
  			break;
  		default:
  			ret_val = -ENOENT;
  		}
d15c345fe   Paul Moore   [NetLabel]: core ...
671
  		break;
dfd56b8b3   Eric Dumazet   net: use IS_ENABL...
672
  #if IS_ENABLED(CONFIG_IPV6)
389fb800a   Paul Moore   netlabel: Label i...
673
674
675
  	case AF_INET6:
  		/* since we don't support any IPv6 labeling protocols right
  		 * now we can optimize everything away until we do */
d15c345fe   Paul Moore   [NetLabel]: core ...
676
677
  		ret_val = 0;
  		break;
389fb800a   Paul Moore   netlabel: Label i...
678
  #endif /* IPv6 */
d15c345fe   Paul Moore   [NetLabel]: core ...
679
  	default:
389fb800a   Paul Moore   netlabel: Label i...
680
  		ret_val = -EPROTONOSUPPORT;
d15c345fe   Paul Moore   [NetLabel]: core ...
681
682
683
684
685
686
687
688
  	}
  
  socket_setattr_return:
  	rcu_read_unlock();
  	return ret_val;
  }
  
  /**
014ab19a6   Paul Moore   selinux: Set sock...
689
690
691
692
693
694
695
696
697
698
699
700
701
702
   * netlbl_sock_delattr - Delete all the NetLabel labels on a socket
   * @sk: the socket
   *
   * Description:
   * Remove all the NetLabel labeling from @sk.  The caller is responsible for
   * ensuring that @sk is locked.
   *
   */
  void netlbl_sock_delattr(struct sock *sk)
  {
  	cipso_v4_sock_delattr(sk);
  }
  
  /**
14a72f53f   Paul Moore   [NetLabel]: corre...
703
704
705
706
707
   * netlbl_sock_getattr - Determine the security attributes of a sock
   * @sk: the sock
   * @secattr: the security attributes
   *
   * Description:
8cc44579d   Paul Moore   NetLabel: Introdu...
708
   * Examines the given sock to see if any NetLabel style labeling has been
14a72f53f   Paul Moore   [NetLabel]: corre...
709
710
711
712
713
   * applied to the sock, if so it parses the socket label and returns the
   * security attributes in @secattr.  Returns zero on success, negative values
   * on failure.
   *
   */
389fb800a   Paul Moore   netlabel: Label i...
714
715
  int netlbl_sock_getattr(struct sock *sk,
  			struct netlbl_lsm_secattr *secattr)
14a72f53f   Paul Moore   [NetLabel]: corre...
716
  {
389fb800a   Paul Moore   netlabel: Label i...
717
718
719
720
721
722
  	int ret_val;
  
  	switch (sk->sk_family) {
  	case AF_INET:
  		ret_val = cipso_v4_sock_getattr(sk, secattr);
  		break;
dfd56b8b3   Eric Dumazet   net: use IS_ENABL...
723
  #if IS_ENABLED(CONFIG_IPV6)
389fb800a   Paul Moore   netlabel: Label i...
724
725
726
727
728
729
730
731
732
  	case AF_INET6:
  		ret_val = -ENOMSG;
  		break;
  #endif /* IPv6 */
  	default:
  		ret_val = -EPROTONOSUPPORT;
  	}
  
  	return ret_val;
14a72f53f   Paul Moore   [NetLabel]: corre...
733
734
735
  }
  
  /**
014ab19a6   Paul Moore   selinux: Set sock...
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
   * netlbl_conn_setattr - Label a connected socket using the correct protocol
   * @sk: the socket to label
   * @addr: the destination address
   * @secattr: the security attributes
   *
   * Description:
   * Attach the correct label to the given connected socket using the security
   * attributes specified in @secattr.  The caller is responsible for ensuring
   * that @sk is locked.  Returns zero on success, negative values on failure.
   *
   */
  int netlbl_conn_setattr(struct sock *sk,
  			struct sockaddr *addr,
  			const struct netlbl_lsm_secattr *secattr)
  {
  	int ret_val;
  	struct sockaddr_in *addr4;
  	struct netlbl_domaddr4_map *af4_entry;
  
  	rcu_read_lock();
  	switch (addr->sa_family) {
  	case AF_INET:
  		addr4 = (struct sockaddr_in *)addr;
  		af4_entry = netlbl_domhsh_getentry_af4(secattr->domain,
  						       addr4->sin_addr.s_addr);
  		if (af4_entry == NULL) {
  			ret_val = -ENOENT;
  			goto conn_setattr_return;
  		}
  		switch (af4_entry->type) {
  		case NETLBL_NLTYPE_CIPSOV4:
  			ret_val = cipso_v4_sock_setattr(sk,
  						   af4_entry->type_def.cipsov4,
  						   secattr);
  			break;
  		case NETLBL_NLTYPE_UNLABELED:
  			/* just delete the protocols we support for right now
  			 * but we could remove other protocols if needed */
  			cipso_v4_sock_delattr(sk);
  			ret_val = 0;
  			break;
  		default:
  			ret_val = -ENOENT;
  		}
  		break;
dfd56b8b3   Eric Dumazet   net: use IS_ENABL...
781
  #if IS_ENABLED(CONFIG_IPV6)
014ab19a6   Paul Moore   selinux: Set sock...
782
783
784
785
786
787
788
  	case AF_INET6:
  		/* since we don't support any IPv6 labeling protocols right
  		 * now we can optimize everything away until we do */
  		ret_val = 0;
  		break;
  #endif /* IPv6 */
  	default:
389fb800a   Paul Moore   netlabel: Label i...
789
  		ret_val = -EPROTONOSUPPORT;
014ab19a6   Paul Moore   selinux: Set sock...
790
791
792
793
794
795
796
797
  	}
  
  conn_setattr_return:
  	rcu_read_unlock();
  	return ret_val;
  }
  
  /**
389fb800a   Paul Moore   netlabel: Label i...
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
   * netlbl_req_setattr - Label a request socket using the correct protocol
   * @req: the request socket to label
   * @secattr: the security attributes
   *
   * Description:
   * Attach the correct label to the given socket using the security attributes
   * specified in @secattr.  Returns zero on success, negative values on failure.
   *
   */
  int netlbl_req_setattr(struct request_sock *req,
  		       const struct netlbl_lsm_secattr *secattr)
  {
  	int ret_val;
  	struct netlbl_dom_map *dom_entry;
  	struct netlbl_domaddr4_map *af4_entry;
  	u32 proto_type;
  	struct cipso_v4_doi *proto_cv4;
  
  	rcu_read_lock();
  	dom_entry = netlbl_domhsh_getentry(secattr->domain);
  	if (dom_entry == NULL) {
  		ret_val = -ENOENT;
  		goto req_setattr_return;
  	}
  	switch (req->rsk_ops->family) {
  	case AF_INET:
  		if (dom_entry->type == NETLBL_NLTYPE_ADDRSELECT) {
  			struct inet_request_sock *req_inet = inet_rsk(req);
  			af4_entry = netlbl_domhsh_getentry_af4(secattr->domain,
  							    req_inet->rmt_addr);
  			if (af4_entry == NULL) {
  				ret_val = -ENOENT;
  				goto req_setattr_return;
  			}
  			proto_type = af4_entry->type;
  			proto_cv4 = af4_entry->type_def.cipsov4;
  		} else {
  			proto_type = dom_entry->type;
  			proto_cv4 = dom_entry->type_def.cipsov4;
  		}
  		switch (proto_type) {
  		case NETLBL_NLTYPE_CIPSOV4:
  			ret_val = cipso_v4_req_setattr(req, proto_cv4, secattr);
  			break;
  		case NETLBL_NLTYPE_UNLABELED:
  			/* just delete the protocols we support for right now
  			 * but we could remove other protocols if needed */
  			cipso_v4_req_delattr(req);
  			ret_val = 0;
  			break;
  		default:
  			ret_val = -ENOENT;
  		}
  		break;
dfd56b8b3   Eric Dumazet   net: use IS_ENABL...
852
  #if IS_ENABLED(CONFIG_IPV6)
389fb800a   Paul Moore   netlabel: Label i...
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
  	case AF_INET6:
  		/* since we don't support any IPv6 labeling protocols right
  		 * now we can optimize everything away until we do */
  		ret_val = 0;
  		break;
  #endif /* IPv6 */
  	default:
  		ret_val = -EPROTONOSUPPORT;
  	}
  
  req_setattr_return:
  	rcu_read_unlock();
  	return ret_val;
  }
  
  /**
07feee8f8   Paul Moore   netlabel: Cleanup...
869
870
871
872
873
874
875
876
877
878
879
880
881
  * netlbl_req_delattr - Delete all the NetLabel labels on a socket
  * @req: the socket
  *
  * Description:
  * Remove all the NetLabel labeling from @req.
  *
  */
  void netlbl_req_delattr(struct request_sock *req)
  {
  	cipso_v4_req_delattr(req);
  }
  
  /**
948bf85c1   Paul Moore   netlabel: Add fun...
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
   * netlbl_skbuff_setattr - Label a packet using the correct protocol
   * @skb: the packet
   * @family: protocol family
   * @secattr: the security attributes
   *
   * Description:
   * Attach the correct label to the given packet using the security attributes
   * specified in @secattr.  Returns zero on success, negative values on failure.
   *
   */
  int netlbl_skbuff_setattr(struct sk_buff *skb,
  			  u16 family,
  			  const struct netlbl_lsm_secattr *secattr)
  {
  	int ret_val;
  	struct iphdr *hdr4;
  	struct netlbl_domaddr4_map *af4_entry;
  
  	rcu_read_lock();
  	switch (family) {
  	case AF_INET:
  		hdr4 = ip_hdr(skb);
  		af4_entry = netlbl_domhsh_getentry_af4(secattr->domain,
  						       hdr4->daddr);
  		if (af4_entry == NULL) {
  			ret_val = -ENOENT;
  			goto skbuff_setattr_return;
  		}
  		switch (af4_entry->type) {
  		case NETLBL_NLTYPE_CIPSOV4:
  			ret_val = cipso_v4_skbuff_setattr(skb,
  						   af4_entry->type_def.cipsov4,
  						   secattr);
  			break;
  		case NETLBL_NLTYPE_UNLABELED:
  			/* just delete the protocols we support for right now
  			 * but we could remove other protocols if needed */
  			ret_val = cipso_v4_skbuff_delattr(skb);
  			break;
  		default:
  			ret_val = -ENOENT;
  		}
  		break;
dfd56b8b3   Eric Dumazet   net: use IS_ENABL...
925
  #if IS_ENABLED(CONFIG_IPV6)
948bf85c1   Paul Moore   netlabel: Add fun...
926
927
928
929
930
931
932
  	case AF_INET6:
  		/* since we don't support any IPv6 labeling protocols right
  		 * now we can optimize everything away until we do */
  		ret_val = 0;
  		break;
  #endif /* IPv6 */
  	default:
389fb800a   Paul Moore   netlabel: Label i...
933
  		ret_val = -EPROTONOSUPPORT;
948bf85c1   Paul Moore   netlabel: Add fun...
934
935
936
937
938
939
940
941
  	}
  
  skbuff_setattr_return:
  	rcu_read_unlock();
  	return ret_val;
  }
  
  /**
d15c345fe   Paul Moore   [NetLabel]: core ...
942
943
   * netlbl_skbuff_getattr - Determine the security attributes of a packet
   * @skb: the packet
75e22910c   Paul Moore   NetLabel: Add IP ...
944
   * @family: protocol family
d15c345fe   Paul Moore   [NetLabel]: core ...
945
946
947
948
949
950
951
952
953
954
   * @secattr: the security attributes
   *
   * Description:
   * Examines the given packet to see if a recognized form of packet labeling
   * is present, if so it parses the packet label and returns the security
   * attributes in @secattr.  Returns zero on success, negative values on
   * failure.
   *
   */
  int netlbl_skbuff_getattr(const struct sk_buff *skb,
75e22910c   Paul Moore   NetLabel: Add IP ...
955
  			  u16 family,
d15c345fe   Paul Moore   [NetLabel]: core ...
956
957
  			  struct netlbl_lsm_secattr *secattr)
  {
389fb800a   Paul Moore   netlabel: Label i...
958
959
960
961
962
963
  	switch (family) {
  	case AF_INET:
  		if (CIPSO_V4_OPTEXIST(skb) &&
  		    cipso_v4_skbuff_getattr(skb, secattr) == 0)
  			return 0;
  		break;
dfd56b8b3   Eric Dumazet   net: use IS_ENABL...
964
  #if IS_ENABLED(CONFIG_IPV6)
389fb800a   Paul Moore   netlabel: Label i...
965
966
967
968
  	case AF_INET6:
  		break;
  #endif /* IPv6 */
  	}
d15c345fe   Paul Moore   [NetLabel]: core ...
969

8cc44579d   Paul Moore   NetLabel: Introdu...
970
  	return netlbl_unlabel_getattr(skb, family, secattr);
d15c345fe   Paul Moore   [NetLabel]: core ...
971
972
973
974
975
976
  }
  
  /**
   * netlbl_skbuff_err - Handle a LSM error on a sk_buff
   * @skb: the packet
   * @error: the error code
dfaebe982   Paul Moore   selinux: Fix miss...
977
   * @gateway: true if host is acting as a gateway, false otherwise
d15c345fe   Paul Moore   [NetLabel]: core ...
978
979
980
981
982
983
984
   *
   * Description:
   * Deal with a LSM problem when handling the packet in @skb, typically this is
   * a permission denied problem (-EACCES).  The correct action is determined
   * according to the packet's labeling protocol.
   *
   */
dfaebe982   Paul Moore   selinux: Fix miss...
985
  void netlbl_skbuff_err(struct sk_buff *skb, int error, int gateway)
d15c345fe   Paul Moore   [NetLabel]: core ...
986
987
  {
  	if (CIPSO_V4_OPTEXIST(skb))
dfaebe982   Paul Moore   selinux: Fix miss...
988
  		cipso_v4_error(skb, error, gateway);
d15c345fe   Paul Moore   [NetLabel]: core ...
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
  }
  
  /**
   * netlbl_cache_invalidate - Invalidate all of the NetLabel protocol caches
   *
   * Description:
   * For all of the NetLabel protocols that support some form of label mapping
   * cache, invalidate the cache.  Returns zero on success, negative values on
   * error.
   *
   */
  void netlbl_cache_invalidate(void)
  {
  	cipso_v4_cache_invalidate();
  }
  
  /**
   * netlbl_cache_add - Add an entry to a NetLabel protocol cache
   * @skb: the packet
   * @secattr: the packet's security attributes
   *
   * Description:
   * Add the LSM security attributes for the given packet to the underlying
   * NetLabel protocol's label mapping cache.  Returns zero on success, negative
   * values on error.
   *
   */
  int netlbl_cache_add(const struct sk_buff *skb,
  		     const struct netlbl_lsm_secattr *secattr)
  {
701a90bad   Paul Moore   NetLabel: make ne...
1019
  	if ((secattr->flags & NETLBL_SECATTR_CACHE) == 0)
d15c345fe   Paul Moore   [NetLabel]: core ...
1020
1021
1022
1023
1024
1025
1026
1027
1028
  		return -ENOMSG;
  
  	if (CIPSO_V4_OPTEXIST(skb))
  		return cipso_v4_cache_add(skb, secattr);
  
  	return -ENOMSG;
  }
  
  /*
6c2e8ac09   Paul Moore   netlabel: Update ...
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
   * Protocol Engine Functions
   */
  
  /**
   * netlbl_audit_start - Start an audit message
   * @type: audit message type
   * @audit_info: NetLabel audit information
   *
   * Description:
   * Start an audit message using the type specified in @type and fill the audit
   * message with some fields common to all NetLabel audit messages.  This
   * function should only be used by protocol engines, not LSMs.  Returns a
   * pointer to the audit buffer on success, NULL on failure.
   *
   */
  struct audit_buffer *netlbl_audit_start(int type,
  					struct netlbl_audit *audit_info)
  {
  	return netlbl_audit_start_common(type, audit_info);
  }
  
  /*
d15c345fe   Paul Moore   [NetLabel]: core ...
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
   * Setup Functions
   */
  
  /**
   * netlbl_init - Initialize NetLabel
   *
   * Description:
   * Perform the required NetLabel initialization before first use.
   *
   */
  static int __init netlbl_init(void)
  {
  	int ret_val;
  
  	printk(KERN_INFO "NetLabel: Initializing
  ");
  	printk(KERN_INFO "NetLabel:  domain hash size = %u
  ",
  	       (1 << NETLBL_DOMHSH_BITSIZE));
  	printk(KERN_INFO "NetLabel:  protocols ="
  	       " UNLABELED"
  	       " CIPSOv4"
  	       "
  ");
  
  	ret_val = netlbl_domhsh_init(NETLBL_DOMHSH_BITSIZE);
  	if (ret_val != 0)
  		goto init_failure;
8cc44579d   Paul Moore   NetLabel: Introdu...
1079
1080
1081
  	ret_val = netlbl_unlabel_init(NETLBL_UNLHSH_BITSIZE);
  	if (ret_val != 0)
  		goto init_failure;
d15c345fe   Paul Moore   [NetLabel]: core ...
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
  	ret_val = netlbl_netlink_init();
  	if (ret_val != 0)
  		goto init_failure;
  
  	ret_val = netlbl_unlabel_defconf();
  	if (ret_val != 0)
  		goto init_failure;
  	printk(KERN_INFO "NetLabel:  unlabeled traffic allowed by default
  ");
  
  	return 0;
  
  init_failure:
  	panic("NetLabel: failed to initialize properly (%d)
  ", ret_val);
  }
  
  subsys_initcall(netlbl_init);