31 #include <linux/types.h>
33 #include <linux/list.h>
35 #include <linux/socket.h>
36 #include <linux/string.h>
38 #include <linux/audit.h>
40 #include <linux/in6.h>
42 #include <linux/ipv6.h>
44 #include <linux/netdevice.h>
46 #include <linux/slab.h>
81 #define netlbl_unlhsh_addr4_entry(iter) \
82 container_of(iter, struct netlbl_unlhsh_addr4, list)
89 #define netlbl_unlhsh_addr6_entry(iter) \
90 container_of(iter, struct netlbl_unlhsh_addr6, list)
118 #define netlbl_unlhsh_rcu_deref(p) \
119 rcu_dereference_check(p, lockdep_is_held(&netlbl_unlhsh_lock))
124 static u8 netlabel_unlabel_acceptflg = 0;
127 static struct genl_family netlbl_unlabel_gnl_family = {
143 .len =
sizeof(
struct in_addr) },
145 .len =
sizeof(
struct in_addr) },
173 #if IS_ENABLED(CONFIG_IPV6)
187 #if IS_ENABLED(CONFIG_IPV6)
188 netlbl_af6list_foreach_safe(iter6, tmp6, &iface->
addr6_list) {
189 netlbl_af6list_remove_entry(iter6);
207 static u32 netlbl_unlhsh_hash(
int ifindex)
229 bkt = netlbl_unlhsh_hash(ifindex);
231 list_for_each_entry_rcu(iter, bkt_list,
list)
232 if (iter->
valid && iter->ifindex == ifindex)
263 entry->
list.addr = addr->s_addr & mask->s_addr;
264 entry->
list.mask = mask->s_addr;
265 entry->
list.valid = 1;
268 spin_lock(&netlbl_unlhsh_lock);
270 spin_unlock(&netlbl_unlhsh_lock);
277 #if IS_ENABLED(CONFIG_IPV6)
304 entry->
list.addr.s6_addr32[0] &= mask->s6_addr32[0];
305 entry->
list.addr.s6_addr32[1] &= mask->s6_addr32[1];
306 entry->
list.addr.s6_addr32[2] &= mask->s6_addr32[2];
307 entry->
list.addr.s6_addr32[3] &= mask->s6_addr32[3];
309 entry->
list.valid = 1;
312 spin_lock(&netlbl_unlhsh_lock);
314 spin_unlock(&netlbl_unlhsh_lock);
346 spin_lock(&netlbl_unlhsh_lock);
348 bkt = netlbl_unlhsh_hash(ifindex);
349 if (netlbl_unlhsh_search_iface(ifindex) != NULL)
350 goto add_iface_failure;
351 list_add_tail_rcu(&iface->
list,
354 INIT_LIST_HEAD(&iface->
list);
356 goto add_iface_failure;
359 spin_unlock(&netlbl_unlhsh_lock);
364 spin_unlock(&netlbl_unlhsh_lock);
385 const char *dev_name,
400 if (addr_len !=
sizeof(
struct in_addr) &&
401 addr_len !=
sizeof(
struct in6_addr))
405 if (dev_name != NULL) {
409 goto unlhsh_add_return;
412 iface = netlbl_unlhsh_search_iface(ifindex);
418 iface = netlbl_unlhsh_add_iface(ifindex);
421 goto unlhsh_add_return;
431 ret_val = netlbl_unlhsh_add_addr4(iface,
addr4, mask4, secid);
432 if (audit_buf != NULL)
433 netlbl_af4list_audit_addr(audit_buf, 1,
439 #if IS_ENABLED(CONFIG_IPV6)
444 ret_val = netlbl_unlhsh_add_addr6(iface, addr6, mask6, secid);
445 if (audit_buf != NULL)
446 netlbl_af6list_audit_addr(audit_buf, 1,
460 if (audit_buf != NULL) {
486 static int netlbl_unlhsh_remove_addr4(
struct net *
net,
499 spin_lock(&netlbl_unlhsh_lock);
502 spin_unlock(&netlbl_unlhsh_lock);
503 if (list_entry != NULL)
510 if (audit_buf != NULL) {
512 netlbl_af4list_audit_addr(audit_buf, 1,
513 (dev != NULL ? dev->
name : NULL),
519 &secctx, &secctx_len) == 0) {
534 #if IS_ENABLED(CONFIG_IPV6)
548 static int netlbl_unlhsh_remove_addr6(
struct net *net,
561 spin_lock(&netlbl_unlhsh_lock);
562 list_entry = netlbl_af6list_remove(addr, mask, &iface->
addr6_list);
563 spin_unlock(&netlbl_unlhsh_lock);
564 if (list_entry != NULL)
571 if (audit_buf != NULL) {
573 netlbl_af6list_audit_addr(audit_buf, 1,
574 (dev != NULL ? dev->
name : NULL),
580 &secctx, &secctx_len) == 0) {
609 #if IS_ENABLED(CONFIG_IPV6)
613 spin_lock(&netlbl_unlhsh_lock);
615 goto unlhsh_condremove_failure;
616 #if IS_ENABLED(CONFIG_IPV6)
617 netlbl_af6list_foreach_rcu(iter6, &iface->
addr6_list)
618 goto unlhsh_condremove_failure;
622 list_del_rcu(&iface->
list);
625 spin_unlock(&netlbl_unlhsh_lock);
630 unlhsh_condremove_failure:
631 spin_unlock(&netlbl_unlhsh_lock);
649 const char *dev_name,
659 if (addr_len !=
sizeof(
struct in_addr) &&
660 addr_len !=
sizeof(
struct in6_addr))
664 if (dev_name != NULL) {
668 goto unlhsh_remove_return;
670 iface = netlbl_unlhsh_search_iface(dev->
ifindex);
675 goto unlhsh_remove_return;
679 ret_val = netlbl_unlhsh_remove_addr4(net,
683 #if IS_ENABLED(CONFIG_IPV6)
684 case
sizeof(struct in6_addr):
685 ret_val = netlbl_unlhsh_remove_addr6(net,
694 netlbl_unlhsh_condremove_iface(iface);
698 unlhsh_remove_return:
719 static int netlbl_unlhsh_netdev_handler(
struct notifier_block *
this,
726 if (!net_eq(dev_net(dev), &
init_net))
731 spin_lock(&netlbl_unlhsh_lock);
732 iface = netlbl_unlhsh_search_iface(dev->
ifindex);
733 if (iface != NULL && iface->
valid) {
735 list_del_rcu(&iface->
list);
738 spin_unlock(&netlbl_unlhsh_lock);
756 static void netlbl_unlabel_acceptflg_set(
u8 value,
762 old_val = netlabel_unlabel_acceptflg;
763 netlabel_unlabel_acceptflg =
value;
766 if (audit_buf != NULL) {
768 " unlbl_accept=%u old=%u", value, old_val);
785 static int netlbl_unlabel_addrinfo_get(
struct genl_info *
info,
794 if (addr_len !=
sizeof(
struct in_addr) &&
803 if (addr_len !=
sizeof(
struct in6_addr) &&
836 if (value == 1 || value == 0) {
837 netlbl_netlink_auditinfo(skb, &audit_info);
838 netlbl_unlabel_acceptflg_set(value, &audit_info);
865 data = genlmsg_put_reply(ans_skb, info, &netlbl_unlabel_gnl_family,
872 ret_val = nla_put_u8(ans_skb,
874 netlabel_unlabel_acceptflg);
878 genlmsg_end(ans_skb, data);
879 return genlmsg_reply(ans_skb, info);
897 static int netlbl_unlabel_staticadd(
struct sk_buff *skb,
920 netlbl_netlink_auditinfo(skb, &audit_info);
922 ret_val = netlbl_unlabel_addrinfo_get(info, &addr, &mask, &addr_len);
934 dev_name, addr, mask, addr_len, secid,
949 static int netlbl_unlabel_staticadddef(
struct sk_buff *skb,
970 netlbl_netlink_auditinfo(skb, &audit_info);
972 ret_val = netlbl_unlabel_addrinfo_get(info, &addr, &mask, &addr_len);
983 NULL, addr, mask, addr_len, secid,
998 static int netlbl_unlabel_staticremove(
struct sk_buff *skb,
1017 netlbl_netlink_auditinfo(skb, &audit_info);
1019 ret_val = netlbl_unlabel_addrinfo_get(info, &addr, &mask, &addr_len);
1025 dev_name, addr, mask, addr_len,
1040 static int netlbl_unlabel_staticremovedef(
struct sk_buff *skb,
1057 netlbl_netlink_auditinfo(skb, &audit_info);
1059 ret_val = netlbl_unlabel_addrinfo_get(info, &addr, &mask, &addr_len);
1064 NULL, addr, mask, addr_len,
1085 static int netlbl_unlabel_staticlist_gen(
u32 cmd,
1100 cb_arg->
seq, &netlbl_unlabel_gnl_family,
1103 goto list_cb_failure;
1109 goto list_cb_failure;
1111 ret_val = nla_put_string(cb_arg->
skb,
1115 goto list_cb_failure;
1127 goto list_cb_failure;
1135 goto list_cb_failure;
1137 secid = addr4->
secid;
1144 goto list_cb_failure;
1151 goto list_cb_failure;
1153 secid = addr6->
secid;
1158 goto list_cb_failure;
1165 goto list_cb_failure;
1168 return genlmsg_end(cb_arg->
skb, data);
1171 genlmsg_cancel(cb_arg->
skb, data);
1186 static int netlbl_unlabel_staticlist(
struct sk_buff *skb,
1195 u32 iter_chain = 0, iter_addr4 = 0, iter_addr6 = 0;
1199 #if IS_ENABLED(CONFIG_IPV6)
1205 cb_arg.
seq = cb->
nlh->nlmsg_seq;
1208 for (iter_bkt = skip_bkt;
1210 iter_bkt++, iter_chain = 0, iter_addr4 = 0, iter_addr6 = 0) {
1212 list_for_each_entry_rcu(iface, iter_list,
list) {
1213 if (!iface->
valid ||
1214 iter_chain++ < skip_chain)
1218 if (iter_addr4++ < skip_addr4)
1220 if (netlbl_unlabel_staticlist_gen(
1228 goto unlabel_staticlist_return;
1231 #if IS_ENABLED(CONFIG_IPV6)
1232 netlbl_af6list_foreach_rcu(addr6,
1234 if (iter_addr6++ < skip_addr6)
1236 if (netlbl_unlabel_staticlist_gen(
1244 goto unlabel_staticlist_return;
1251 unlabel_staticlist_return:
1253 cb->
args[0] = skip_bkt;
1254 cb->
args[1] = skip_chain;
1255 cb->
args[2] = skip_addr4;
1256 cb->
args[3] = skip_addr6;
1271 static int netlbl_unlabel_staticlistdef(
struct sk_buff *skb,
1280 #if IS_ENABLED(CONFIG_IPV6)
1287 cb_arg.
seq = cb->
nlh->nlmsg_seq;
1291 if (iface == NULL || !iface->
valid)
1292 goto unlabel_staticlistdef_return;
1295 if (iter_addr4++ < skip_addr4)
1303 goto unlabel_staticlistdef_return;
1306 #if IS_ENABLED(CONFIG_IPV6)
1307 netlbl_af6list_foreach_rcu(addr6, &iface->
addr6_list) {
1308 if (iter_addr6++ < skip_addr6)
1316 goto unlabel_staticlistdef_return;
1321 unlabel_staticlistdef_return:
1323 cb->
args[0] = skip_addr4;
1324 cb->
args[1] = skip_addr6;
1332 static struct genl_ops netlbl_unlabel_genl_ops[] = {
1336 .policy = netlbl_unlabel_genl_policy,
1337 .doit = netlbl_unlabel_staticadd,
1343 .policy = netlbl_unlabel_genl_policy,
1344 .doit = netlbl_unlabel_staticremove,
1350 .policy = netlbl_unlabel_genl_policy,
1352 .dumpit = netlbl_unlabel_staticlist,
1357 .policy = netlbl_unlabel_genl_policy,
1358 .doit = netlbl_unlabel_staticadddef,
1364 .policy = netlbl_unlabel_genl_policy,
1365 .doit = netlbl_unlabel_staticremovedef,
1371 .policy = netlbl_unlabel_genl_policy,
1373 .dumpit = netlbl_unlabel_staticlistdef,
1378 .policy = netlbl_unlabel_genl_policy,
1379 .doit = netlbl_unlabel_accept,
1385 .policy = netlbl_unlabel_genl_policy,
1386 .doit = netlbl_unlabel_list,
1406 netlbl_unlabel_genl_ops,
ARRAY_SIZE(netlbl_unlabel_genl_ops));
1414 .notifier_call = netlbl_unlhsh_netdev_handler,
1437 if (hsh_tbl == NULL)
1440 hsh_tbl->
tbl = kcalloc(hsh_tbl->
size,
1443 if (hsh_tbl->
tbl == NULL) {
1447 for (iter = 0; iter < hsh_tbl->
size; iter++)
1448 INIT_LIST_HEAD(&hsh_tbl->
tbl[iter]);
1450 spin_lock(&netlbl_unlhsh_lock);
1452 spin_unlock(&netlbl_unlhsh_lock);
1477 iface = netlbl_unlhsh_search_iface(skb->
skb_iif);
1480 if (iface == NULL || !iface->
valid)
1481 goto unlabel_getattr_nolabel;
1491 goto unlabel_getattr_nolabel;
1495 #if IS_ENABLED(CONFIG_IPV6)
1500 hdr6 = ipv6_hdr(skb);
1501 addr6 = netlbl_af6list_search(&hdr6->
saddr,
1504 goto unlabel_getattr_nolabel;
1510 goto unlabel_getattr_nolabel;
1518 unlabel_getattr_nolabel:
1520 if (netlabel_unlabel_acceptflg == 0)
1555 netlbl_unlabel_acceptflg_set(1, &audit_info);