40 #include <linux/types.h>
42 #include <linux/list.h>
44 #include <linux/string.h>
46 #include <linux/audit.h>
47 #include <linux/slab.h>
55 #include <asm/unaligned.h>
68 #define CIPSO_V4_CACHE_BUCKETBITS 7
69 #define CIPSO_V4_CACHE_BUCKETS (1 << CIPSO_V4_CACHE_BUCKETBITS)
70 #define CIPSO_V4_CACHE_REORDERLIMIT 10
98 #define CIPSO_V4_OPT_LEN_MAX 40
102 #define CIPSO_V4_HDR_LEN 6
105 #define CIPSO_V4_TAG_RBM_BLEN 4
108 #define CIPSO_V4_TAG_ENUM_BLEN 4
111 #define CIPSO_V4_TAG_RNG_BLEN 4
117 #define CIPSO_V4_TAG_RNG_CAT_MAX 8
130 #define CIPSO_V4_TAG_LOC_BLEN 6
148 static int cipso_v4_bitmap_walk(
const unsigned char *
bitmap,
159 byte_offset = offset / 8;
162 bitmask = 0x80 >> (offset % 8);
164 while (bit_spot < bitmap_len) {
165 if ((state && (byte & bitmask) == bitmask) ||
166 (state == 0 && (byte &
bitmask) == 0))
190 static void cipso_v4_bitmap_setbit(
unsigned char *
bitmap,
199 bitmask = 0x80 >> (bit % 8);
203 bitmap[byte_spot] &= ~bitmask;
218 netlbl_secattr_cache_free(entry->
lsm_data);
234 return jhash(key, key_len, 0);
250 static int cipso_v4_cache_init(
void)
257 if (cipso_v4_cache ==
NULL)
262 cipso_v4_cache[iter].
size = 0;
263 INIT_LIST_HEAD(&cipso_v4_cache[iter].
list);
283 spin_lock_bh(&cipso_v4_cache[iter].
lock);
286 &cipso_v4_cache[iter].
list, list) {
288 cipso_v4_cache_entry_free(entry);
290 cipso_v4_cache[iter].
size = 0;
291 spin_unlock_bh(&cipso_v4_cache[iter].lock);
317 static int cipso_v4_cache_check(
const unsigned char *
key,
329 hash = cipso_v4_map_cache_hash(key, key_len);
331 spin_lock_bh(&cipso_v4_cache[bkt].lock);
333 if (entry->
hash == hash &&
341 if (prev_entry ==
NULL) {
342 spin_unlock_bh(&cipso_v4_cache[bkt].lock);
351 __list_del(entry->
list.prev, entry->
list.next);
353 prev_entry->
list.prev,
357 spin_unlock_bh(&cipso_v4_cache[bkt].lock);
362 spin_unlock_bh(&cipso_v4_cache[bkt].lock);
383 int ret_val = -
EPERM;
387 unsigned char *cipso_ptr;
394 cipso_ptr_len = cipso_ptr[1];
402 goto cache_add_failure;
404 entry->
key_len = cipso_ptr_len;
405 entry->
hash = cipso_v4_map_cache_hash(cipso_ptr, cipso_ptr_len);
410 spin_lock_bh(&cipso_v4_cache[bkt].
lock);
412 list_add(&entry->
list, &cipso_v4_cache[bkt].
list);
413 cipso_v4_cache[bkt].
size += 1;
415 old_entry =
list_entry(cipso_v4_cache[bkt].list.prev,
418 list_add(&entry->
list, &cipso_v4_cache[bkt].
list);
419 cipso_v4_cache_entry_free(old_entry);
421 spin_unlock_bh(&cipso_v4_cache[bkt].lock);
427 cipso_v4_cache_entry_free(entry);
448 list_for_each_entry_rcu(iter, &cipso_v4_doi_list, list)
477 doi_type = doi_def->type;
482 switch (doi_def->tags[iter]) {
505 spin_lock(&cipso_v4_doi_list_lock);
506 if (cipso_v4_doi_search(doi_def->doi) != NULL) {
507 spin_unlock(&cipso_v4_doi_list_lock);
511 list_add_tail_rcu(&doi_def->list, &cipso_v4_doi_list);
512 spin_unlock(&cipso_v4_doi_list_lock);
517 if (audit_buf != NULL) {
518 const char *type_str;
530 type_str =
"(unknown)";
533 " cipso_doi=%u cipso_type=%s res=%u",
534 doi, type_str, ret_val == 0 ? 1 : 0);
554 switch (doi_def->
type) {
575 static void cipso_v4_doi_free_rcu(
struct rcu_head *entry)
600 spin_lock(&cipso_v4_doi_list_lock);
601 doi_def = cipso_v4_doi_search(doi);
602 if (doi_def ==
NULL) {
603 spin_unlock(&cipso_v4_doi_list_lock);
605 goto doi_remove_return;
608 spin_unlock(&cipso_v4_doi_list_lock);
610 goto doi_remove_return;
612 list_del_rcu(&doi_def->
list);
613 spin_unlock(&cipso_v4_doi_list_lock);
621 if (audit_buf !=
NULL) {
623 " cipso_doi=%u res=%u",
624 doi, ret_val == 0 ? 1 : 0);
647 doi_def = cipso_v4_doi_search(doi);
649 goto doi_getdef_return;
673 spin_lock(&cipso_v4_doi_list_lock);
674 list_del_rcu(&doi_def->
list);
675 spin_unlock(&cipso_v4_doi_list_lock);
703 list_for_each_entry_rcu(iter_doi, &cipso_v4_doi_list, list)
705 if (doi_cnt++ < *skip_cnt)
707 ret_val =
callback(iter_doi, cb_arg);
710 goto doi_walk_return;
737 switch (doi_def->
type) {
761 static int cipso_v4_map_lvl_hton(
const struct cipso_v4_doi *doi_def,
765 switch (doi_def->
type) {
770 if (host_lvl < doi_def->
map.std->lvl.local_size &&
772 *net_lvl = doi_def->
map.
std->lvl.local[host_lvl];
793 static int cipso_v4_map_lvl_ntoh(
const struct cipso_v4_doi *doi_def,
799 switch (doi_def->
type) {
804 map_tbl = doi_def->
map.
std;
805 if (net_lvl < map_tbl->
lvl.cipso_size &&
807 *host_lvl = doi_def->
map.
std->lvl.cipso[net_lvl];
828 static int cipso_v4_map_cat_rbm_valid(
const struct cipso_v4_doi *doi_def,
829 const unsigned char *bitmap,
833 u32 bitmap_len_bits = bitmap_len * 8;
837 switch (doi_def->
type) {
841 cipso_cat_size = doi_def->
map.
std->cat.cipso_size;
842 cipso_array = doi_def->
map.
std->cat.cipso;
844 cat = cipso_v4_bitmap_walk(bitmap,
850 if (cat >= cipso_cat_size ||
876 static int cipso_v4_map_cat_rbm_hton(
const struct cipso_v4_doi *doi_def,
878 unsigned char *net_cat,
883 u32 net_spot_max = 0;
884 u32 net_clen_bits = net_cat_len * 8;
885 u32 host_cat_size = 0;
889 host_cat_size = doi_def->
map.
std->cat.local_size;
890 host_cat_array = doi_def->
map.
std->cat.local;
899 switch (doi_def->
type) {
901 net_spot = host_spot;
904 if (host_spot >= host_cat_size)
906 net_spot = host_cat_array[host_spot];
911 if (net_spot >= net_clen_bits)
913 cipso_v4_bitmap_setbit(net_cat, net_spot, 1);
915 if (net_spot > net_spot_max)
916 net_spot_max = net_spot;
919 if (++net_spot_max % 8)
920 return net_spot_max / 8 + 1;
921 return net_spot_max / 8;
937 static int cipso_v4_map_cat_rbm_ntoh(
const struct cipso_v4_doi *doi_def,
938 const unsigned char *net_cat,
945 u32 net_clen_bits = net_cat_len * 8;
946 u32 net_cat_size = 0;
950 net_cat_size = doi_def->
map.
std->cat.cipso_size;
951 net_cat_array = doi_def->
map.
std->cat.cipso;
955 net_spot = cipso_v4_bitmap_walk(net_cat,
965 switch (doi_def->
type) {
967 host_spot = net_spot;
970 if (net_spot >= net_cat_size)
972 host_spot = net_cat_array[net_spot];
999 static int cipso_v4_map_cat_enum_valid(
const struct cipso_v4_doi *doi_def,
1000 const unsigned char *enumcat,
1010 for (iter = 0; iter < enumcat_len; iter += 2) {
1011 cat = get_unaligned_be16(&enumcat[iter]);
1012 if (cat <= cat_prev)
1034 static int cipso_v4_map_cat_enum_hton(
const struct cipso_v4_doi *doi_def,
1036 unsigned char *net_cat,
1047 if ((cat_iter + 2) > net_cat_len)
1070 static int cipso_v4_map_cat_enum_ntoh(
const struct cipso_v4_doi *doi_def,
1071 const unsigned char *net_cat,
1078 for (iter = 0; iter < net_cat_len; iter += 2) {
1080 get_unaligned_be16(&net_cat[iter]),
1101 static int cipso_v4_map_cat_rng_valid(
const struct cipso_v4_doi *doi_def,
1102 const unsigned char *rngcat,
1113 for (iter = 0; iter < rngcat_len; iter += 4) {
1114 cat_high = get_unaligned_be16(&rngcat[iter]);
1115 if ((iter + 4) <= rngcat_len)
1116 cat_low = get_unaligned_be16(&rngcat[iter + 2]);
1120 if (cat_high > cat_prev)
1143 static int cipso_v4_map_cat_rng_hton(
const struct cipso_v4_doi *doi_def,
1145 unsigned char *net_cat,
1163 cat_size += (iter == 0 ? 0 :
sizeof(
u16));
1164 if (cat_size > net_cat_len)
1166 array[array_cnt++] = iter;
1172 cat_size +=
sizeof(
u16);
1173 if (cat_size > net_cat_len)
1175 array[array_cnt++] = iter;
1178 for (iter = 0; array_cnt > 0;) {
1179 *((
__be16 *)&net_cat[iter]) =
htons(array[--array_cnt]);
1182 if (array[array_cnt] != 0) {
1183 *((
__be16 *)&net_cat[iter]) =
htons(array[array_cnt]);
1204 static int cipso_v4_map_cat_rng_ntoh(
const struct cipso_v4_doi *doi_def,
1205 const unsigned char *net_cat,
1214 for (net_iter = 0; net_iter < net_cat_len; net_iter += 4) {
1215 cat_high = get_unaligned_be16(&net_cat[net_iter]);
1216 if ((net_iter + 4) <= net_cat_len)
1217 cat_low = get_unaligned_be16(&net_cat[net_iter + 2]);
1246 static void cipso_v4_gentag_hdr(
const struct cipso_v4_doi *doi_def,
1269 static int cipso_v4_gentag_rbm(
const struct cipso_v4_doi *doi_def,
1281 ret_val = cipso_v4_map_lvl_hton(doi_def,
1282 secattr->
attr.mls.lvl,
1288 ret_val = cipso_v4_map_cat_rbm_hton(doi_def,
1301 tag_len = 4 + ret_val;
1324 static int cipso_v4_parsetag_rbm(
const struct cipso_v4_doi *doi_def,
1325 const unsigned char *
tag,
1329 u8 tag_len = tag[1];
1332 ret_val = cipso_v4_map_lvl_ntoh(doi_def, tag[3], &level);
1339 secattr->
attr.mls.cat =
1344 ret_val = cipso_v4_map_cat_rbm_ntoh(doi_def,
1349 netlbl_secattr_catmap_free(secattr->
attr.mls.cat);
1371 static int cipso_v4_gentag_enum(
const struct cipso_v4_doi *doi_def,
1373 unsigned char *buffer,
1383 ret_val = cipso_v4_map_lvl_hton(doi_def,
1384 secattr->
attr.mls.lvl,
1390 ret_val = cipso_v4_map_cat_enum_hton(doi_def,
1397 tag_len = 4 + ret_val;
1420 static int cipso_v4_parsetag_enum(
const struct cipso_v4_doi *doi_def,
1421 const unsigned char *tag,
1425 u8 tag_len = tag[1];
1428 ret_val = cipso_v4_map_lvl_ntoh(doi_def, tag[3], &level);
1435 secattr->
attr.mls.cat =
1440 ret_val = cipso_v4_map_cat_enum_ntoh(doi_def,
1445 netlbl_secattr_catmap_free(secattr->
attr.mls.cat);
1467 static int cipso_v4_gentag_rng(
const struct cipso_v4_doi *doi_def,
1469 unsigned char *buffer,
1479 ret_val = cipso_v4_map_lvl_hton(doi_def,
1480 secattr->
attr.mls.lvl,
1486 ret_val = cipso_v4_map_cat_rng_hton(doi_def,
1493 tag_len = 4 + ret_val;
1515 static int cipso_v4_parsetag_rng(
const struct cipso_v4_doi *doi_def,
1516 const unsigned char *tag,
1520 u8 tag_len = tag[1];
1523 ret_val = cipso_v4_map_lvl_ntoh(doi_def, tag[3], &level);
1530 secattr->
attr.mls.cat =
1535 ret_val = cipso_v4_map_cat_rng_ntoh(doi_def,
1540 netlbl_secattr_catmap_free(secattr->
attr.mls.cat);
1562 static int cipso_v4_gentag_loc(
const struct cipso_v4_doi *doi_def,
1564 unsigned char *buffer,
1572 *(
u32 *)&buffer[2] = secattr->
attr.secid;
1588 static int cipso_v4_parsetag_loc(
const struct cipso_v4_doi *doi_def,
1589 const unsigned char *tag,
1592 secattr->
attr.secid = *(
u32 *)&tag[2];
1621 unsigned char opt_iter;
1622 unsigned char err_offset = 0;
1632 goto validate_return;
1637 if (doi_def ==
NULL) {
1639 goto validate_return_locked;
1643 tag = opt + opt_iter;
1644 while (opt_iter < opt_len) {
1645 for (tag_iter = 0; doi_def->
tags[tag_iter] != tag[0];)
1648 err_offset = opt_iter;
1649 goto validate_return_locked;
1653 if (tag_len > (opt_len - opt_iter)) {
1654 err_offset = opt_iter + 1;
1655 goto validate_return_locked;
1661 err_offset = opt_iter + 1;
1662 goto validate_return_locked;
1673 if (cipso_v4_map_lvl_valid(doi_def,
1675 err_offset = opt_iter + 3;
1676 goto validate_return_locked;
1679 cipso_v4_map_cat_rbm_valid(doi_def,
1682 err_offset = opt_iter + 4;
1683 goto validate_return_locked;
1689 err_offset = opt_iter + 1;
1690 goto validate_return_locked;
1693 if (cipso_v4_map_lvl_valid(doi_def,
1695 err_offset = opt_iter + 3;
1696 goto validate_return_locked;
1699 cipso_v4_map_cat_enum_valid(doi_def,
1702 err_offset = opt_iter + 4;
1703 goto validate_return_locked;
1708 err_offset = opt_iter + 1;
1709 goto validate_return_locked;
1712 if (cipso_v4_map_lvl_valid(doi_def,
1714 err_offset = opt_iter + 3;
1715 goto validate_return_locked;
1718 cipso_v4_map_cat_rng_valid(doi_def,
1721 err_offset = opt_iter + 4;
1722 goto validate_return_locked;
1732 err_offset = opt_iter;
1733 goto validate_return_locked;
1736 err_offset = opt_iter + 1;
1737 goto validate_return_locked;
1741 err_offset = opt_iter;
1742 goto validate_return_locked;
1749 validate_return_locked:
1752 *option = opt + err_offset;
1807 static int cipso_v4_genopt(
unsigned char *buf,
u32 buf_len,
1823 switch (doi_def->
tags[iter]) {
1825 ret_val = cipso_v4_gentag_rbm(doi_def,
1828 buf_len - CIPSO_V4_HDR_LEN);
1831 ret_val = cipso_v4_gentag_enum(doi_def,
1834 buf_len - CIPSO_V4_HDR_LEN);
1837 ret_val = cipso_v4_gentag_rng(doi_def,
1840 buf_len - CIPSO_V4_HDR_LEN);
1843 ret_val = cipso_v4_gentag_loc(doi_def,
1846 buf_len - CIPSO_V4_HDR_LEN);
1853 }
while (ret_val < 0 &&
1858 cipso_v4_gentag_hdr(doi_def, buf, ret_val);
1880 int ret_val = -
EPERM;
1881 unsigned char *buf =
NULL;
1902 goto socket_setattr_failure;
1905 ret_val = cipso_v4_genopt(buf, buf_len, doi_def, secattr);
1907 goto socket_setattr_failure;
1914 opt_len = (buf_len + 3) & ~3;
1915 opt = kzalloc(
sizeof(*opt) + opt_len,
GFP_ATOMIC);
1918 goto socket_setattr_failure;
1921 opt->
opt.optlen = opt_len;
1922 opt->
opt.cipso =
sizeof(
struct iphdr);
1926 sk_inet = inet_sk(sk);
1930 sk_conn = inet_csk(sk);
1942 socket_setattr_failure:
1964 int ret_val = -
EPERM;
1965 unsigned char *buf =
NULL;
1978 goto req_setattr_failure;
1981 ret_val = cipso_v4_genopt(buf, buf_len, doi_def, secattr);
1983 goto req_setattr_failure;
1990 opt_len = (buf_len + 3) & ~3;
1991 opt = kzalloc(
sizeof(*opt) + opt_len,
GFP_ATOMIC);
1994 goto req_setattr_failure;
1997 opt->
opt.optlen = opt_len;
1998 opt->
opt.cipso =
sizeof(
struct iphdr);
2002 req_inet = inet_rsk(req);
2003 opt =
xchg(&req_inet->
opt, opt);
2009 req_setattr_failure:
2030 if (opt->
opt.srr || opt->
opt.rr || opt->
opt.ts || opt->
opt.router_alert) {
2033 unsigned char *cipso_ptr;
2037 cipso_off = opt->
opt.cipso -
sizeof(
struct iphdr);
2038 cipso_ptr = &opt->
opt.__data[cipso_off];
2039 cipso_len = cipso_ptr[1];
2041 if (opt->
opt.srr > opt->
opt.cipso)
2042 opt->
opt.srr -= cipso_len;
2043 if (opt->
opt.rr > opt->
opt.cipso)
2044 opt->
opt.rr -= cipso_len;
2045 if (opt->
opt.ts > opt->
opt.cipso)
2046 opt->
opt.ts -= cipso_len;
2047 if (opt->
opt.router_alert > opt->
opt.cipso)
2048 opt->
opt.router_alert -= cipso_len;
2051 memmove(cipso_ptr, cipso_ptr + cipso_len,
2052 opt->
opt.optlen - cipso_off - cipso_len);
2061 while (iter < opt->opt.optlen)
2063 iter += opt->
opt.__data[iter + 1];
2067 hdr_delta = opt->
opt.optlen;
2068 opt->
opt.optlen = (optlen_new + 3) & ~3;
2069 hdr_delta -= opt->
opt.optlen;
2074 hdr_delta = opt->
opt.optlen;
2095 sk_inet = inet_sk(sk);
2097 if (opt ==
NULL || opt->
opt.cipso == 0)
2100 hdr_delta = cipso_v4_delopt(&sk_inet->
inet_opt);
2101 if (sk_inet->
is_icsk && hdr_delta > 0) {
2121 req_inet = inet_rsk(req);
2122 opt = req_inet->
opt;
2123 if (opt ==
NULL || opt->
opt.cipso == 0)
2126 cipso_v4_delopt(&req_inet->
opt);
2139 static int cipso_v4_getattr(
const unsigned char *cipso,
2146 if (cipso_v4_cache_check(cipso, cipso[1], secattr) == 0)
2151 doi_def = cipso_v4_doi_search(doi);
2152 if (doi_def ==
NULL)
2153 goto getattr_return;
2159 ret_val = cipso_v4_parsetag_rbm(doi_def, &cipso[6], secattr);
2162 ret_val = cipso_v4_parsetag_enum(doi_def, &cipso[6], secattr);
2165 ret_val = cipso_v4_parsetag_rng(doi_def, &cipso[6], secattr);
2168 ret_val = cipso_v4_parsetag_loc(doi_def, &cipso[6], secattr);
2198 if (opt && opt->
opt.cipso)
2199 res = cipso_v4_getattr(opt->
opt.__data +
2201 sizeof(
struct iphdr),
2229 ret_val = cipso_v4_genopt(buf, buf_len, doi_def, secattr);
2233 opt_len = (buf_len + 3) & ~3;
2241 len_delta = opt_len - opt->
optlen;
2245 ret_val = skb_cow(skb, skb_headroom(skb) + len_delta);
2249 if (len_delta > 0) {
2254 memmove((
char *)iph - len_delta, iph, iph->ihl << 2);
2255 skb_reset_network_header(skb);
2257 }
else if (len_delta < 0) {
2264 memset(opt, 0,
sizeof(*opt));
2274 memcpy(iph + 1, buf, buf_len);
2275 if (opt_len > buf_len)
2276 memset((
char *)(iph + 1) + buf_len, 0, opt_len - buf_len);
2277 if (len_delta != 0) {
2278 iph->ihl = 5 + (opt_len >> 2);
2300 unsigned char *cipso_ptr;
2302 if (opt->
cipso == 0)
2306 ret_val = skb_cow(skb, skb_headroom(skb));
2315 cipso_ptr = (
unsigned char *)iph + opt->
cipso;
2353 static int __init cipso_v4_init(
void)
2357 ret_val = cipso_v4_cache_init();
2359 panic(
"Failed to initialize the CIPSO/IPv4 cache (%d)\n",