0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #include <linux/init.h>
0017 #include <linux/types.h>
0018 #include <linux/slab.h>
0019 #include <linux/audit.h>
0020 #include <linux/in.h>
0021 #include <linux/in6.h>
0022 #include <net/ip.h>
0023 #include <net/ipv6.h>
0024 #include <net/netlabel.h>
0025 #include <net/cipso_ipv4.h>
0026 #include <net/calipso.h>
0027 #include <asm/bug.h>
0028 #include <linux/atomic.h>
0029
0030 #include "netlabel_domainhash.h"
0031 #include "netlabel_unlabeled.h"
0032 #include "netlabel_cipso_v4.h"
0033 #include "netlabel_calipso.h"
0034 #include "netlabel_user.h"
0035 #include "netlabel_mgmt.h"
0036 #include "netlabel_addrlist.h"
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056 int netlbl_cfg_map_del(const char *domain,
0057 u16 family,
0058 const void *addr,
0059 const void *mask,
0060 struct netlbl_audit *audit_info)
0061 {
0062 if (addr == NULL && mask == NULL) {
0063 return netlbl_domhsh_remove(domain, family, audit_info);
0064 } else if (addr != NULL && mask != NULL) {
0065 switch (family) {
0066 case AF_INET:
0067 return netlbl_domhsh_remove_af4(domain, addr, mask,
0068 audit_info);
0069 #if IS_ENABLED(CONFIG_IPV6)
0070 case AF_INET6:
0071 return netlbl_domhsh_remove_af6(domain, addr, mask,
0072 audit_info);
0073 #endif
0074 default:
0075 return -EPFNOSUPPORT;
0076 }
0077 } else
0078 return -EINVAL;
0079 }
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095 int netlbl_cfg_unlbl_map_add(const char *domain,
0096 u16 family,
0097 const void *addr,
0098 const void *mask,
0099 struct netlbl_audit *audit_info)
0100 {
0101 int ret_val = -ENOMEM;
0102 struct netlbl_dom_map *entry;
0103 struct netlbl_domaddr_map *addrmap = NULL;
0104 struct netlbl_domaddr4_map *map4 = NULL;
0105 struct netlbl_domaddr6_map *map6 = NULL;
0106
0107 entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
0108 if (entry == NULL)
0109 return -ENOMEM;
0110 if (domain != NULL) {
0111 entry->domain = kstrdup(domain, GFP_ATOMIC);
0112 if (entry->domain == NULL)
0113 goto cfg_unlbl_map_add_failure;
0114 }
0115 entry->family = family;
0116
0117 if (addr == NULL && mask == NULL)
0118 entry->def.type = NETLBL_NLTYPE_UNLABELED;
0119 else if (addr != NULL && mask != NULL) {
0120 addrmap = kzalloc(sizeof(*addrmap), GFP_ATOMIC);
0121 if (addrmap == NULL)
0122 goto cfg_unlbl_map_add_failure;
0123 INIT_LIST_HEAD(&addrmap->list4);
0124 INIT_LIST_HEAD(&addrmap->list6);
0125
0126 switch (family) {
0127 case AF_INET: {
0128 const struct in_addr *addr4 = addr;
0129 const struct in_addr *mask4 = mask;
0130 map4 = kzalloc(sizeof(*map4), GFP_ATOMIC);
0131 if (map4 == NULL)
0132 goto cfg_unlbl_map_add_failure;
0133 map4->def.type = NETLBL_NLTYPE_UNLABELED;
0134 map4->list.addr = addr4->s_addr & mask4->s_addr;
0135 map4->list.mask = mask4->s_addr;
0136 map4->list.valid = 1;
0137 ret_val = netlbl_af4list_add(&map4->list,
0138 &addrmap->list4);
0139 if (ret_val != 0)
0140 goto cfg_unlbl_map_add_failure;
0141 break;
0142 }
0143 #if IS_ENABLED(CONFIG_IPV6)
0144 case AF_INET6: {
0145 const struct in6_addr *addr6 = addr;
0146 const struct in6_addr *mask6 = mask;
0147 map6 = kzalloc(sizeof(*map6), GFP_ATOMIC);
0148 if (map6 == NULL)
0149 goto cfg_unlbl_map_add_failure;
0150 map6->def.type = NETLBL_NLTYPE_UNLABELED;
0151 map6->list.addr = *addr6;
0152 map6->list.addr.s6_addr32[0] &= mask6->s6_addr32[0];
0153 map6->list.addr.s6_addr32[1] &= mask6->s6_addr32[1];
0154 map6->list.addr.s6_addr32[2] &= mask6->s6_addr32[2];
0155 map6->list.addr.s6_addr32[3] &= mask6->s6_addr32[3];
0156 map6->list.mask = *mask6;
0157 map6->list.valid = 1;
0158 ret_val = netlbl_af6list_add(&map6->list,
0159 &addrmap->list6);
0160 if (ret_val != 0)
0161 goto cfg_unlbl_map_add_failure;
0162 break;
0163 }
0164 #endif
0165 default:
0166 goto cfg_unlbl_map_add_failure;
0167 }
0168
0169 entry->def.addrsel = addrmap;
0170 entry->def.type = NETLBL_NLTYPE_ADDRSELECT;
0171 } else {
0172 ret_val = -EINVAL;
0173 goto cfg_unlbl_map_add_failure;
0174 }
0175
0176 ret_val = netlbl_domhsh_add(entry, audit_info);
0177 if (ret_val != 0)
0178 goto cfg_unlbl_map_add_failure;
0179
0180 return 0;
0181
0182 cfg_unlbl_map_add_failure:
0183 kfree(entry->domain);
0184 kfree(entry);
0185 kfree(addrmap);
0186 kfree(map4);
0187 kfree(map6);
0188 return ret_val;
0189 }
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208 int netlbl_cfg_unlbl_static_add(struct net *net,
0209 const char *dev_name,
0210 const void *addr,
0211 const void *mask,
0212 u16 family,
0213 u32 secid,
0214 struct netlbl_audit *audit_info)
0215 {
0216 u32 addr_len;
0217
0218 switch (family) {
0219 case AF_INET:
0220 addr_len = sizeof(struct in_addr);
0221 break;
0222 #if IS_ENABLED(CONFIG_IPV6)
0223 case AF_INET6:
0224 addr_len = sizeof(struct in6_addr);
0225 break;
0226 #endif
0227 default:
0228 return -EPFNOSUPPORT;
0229 }
0230
0231 return netlbl_unlhsh_add(net,
0232 dev_name, addr, mask, addr_len,
0233 secid, audit_info);
0234 }
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251 int netlbl_cfg_unlbl_static_del(struct net *net,
0252 const char *dev_name,
0253 const void *addr,
0254 const void *mask,
0255 u16 family,
0256 struct netlbl_audit *audit_info)
0257 {
0258 u32 addr_len;
0259
0260 switch (family) {
0261 case AF_INET:
0262 addr_len = sizeof(struct in_addr);
0263 break;
0264 #if IS_ENABLED(CONFIG_IPV6)
0265 case AF_INET6:
0266 addr_len = sizeof(struct in6_addr);
0267 break;
0268 #endif
0269 default:
0270 return -EPFNOSUPPORT;
0271 }
0272
0273 return netlbl_unlhsh_remove(net,
0274 dev_name, addr, mask, addr_len,
0275 audit_info);
0276 }
0277
0278
0279
0280
0281
0282
0283
0284
0285
0286
0287
0288 int netlbl_cfg_cipsov4_add(struct cipso_v4_doi *doi_def,
0289 struct netlbl_audit *audit_info)
0290 {
0291 return cipso_v4_doi_add(doi_def, audit_info);
0292 }
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302
0303
0304 void netlbl_cfg_cipsov4_del(u32 doi, struct netlbl_audit *audit_info)
0305 {
0306 cipso_v4_doi_remove(doi, audit_info);
0307 }
0308
0309
0310
0311
0312
0313
0314
0315
0316
0317
0318
0319
0320
0321
0322
0323 int netlbl_cfg_cipsov4_map_add(u32 doi,
0324 const char *domain,
0325 const struct in_addr *addr,
0326 const struct in_addr *mask,
0327 struct netlbl_audit *audit_info)
0328 {
0329 int ret_val = -ENOMEM;
0330 struct cipso_v4_doi *doi_def;
0331 struct netlbl_dom_map *entry;
0332 struct netlbl_domaddr_map *addrmap = NULL;
0333 struct netlbl_domaddr4_map *addrinfo = NULL;
0334
0335 doi_def = cipso_v4_doi_getdef(doi);
0336 if (doi_def == NULL)
0337 return -ENOENT;
0338
0339 entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
0340 if (entry == NULL)
0341 goto out_entry;
0342 entry->family = AF_INET;
0343 if (domain != NULL) {
0344 entry->domain = kstrdup(domain, GFP_ATOMIC);
0345 if (entry->domain == NULL)
0346 goto out_domain;
0347 }
0348
0349 if (addr == NULL && mask == NULL) {
0350 entry->def.cipso = doi_def;
0351 entry->def.type = NETLBL_NLTYPE_CIPSOV4;
0352 } else if (addr != NULL && mask != NULL) {
0353 addrmap = kzalloc(sizeof(*addrmap), GFP_ATOMIC);
0354 if (addrmap == NULL)
0355 goto out_addrmap;
0356 INIT_LIST_HEAD(&addrmap->list4);
0357 INIT_LIST_HEAD(&addrmap->list6);
0358
0359 addrinfo = kzalloc(sizeof(*addrinfo), GFP_ATOMIC);
0360 if (addrinfo == NULL)
0361 goto out_addrinfo;
0362 addrinfo->def.cipso = doi_def;
0363 addrinfo->def.type = NETLBL_NLTYPE_CIPSOV4;
0364 addrinfo->list.addr = addr->s_addr & mask->s_addr;
0365 addrinfo->list.mask = mask->s_addr;
0366 addrinfo->list.valid = 1;
0367 ret_val = netlbl_af4list_add(&addrinfo->list, &addrmap->list4);
0368 if (ret_val != 0)
0369 goto cfg_cipsov4_map_add_failure;
0370
0371 entry->def.addrsel = addrmap;
0372 entry->def.type = NETLBL_NLTYPE_ADDRSELECT;
0373 } else {
0374 ret_val = -EINVAL;
0375 goto out_addrmap;
0376 }
0377
0378 ret_val = netlbl_domhsh_add(entry, audit_info);
0379 if (ret_val != 0)
0380 goto cfg_cipsov4_map_add_failure;
0381
0382 return 0;
0383
0384 cfg_cipsov4_map_add_failure:
0385 kfree(addrinfo);
0386 out_addrinfo:
0387 kfree(addrmap);
0388 out_addrmap:
0389 kfree(entry->domain);
0390 out_domain:
0391 kfree(entry);
0392 out_entry:
0393 cipso_v4_doi_putdef(doi_def);
0394 return ret_val;
0395 }
0396
0397
0398
0399
0400
0401
0402
0403
0404
0405
0406
0407 int netlbl_cfg_calipso_add(struct calipso_doi *doi_def,
0408 struct netlbl_audit *audit_info)
0409 {
0410 #if IS_ENABLED(CONFIG_IPV6)
0411 return calipso_doi_add(doi_def, audit_info);
0412 #else
0413 return -ENOSYS;
0414 #endif
0415 }
0416
0417
0418
0419
0420
0421
0422
0423
0424
0425
0426
0427 void netlbl_cfg_calipso_del(u32 doi, struct netlbl_audit *audit_info)
0428 {
0429 #if IS_ENABLED(CONFIG_IPV6)
0430 calipso_doi_remove(doi, audit_info);
0431 #endif
0432 }
0433
0434
0435
0436
0437
0438
0439
0440
0441
0442
0443
0444
0445
0446
0447
0448 int netlbl_cfg_calipso_map_add(u32 doi,
0449 const char *domain,
0450 const struct in6_addr *addr,
0451 const struct in6_addr *mask,
0452 struct netlbl_audit *audit_info)
0453 {
0454 #if IS_ENABLED(CONFIG_IPV6)
0455 int ret_val = -ENOMEM;
0456 struct calipso_doi *doi_def;
0457 struct netlbl_dom_map *entry;
0458 struct netlbl_domaddr_map *addrmap = NULL;
0459 struct netlbl_domaddr6_map *addrinfo = NULL;
0460
0461 doi_def = calipso_doi_getdef(doi);
0462 if (doi_def == NULL)
0463 return -ENOENT;
0464
0465 entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
0466 if (entry == NULL)
0467 goto out_entry;
0468 entry->family = AF_INET6;
0469 if (domain != NULL) {
0470 entry->domain = kstrdup(domain, GFP_ATOMIC);
0471 if (entry->domain == NULL)
0472 goto out_domain;
0473 }
0474
0475 if (addr == NULL && mask == NULL) {
0476 entry->def.calipso = doi_def;
0477 entry->def.type = NETLBL_NLTYPE_CALIPSO;
0478 } else if (addr != NULL && mask != NULL) {
0479 addrmap = kzalloc(sizeof(*addrmap), GFP_ATOMIC);
0480 if (addrmap == NULL)
0481 goto out_addrmap;
0482 INIT_LIST_HEAD(&addrmap->list4);
0483 INIT_LIST_HEAD(&addrmap->list6);
0484
0485 addrinfo = kzalloc(sizeof(*addrinfo), GFP_ATOMIC);
0486 if (addrinfo == NULL)
0487 goto out_addrinfo;
0488 addrinfo->def.calipso = doi_def;
0489 addrinfo->def.type = NETLBL_NLTYPE_CALIPSO;
0490 addrinfo->list.addr = *addr;
0491 addrinfo->list.addr.s6_addr32[0] &= mask->s6_addr32[0];
0492 addrinfo->list.addr.s6_addr32[1] &= mask->s6_addr32[1];
0493 addrinfo->list.addr.s6_addr32[2] &= mask->s6_addr32[2];
0494 addrinfo->list.addr.s6_addr32[3] &= mask->s6_addr32[3];
0495 addrinfo->list.mask = *mask;
0496 addrinfo->list.valid = 1;
0497 ret_val = netlbl_af6list_add(&addrinfo->list, &addrmap->list6);
0498 if (ret_val != 0)
0499 goto cfg_calipso_map_add_failure;
0500
0501 entry->def.addrsel = addrmap;
0502 entry->def.type = NETLBL_NLTYPE_ADDRSELECT;
0503 } else {
0504 ret_val = -EINVAL;
0505 goto out_addrmap;
0506 }
0507
0508 ret_val = netlbl_domhsh_add(entry, audit_info);
0509 if (ret_val != 0)
0510 goto cfg_calipso_map_add_failure;
0511
0512 return 0;
0513
0514 cfg_calipso_map_add_failure:
0515 kfree(addrinfo);
0516 out_addrinfo:
0517 kfree(addrmap);
0518 out_addrmap:
0519 kfree(entry->domain);
0520 out_domain:
0521 kfree(entry);
0522 out_entry:
0523 calipso_doi_putdef(doi_def);
0524 return ret_val;
0525 #else
0526 return -ENOSYS;
0527 #endif
0528 }
0529
0530
0531
0532
0533
0534 #define _CM_F_NONE 0x00000000
0535 #define _CM_F_ALLOC 0x00000001
0536 #define _CM_F_WALK 0x00000002
0537
0538
0539
0540
0541
0542
0543
0544
0545
0546
0547
0548
0549
0550
0551
0552
0553 static struct netlbl_lsm_catmap *_netlbl_catmap_getnode(
0554 struct netlbl_lsm_catmap **catmap,
0555 u32 offset,
0556 unsigned int cm_flags,
0557 gfp_t gfp_flags)
0558 {
0559 struct netlbl_lsm_catmap *iter = *catmap;
0560 struct netlbl_lsm_catmap *prev = NULL;
0561
0562 if (iter == NULL)
0563 goto catmap_getnode_alloc;
0564 if (offset < iter->startbit)
0565 goto catmap_getnode_walk;
0566 while (iter && offset >= (iter->startbit + NETLBL_CATMAP_SIZE)) {
0567 prev = iter;
0568 iter = iter->next;
0569 }
0570 if (iter == NULL || offset < iter->startbit)
0571 goto catmap_getnode_walk;
0572
0573 return iter;
0574
0575 catmap_getnode_walk:
0576 if (cm_flags & _CM_F_WALK)
0577 return iter;
0578 catmap_getnode_alloc:
0579 if (!(cm_flags & _CM_F_ALLOC))
0580 return NULL;
0581
0582 iter = netlbl_catmap_alloc(gfp_flags);
0583 if (iter == NULL)
0584 return NULL;
0585 iter->startbit = offset & ~(NETLBL_CATMAP_SIZE - 1);
0586
0587 if (prev == NULL) {
0588 iter->next = *catmap;
0589 *catmap = iter;
0590 } else {
0591 iter->next = prev->next;
0592 prev->next = iter;
0593 }
0594
0595 return iter;
0596 }
0597
0598
0599
0600
0601
0602
0603
0604
0605
0606
0607
0608 int netlbl_catmap_walk(struct netlbl_lsm_catmap *catmap, u32 offset)
0609 {
0610 struct netlbl_lsm_catmap *iter;
0611 u32 idx;
0612 u32 bit;
0613 NETLBL_CATMAP_MAPTYPE bitmap;
0614
0615 iter = _netlbl_catmap_getnode(&catmap, offset, _CM_F_WALK, 0);
0616 if (iter == NULL)
0617 return -ENOENT;
0618 if (offset > iter->startbit) {
0619 offset -= iter->startbit;
0620 idx = offset / NETLBL_CATMAP_MAPSIZE;
0621 bit = offset % NETLBL_CATMAP_MAPSIZE;
0622 } else {
0623 idx = 0;
0624 bit = 0;
0625 }
0626 bitmap = iter->bitmap[idx] >> bit;
0627
0628 for (;;) {
0629 if (bitmap != 0) {
0630 while ((bitmap & NETLBL_CATMAP_BIT) == 0) {
0631 bitmap >>= 1;
0632 bit++;
0633 }
0634 return iter->startbit +
0635 (NETLBL_CATMAP_MAPSIZE * idx) + bit;
0636 }
0637 if (++idx >= NETLBL_CATMAP_MAPCNT) {
0638 if (iter->next != NULL) {
0639 iter = iter->next;
0640 idx = 0;
0641 } else
0642 return -ENOENT;
0643 }
0644 bitmap = iter->bitmap[idx];
0645 bit = 0;
0646 }
0647
0648 return -ENOENT;
0649 }
0650 EXPORT_SYMBOL(netlbl_catmap_walk);
0651
0652
0653
0654
0655
0656
0657
0658
0659
0660
0661
0662
0663 int netlbl_catmap_walkrng(struct netlbl_lsm_catmap *catmap, u32 offset)
0664 {
0665 struct netlbl_lsm_catmap *iter;
0666 struct netlbl_lsm_catmap *prev = NULL;
0667 u32 idx;
0668 u32 bit;
0669 NETLBL_CATMAP_MAPTYPE bitmask;
0670 NETLBL_CATMAP_MAPTYPE bitmap;
0671
0672 iter = _netlbl_catmap_getnode(&catmap, offset, _CM_F_WALK, 0);
0673 if (iter == NULL)
0674 return -ENOENT;
0675 if (offset > iter->startbit) {
0676 offset -= iter->startbit;
0677 idx = offset / NETLBL_CATMAP_MAPSIZE;
0678 bit = offset % NETLBL_CATMAP_MAPSIZE;
0679 } else {
0680 idx = 0;
0681 bit = 0;
0682 }
0683 bitmask = NETLBL_CATMAP_BIT << bit;
0684
0685 for (;;) {
0686 bitmap = iter->bitmap[idx];
0687 while (bitmask != 0 && (bitmap & bitmask) != 0) {
0688 bitmask <<= 1;
0689 bit++;
0690 }
0691
0692 if (prev && idx == 0 && bit == 0)
0693 return prev->startbit + NETLBL_CATMAP_SIZE - 1;
0694 else if (bitmask != 0)
0695 return iter->startbit +
0696 (NETLBL_CATMAP_MAPSIZE * idx) + bit - 1;
0697 else if (++idx >= NETLBL_CATMAP_MAPCNT) {
0698 if (iter->next == NULL)
0699 return iter->startbit + NETLBL_CATMAP_SIZE - 1;
0700 prev = iter;
0701 iter = iter->next;
0702 idx = 0;
0703 }
0704 bitmask = NETLBL_CATMAP_BIT;
0705 bit = 0;
0706 }
0707
0708 return -ENOENT;
0709 }
0710
0711
0712
0713
0714
0715
0716
0717
0718
0719
0720
0721
0722
0723
0724
0725 int netlbl_catmap_getlong(struct netlbl_lsm_catmap *catmap,
0726 u32 *offset,
0727 unsigned long *bitmap)
0728 {
0729 struct netlbl_lsm_catmap *iter;
0730 u32 off = *offset;
0731 u32 idx;
0732
0733
0734 if ((off & (BITS_PER_LONG - 1)) != 0)
0735 return -EINVAL;
0736
0737
0738 if (!catmap) {
0739 *offset = (u32)-1;
0740 return 0;
0741 }
0742
0743 if (off < catmap->startbit) {
0744 off = catmap->startbit;
0745 *offset = off;
0746 }
0747 iter = _netlbl_catmap_getnode(&catmap, off, _CM_F_WALK, 0);
0748 if (iter == NULL) {
0749 *offset = (u32)-1;
0750 return 0;
0751 }
0752
0753 if (off < iter->startbit) {
0754 *offset = iter->startbit;
0755 off = 0;
0756 } else
0757 off -= iter->startbit;
0758 idx = off / NETLBL_CATMAP_MAPSIZE;
0759 *bitmap = iter->bitmap[idx] >> (off % NETLBL_CATMAP_MAPSIZE);
0760
0761 return 0;
0762 }
0763
0764
0765
0766
0767
0768
0769
0770
0771
0772
0773
0774
0775 int netlbl_catmap_setbit(struct netlbl_lsm_catmap **catmap,
0776 u32 bit,
0777 gfp_t flags)
0778 {
0779 struct netlbl_lsm_catmap *iter;
0780 u32 idx;
0781
0782 iter = _netlbl_catmap_getnode(catmap, bit, _CM_F_ALLOC, flags);
0783 if (iter == NULL)
0784 return -ENOMEM;
0785
0786 bit -= iter->startbit;
0787 idx = bit / NETLBL_CATMAP_MAPSIZE;
0788 iter->bitmap[idx] |= NETLBL_CATMAP_BIT << (bit % NETLBL_CATMAP_MAPSIZE);
0789
0790 return 0;
0791 }
0792 EXPORT_SYMBOL(netlbl_catmap_setbit);
0793
0794
0795
0796
0797
0798
0799
0800
0801
0802
0803
0804
0805
0806 int netlbl_catmap_setrng(struct netlbl_lsm_catmap **catmap,
0807 u32 start,
0808 u32 end,
0809 gfp_t flags)
0810 {
0811 int rc = 0;
0812 u32 spot = start;
0813
0814 while (rc == 0 && spot <= end) {
0815 if (((spot & (BITS_PER_LONG - 1)) == 0) &&
0816 ((end - spot) > BITS_PER_LONG)) {
0817 rc = netlbl_catmap_setlong(catmap,
0818 spot,
0819 (unsigned long)-1,
0820 flags);
0821 spot += BITS_PER_LONG;
0822 } else
0823 rc = netlbl_catmap_setbit(catmap, spot++, flags);
0824 }
0825
0826 return rc;
0827 }
0828
0829
0830
0831
0832
0833
0834
0835
0836
0837
0838
0839
0840
0841
0842 int netlbl_catmap_setlong(struct netlbl_lsm_catmap **catmap,
0843 u32 offset,
0844 unsigned long bitmap,
0845 gfp_t flags)
0846 {
0847 struct netlbl_lsm_catmap *iter;
0848 u32 idx;
0849
0850
0851 if ((offset & (BITS_PER_LONG - 1)) != 0)
0852 return -EINVAL;
0853
0854 iter = _netlbl_catmap_getnode(catmap, offset, _CM_F_ALLOC, flags);
0855 if (iter == NULL)
0856 return -ENOMEM;
0857
0858 offset -= iter->startbit;
0859 idx = offset / NETLBL_CATMAP_MAPSIZE;
0860 iter->bitmap[idx] |= bitmap << (offset % NETLBL_CATMAP_MAPSIZE);
0861
0862 return 0;
0863 }
0864
0865
0866
0867
0868
0869
0870
0871
0872
0873
0874
0875
0876
0877
0878
0879
0880 int netlbl_bitmap_walk(const unsigned char *bitmap, u32 bitmap_len,
0881 u32 offset, u8 state)
0882 {
0883 u32 bit_spot;
0884 u32 byte_offset;
0885 unsigned char bitmask;
0886 unsigned char byte;
0887
0888 if (offset >= bitmap_len)
0889 return -1;
0890 byte_offset = offset / 8;
0891 byte = bitmap[byte_offset];
0892 bit_spot = offset;
0893 bitmask = 0x80 >> (offset % 8);
0894
0895 while (bit_spot < bitmap_len) {
0896 if ((state && (byte & bitmask) == bitmask) ||
0897 (state == 0 && (byte & bitmask) == 0))
0898 return bit_spot;
0899
0900 if (++bit_spot >= bitmap_len)
0901 return -1;
0902 bitmask >>= 1;
0903 if (bitmask == 0) {
0904 byte = bitmap[++byte_offset];
0905 bitmask = 0x80;
0906 }
0907 }
0908
0909 return -1;
0910 }
0911 EXPORT_SYMBOL(netlbl_bitmap_walk);
0912
0913
0914
0915
0916
0917
0918
0919
0920
0921
0922
0923 void netlbl_bitmap_setbit(unsigned char *bitmap, u32 bit, u8 state)
0924 {
0925 u32 byte_spot;
0926 u8 bitmask;
0927
0928
0929 byte_spot = bit / 8;
0930 bitmask = 0x80 >> (bit % 8);
0931 if (state)
0932 bitmap[byte_spot] |= bitmask;
0933 else
0934 bitmap[byte_spot] &= ~bitmask;
0935 }
0936 EXPORT_SYMBOL(netlbl_bitmap_setbit);
0937
0938
0939
0940
0941
0942
0943
0944
0945
0946
0947
0948
0949
0950
0951
0952
0953
0954 int netlbl_enabled(void)
0955 {
0956
0957
0958
0959 return (atomic_read(&netlabel_mgmt_protocount) > 0);
0960 }
0961
0962
0963
0964
0965
0966
0967
0968
0969
0970
0971
0972
0973
0974
0975
0976
0977 int netlbl_sock_setattr(struct sock *sk,
0978 u16 family,
0979 const struct netlbl_lsm_secattr *secattr)
0980 {
0981 int ret_val;
0982 struct netlbl_dom_map *dom_entry;
0983
0984 rcu_read_lock();
0985 dom_entry = netlbl_domhsh_getentry(secattr->domain, family);
0986 if (dom_entry == NULL) {
0987 ret_val = -ENOENT;
0988 goto socket_setattr_return;
0989 }
0990 switch (family) {
0991 case AF_INET:
0992 switch (dom_entry->def.type) {
0993 case NETLBL_NLTYPE_ADDRSELECT:
0994 ret_val = -EDESTADDRREQ;
0995 break;
0996 case NETLBL_NLTYPE_CIPSOV4:
0997 ret_val = cipso_v4_sock_setattr(sk,
0998 dom_entry->def.cipso,
0999 secattr);
1000 break;
1001 case NETLBL_NLTYPE_UNLABELED:
1002 ret_val = 0;
1003 break;
1004 default:
1005 ret_val = -ENOENT;
1006 }
1007 break;
1008 #if IS_ENABLED(CONFIG_IPV6)
1009 case AF_INET6:
1010 switch (dom_entry->def.type) {
1011 case NETLBL_NLTYPE_ADDRSELECT:
1012 ret_val = -EDESTADDRREQ;
1013 break;
1014 case NETLBL_NLTYPE_CALIPSO:
1015 ret_val = calipso_sock_setattr(sk,
1016 dom_entry->def.calipso,
1017 secattr);
1018 break;
1019 case NETLBL_NLTYPE_UNLABELED:
1020 ret_val = 0;
1021 break;
1022 default:
1023 ret_val = -ENOENT;
1024 }
1025 break;
1026 #endif
1027 default:
1028 ret_val = -EPROTONOSUPPORT;
1029 }
1030
1031 socket_setattr_return:
1032 rcu_read_unlock();
1033 return ret_val;
1034 }
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045 void netlbl_sock_delattr(struct sock *sk)
1046 {
1047 switch (sk->sk_family) {
1048 case AF_INET:
1049 cipso_v4_sock_delattr(sk);
1050 break;
1051 #if IS_ENABLED(CONFIG_IPV6)
1052 case AF_INET6:
1053 calipso_sock_delattr(sk);
1054 break;
1055 #endif
1056 }
1057 }
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071 int netlbl_sock_getattr(struct sock *sk,
1072 struct netlbl_lsm_secattr *secattr)
1073 {
1074 int ret_val;
1075
1076 switch (sk->sk_family) {
1077 case AF_INET:
1078 ret_val = cipso_v4_sock_getattr(sk, secattr);
1079 break;
1080 #if IS_ENABLED(CONFIG_IPV6)
1081 case AF_INET6:
1082 ret_val = calipso_sock_getattr(sk, secattr);
1083 break;
1084 #endif
1085 default:
1086 ret_val = -EPROTONOSUPPORT;
1087 }
1088
1089 return ret_val;
1090 }
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104 int netlbl_conn_setattr(struct sock *sk,
1105 struct sockaddr *addr,
1106 const struct netlbl_lsm_secattr *secattr)
1107 {
1108 int ret_val;
1109 struct sockaddr_in *addr4;
1110 #if IS_ENABLED(CONFIG_IPV6)
1111 struct sockaddr_in6 *addr6;
1112 #endif
1113 struct netlbl_dommap_def *entry;
1114
1115 rcu_read_lock();
1116 switch (addr->sa_family) {
1117 case AF_INET:
1118 addr4 = (struct sockaddr_in *)addr;
1119 entry = netlbl_domhsh_getentry_af4(secattr->domain,
1120 addr4->sin_addr.s_addr);
1121 if (entry == NULL) {
1122 ret_val = -ENOENT;
1123 goto conn_setattr_return;
1124 }
1125 switch (entry->type) {
1126 case NETLBL_NLTYPE_CIPSOV4:
1127 ret_val = cipso_v4_sock_setattr(sk,
1128 entry->cipso, secattr);
1129 break;
1130 case NETLBL_NLTYPE_UNLABELED:
1131
1132
1133 netlbl_sock_delattr(sk);
1134 ret_val = 0;
1135 break;
1136 default:
1137 ret_val = -ENOENT;
1138 }
1139 break;
1140 #if IS_ENABLED(CONFIG_IPV6)
1141 case AF_INET6:
1142 addr6 = (struct sockaddr_in6 *)addr;
1143 entry = netlbl_domhsh_getentry_af6(secattr->domain,
1144 &addr6->sin6_addr);
1145 if (entry == NULL) {
1146 ret_val = -ENOENT;
1147 goto conn_setattr_return;
1148 }
1149 switch (entry->type) {
1150 case NETLBL_NLTYPE_CALIPSO:
1151 ret_val = calipso_sock_setattr(sk,
1152 entry->calipso, secattr);
1153 break;
1154 case NETLBL_NLTYPE_UNLABELED:
1155
1156
1157 netlbl_sock_delattr(sk);
1158 ret_val = 0;
1159 break;
1160 default:
1161 ret_val = -ENOENT;
1162 }
1163 break;
1164 #endif
1165 default:
1166 ret_val = -EPROTONOSUPPORT;
1167 }
1168
1169 conn_setattr_return:
1170 rcu_read_unlock();
1171 return ret_val;
1172 }
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184 int netlbl_req_setattr(struct request_sock *req,
1185 const struct netlbl_lsm_secattr *secattr)
1186 {
1187 int ret_val;
1188 struct netlbl_dommap_def *entry;
1189 struct inet_request_sock *ireq = inet_rsk(req);
1190
1191 rcu_read_lock();
1192 switch (req->rsk_ops->family) {
1193 case AF_INET:
1194 entry = netlbl_domhsh_getentry_af4(secattr->domain,
1195 ireq->ir_rmt_addr);
1196 if (entry == NULL) {
1197 ret_val = -ENOENT;
1198 goto req_setattr_return;
1199 }
1200 switch (entry->type) {
1201 case NETLBL_NLTYPE_CIPSOV4:
1202 ret_val = cipso_v4_req_setattr(req,
1203 entry->cipso, secattr);
1204 break;
1205 case NETLBL_NLTYPE_UNLABELED:
1206 netlbl_req_delattr(req);
1207 ret_val = 0;
1208 break;
1209 default:
1210 ret_val = -ENOENT;
1211 }
1212 break;
1213 #if IS_ENABLED(CONFIG_IPV6)
1214 case AF_INET6:
1215 entry = netlbl_domhsh_getentry_af6(secattr->domain,
1216 &ireq->ir_v6_rmt_addr);
1217 if (entry == NULL) {
1218 ret_val = -ENOENT;
1219 goto req_setattr_return;
1220 }
1221 switch (entry->type) {
1222 case NETLBL_NLTYPE_CALIPSO:
1223 ret_val = calipso_req_setattr(req,
1224 entry->calipso, secattr);
1225 break;
1226 case NETLBL_NLTYPE_UNLABELED:
1227 netlbl_req_delattr(req);
1228 ret_val = 0;
1229 break;
1230 default:
1231 ret_val = -ENOENT;
1232 }
1233 break;
1234 #endif
1235 default:
1236 ret_val = -EPROTONOSUPPORT;
1237 }
1238
1239 req_setattr_return:
1240 rcu_read_unlock();
1241 return ret_val;
1242 }
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252 void netlbl_req_delattr(struct request_sock *req)
1253 {
1254 switch (req->rsk_ops->family) {
1255 case AF_INET:
1256 cipso_v4_req_delattr(req);
1257 break;
1258 #if IS_ENABLED(CONFIG_IPV6)
1259 case AF_INET6:
1260 calipso_req_delattr(req);
1261 break;
1262 #endif
1263 }
1264 }
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277 int netlbl_skbuff_setattr(struct sk_buff *skb,
1278 u16 family,
1279 const struct netlbl_lsm_secattr *secattr)
1280 {
1281 int ret_val;
1282 struct iphdr *hdr4;
1283 #if IS_ENABLED(CONFIG_IPV6)
1284 struct ipv6hdr *hdr6;
1285 #endif
1286 struct netlbl_dommap_def *entry;
1287
1288 rcu_read_lock();
1289 switch (family) {
1290 case AF_INET:
1291 hdr4 = ip_hdr(skb);
1292 entry = netlbl_domhsh_getentry_af4(secattr->domain,
1293 hdr4->daddr);
1294 if (entry == NULL) {
1295 ret_val = -ENOENT;
1296 goto skbuff_setattr_return;
1297 }
1298 switch (entry->type) {
1299 case NETLBL_NLTYPE_CIPSOV4:
1300 ret_val = cipso_v4_skbuff_setattr(skb, entry->cipso,
1301 secattr);
1302 break;
1303 case NETLBL_NLTYPE_UNLABELED:
1304
1305
1306 ret_val = cipso_v4_skbuff_delattr(skb);
1307 break;
1308 default:
1309 ret_val = -ENOENT;
1310 }
1311 break;
1312 #if IS_ENABLED(CONFIG_IPV6)
1313 case AF_INET6:
1314 hdr6 = ipv6_hdr(skb);
1315 entry = netlbl_domhsh_getentry_af6(secattr->domain,
1316 &hdr6->daddr);
1317 if (entry == NULL) {
1318 ret_val = -ENOENT;
1319 goto skbuff_setattr_return;
1320 }
1321 switch (entry->type) {
1322 case NETLBL_NLTYPE_CALIPSO:
1323 ret_val = calipso_skbuff_setattr(skb, entry->calipso,
1324 secattr);
1325 break;
1326 case NETLBL_NLTYPE_UNLABELED:
1327
1328
1329 ret_val = calipso_skbuff_delattr(skb);
1330 break;
1331 default:
1332 ret_val = -ENOENT;
1333 }
1334 break;
1335 #endif
1336 default:
1337 ret_val = -EPROTONOSUPPORT;
1338 }
1339
1340 skbuff_setattr_return:
1341 rcu_read_unlock();
1342 return ret_val;
1343 }
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358 int netlbl_skbuff_getattr(const struct sk_buff *skb,
1359 u16 family,
1360 struct netlbl_lsm_secattr *secattr)
1361 {
1362 unsigned char *ptr;
1363
1364 switch (family) {
1365 case AF_INET:
1366 ptr = cipso_v4_optptr(skb);
1367 if (ptr && cipso_v4_getattr(ptr, secattr) == 0)
1368 return 0;
1369 break;
1370 #if IS_ENABLED(CONFIG_IPV6)
1371 case AF_INET6:
1372 ptr = calipso_optptr(skb);
1373 if (ptr && calipso_getattr(ptr, secattr) == 0)
1374 return 0;
1375 break;
1376 #endif
1377 }
1378
1379 return netlbl_unlabel_getattr(skb, family, secattr);
1380 }
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395 void netlbl_skbuff_err(struct sk_buff *skb, u16 family, int error, int gateway)
1396 {
1397 switch (family) {
1398 case AF_INET:
1399 if (cipso_v4_optptr(skb))
1400 cipso_v4_error(skb, error, gateway);
1401 break;
1402 }
1403 }
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414 void netlbl_cache_invalidate(void)
1415 {
1416 cipso_v4_cache_invalidate();
1417 #if IS_ENABLED(CONFIG_IPV6)
1418 calipso_cache_invalidate();
1419 #endif
1420 }
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434 int netlbl_cache_add(const struct sk_buff *skb, u16 family,
1435 const struct netlbl_lsm_secattr *secattr)
1436 {
1437 unsigned char *ptr;
1438
1439 if ((secattr->flags & NETLBL_SECATTR_CACHE) == 0)
1440 return -ENOMSG;
1441
1442 switch (family) {
1443 case AF_INET:
1444 ptr = cipso_v4_optptr(skb);
1445 if (ptr)
1446 return cipso_v4_cache_add(ptr, secattr);
1447 break;
1448 #if IS_ENABLED(CONFIG_IPV6)
1449 case AF_INET6:
1450 ptr = calipso_optptr(skb);
1451 if (ptr)
1452 return calipso_cache_add(ptr, secattr);
1453 break;
1454 #endif
1455 }
1456 return -ENOMSG;
1457 }
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475 struct audit_buffer *netlbl_audit_start(int type,
1476 struct netlbl_audit *audit_info)
1477 {
1478 return netlbl_audit_start_common(type, audit_info);
1479 }
1480 EXPORT_SYMBOL(netlbl_audit_start);
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493 static int __init netlbl_init(void)
1494 {
1495 int ret_val;
1496
1497 printk(KERN_INFO "NetLabel: Initializing\n");
1498 printk(KERN_INFO "NetLabel: domain hash size = %u\n",
1499 (1 << NETLBL_DOMHSH_BITSIZE));
1500 printk(KERN_INFO "NetLabel: protocols = UNLABELED CIPSOv4 CALIPSO\n");
1501
1502 ret_val = netlbl_domhsh_init(NETLBL_DOMHSH_BITSIZE);
1503 if (ret_val != 0)
1504 goto init_failure;
1505
1506 ret_val = netlbl_unlabel_init(NETLBL_UNLHSH_BITSIZE);
1507 if (ret_val != 0)
1508 goto init_failure;
1509
1510 ret_val = netlbl_netlink_init();
1511 if (ret_val != 0)
1512 goto init_failure;
1513
1514 ret_val = netlbl_unlabel_defconf();
1515 if (ret_val != 0)
1516 goto init_failure;
1517 printk(KERN_INFO "NetLabel: unlabeled traffic allowed by default\n");
1518
1519 return 0;
1520
1521 init_failure:
1522 panic("NetLabel: failed to initialize properly (%d)\n", ret_val);
1523 }
1524
1525 subsys_initcall(netlbl_init);