0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021 #include <linux/types.h>
0022 #include <linux/rcupdate.h>
0023 #include <linux/list.h>
0024 #include <linux/slab.h>
0025 #include <linux/spinlock.h>
0026 #include <linux/in.h>
0027 #include <linux/in6.h>
0028 #include <linux/ip.h>
0029 #include <linux/ipv6.h>
0030 #include <net/ip.h>
0031 #include <net/ipv6.h>
0032
0033 #include "netnode.h"
0034 #include "objsec.h"
0035
0036 #define SEL_NETNODE_HASH_SIZE 256
0037 #define SEL_NETNODE_HASH_BKT_LIMIT 16
0038
0039 struct sel_netnode_bkt {
0040 unsigned int size;
0041 struct list_head list;
0042 };
0043
0044 struct sel_netnode {
0045 struct netnode_security_struct nsec;
0046
0047 struct list_head list;
0048 struct rcu_head rcu;
0049 };
0050
0051
0052
0053
0054
0055
0056
0057 static DEFINE_SPINLOCK(sel_netnode_lock);
0058 static struct sel_netnode_bkt sel_netnode_hash[SEL_NETNODE_HASH_SIZE];
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069 static unsigned int sel_netnode_hashfn_ipv4(__be32 addr)
0070 {
0071
0072
0073 return (addr & (SEL_NETNODE_HASH_SIZE - 1));
0074 }
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085 static unsigned int sel_netnode_hashfn_ipv6(const struct in6_addr *addr)
0086 {
0087
0088
0089
0090 return (addr->s6_addr32[3] & (SEL_NETNODE_HASH_SIZE - 1));
0091 }
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103 static struct sel_netnode *sel_netnode_find(const void *addr, u16 family)
0104 {
0105 unsigned int idx;
0106 struct sel_netnode *node;
0107
0108 switch (family) {
0109 case PF_INET:
0110 idx = sel_netnode_hashfn_ipv4(*(const __be32 *)addr);
0111 break;
0112 case PF_INET6:
0113 idx = sel_netnode_hashfn_ipv6(addr);
0114 break;
0115 default:
0116 BUG();
0117 return NULL;
0118 }
0119
0120 list_for_each_entry_rcu(node, &sel_netnode_hash[idx].list, list)
0121 if (node->nsec.family == family)
0122 switch (family) {
0123 case PF_INET:
0124 if (node->nsec.addr.ipv4 == *(const __be32 *)addr)
0125 return node;
0126 break;
0127 case PF_INET6:
0128 if (ipv6_addr_equal(&node->nsec.addr.ipv6,
0129 addr))
0130 return node;
0131 break;
0132 }
0133
0134 return NULL;
0135 }
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145 static void sel_netnode_insert(struct sel_netnode *node)
0146 {
0147 unsigned int idx;
0148
0149 switch (node->nsec.family) {
0150 case PF_INET:
0151 idx = sel_netnode_hashfn_ipv4(node->nsec.addr.ipv4);
0152 break;
0153 case PF_INET6:
0154 idx = sel_netnode_hashfn_ipv6(&node->nsec.addr.ipv6);
0155 break;
0156 default:
0157 BUG();
0158 return;
0159 }
0160
0161
0162
0163 list_add_rcu(&node->list, &sel_netnode_hash[idx].list);
0164 if (sel_netnode_hash[idx].size == SEL_NETNODE_HASH_BKT_LIMIT) {
0165 struct sel_netnode *tail;
0166 tail = list_entry(
0167 rcu_dereference_protected(
0168 list_tail_rcu(&sel_netnode_hash[idx].list),
0169 lockdep_is_held(&sel_netnode_lock)),
0170 struct sel_netnode, list);
0171 list_del_rcu(&tail->list);
0172 kfree_rcu(tail, rcu);
0173 } else
0174 sel_netnode_hash[idx].size++;
0175 }
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190 static int sel_netnode_sid_slow(void *addr, u16 family, u32 *sid)
0191 {
0192 int ret;
0193 struct sel_netnode *node;
0194 struct sel_netnode *new;
0195
0196 spin_lock_bh(&sel_netnode_lock);
0197 node = sel_netnode_find(addr, family);
0198 if (node != NULL) {
0199 *sid = node->nsec.sid;
0200 spin_unlock_bh(&sel_netnode_lock);
0201 return 0;
0202 }
0203
0204 new = kzalloc(sizeof(*new), GFP_ATOMIC);
0205 switch (family) {
0206 case PF_INET:
0207 ret = security_node_sid(&selinux_state, PF_INET,
0208 addr, sizeof(struct in_addr), sid);
0209 if (new)
0210 new->nsec.addr.ipv4 = *(__be32 *)addr;
0211 break;
0212 case PF_INET6:
0213 ret = security_node_sid(&selinux_state, PF_INET6,
0214 addr, sizeof(struct in6_addr), sid);
0215 if (new)
0216 new->nsec.addr.ipv6 = *(struct in6_addr *)addr;
0217 break;
0218 default:
0219 BUG();
0220 ret = -EINVAL;
0221 }
0222 if (ret == 0 && new) {
0223 new->nsec.family = family;
0224 new->nsec.sid = *sid;
0225 sel_netnode_insert(new);
0226 } else
0227 kfree(new);
0228
0229 spin_unlock_bh(&sel_netnode_lock);
0230 if (unlikely(ret))
0231 pr_warn("SELinux: failure in %s(), unable to determine network node label\n",
0232 __func__);
0233 return ret;
0234 }
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250 int sel_netnode_sid(void *addr, u16 family, u32 *sid)
0251 {
0252 struct sel_netnode *node;
0253
0254 rcu_read_lock();
0255 node = sel_netnode_find(addr, family);
0256 if (node != NULL) {
0257 *sid = node->nsec.sid;
0258 rcu_read_unlock();
0259 return 0;
0260 }
0261 rcu_read_unlock();
0262
0263 return sel_netnode_sid_slow(addr, family, sid);
0264 }
0265
0266
0267
0268
0269
0270
0271
0272
0273 void sel_netnode_flush(void)
0274 {
0275 unsigned int idx;
0276 struct sel_netnode *node, *node_tmp;
0277
0278 spin_lock_bh(&sel_netnode_lock);
0279 for (idx = 0; idx < SEL_NETNODE_HASH_SIZE; idx++) {
0280 list_for_each_entry_safe(node, node_tmp,
0281 &sel_netnode_hash[idx].list, list) {
0282 list_del_rcu(&node->list);
0283 kfree_rcu(node, rcu);
0284 }
0285 sel_netnode_hash[idx].size = 0;
0286 }
0287 spin_unlock_bh(&sel_netnode_lock);
0288 }
0289
0290 static __init int sel_netnode_init(void)
0291 {
0292 int iter;
0293
0294 if (!selinux_enabled_boot)
0295 return 0;
0296
0297 for (iter = 0; iter < SEL_NETNODE_HASH_SIZE; iter++) {
0298 INIT_LIST_HEAD(&sel_netnode_hash[iter].list);
0299 sel_netnode_hash[iter].size = 0;
0300 }
0301
0302 return 0;
0303 }
0304
0305 __initcall(sel_netnode_init);