netnode.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. /*
  2. * Network node table
  3. *
  4. * SELinux must keep a mapping of network nodes to labels/SIDs. This
  5. * mapping is maintained as part of the normal policy but a fast cache is
  6. * needed to reduce the lookup overhead since most of these queries happen on
  7. * a per-packet basis.
  8. *
  9. * Author: Paul Moore <paul.moore@hp.com>
  10. *
  11. * This code is heavily based on the "netif" concept originally developed by
  12. * James Morris <jmorris@redhat.com>
  13. * (see security/selinux/netif.c for more information)
  14. *
  15. */
  16. /*
  17. * (c) Copyright Hewlett-Packard Development Company, L.P., 2007
  18. *
  19. * This program is free software: you can redistribute it and/or modify
  20. * it under the terms of version 2 of the GNU General Public License as
  21. * published by the Free Software Foundation.
  22. *
  23. * This program is distributed in the hope that it will be useful,
  24. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  25. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  26. * GNU General Public License for more details.
  27. *
  28. */
  29. #include <linux/types.h>
  30. #include <linux/rcupdate.h>
  31. #include <linux/list.h>
  32. #include <linux/spinlock.h>
  33. #include <linux/in.h>
  34. #include <linux/in6.h>
  35. #include <linux/ip.h>
  36. #include <linux/ipv6.h>
  37. #include <net/ip.h>
  38. #include <net/ipv6.h>
  39. #include <asm/bug.h>
  40. #include "objsec.h"
  41. #define SEL_NETNODE_HASH_SIZE 256
  42. #define SEL_NETNODE_HASH_BKT_LIMIT 16
  43. struct sel_netnode {
  44. struct netnode_security_struct nsec;
  45. struct list_head list;
  46. struct rcu_head rcu;
  47. };
  48. /* NOTE: we are using a combined hash table for both IPv4 and IPv6, the reason
  49. * for this is that I suspect most users will not make heavy use of both
  50. * address families at the same time so one table will usually end up wasted,
  51. * if this becomes a problem we can always add a hash table for each address
  52. * family later */
  53. static LIST_HEAD(sel_netnode_list);
  54. static DEFINE_SPINLOCK(sel_netnode_lock);
  55. static struct list_head sel_netnode_hash[SEL_NETNODE_HASH_SIZE];
  56. /**
  57. * sel_netnode_free - Frees a node entry
  58. * @p: the entry's RCU field
  59. *
  60. * Description:
  61. * This function is designed to be used as a callback to the call_rcu()
  62. * function so that memory allocated to a hash table node entry can be
  63. * released safely.
  64. *
  65. */
  66. static void sel_netnode_free(struct rcu_head *p)
  67. {
  68. struct sel_netnode *node = container_of(p, struct sel_netnode, rcu);
  69. kfree(node);
  70. }
  71. /**
  72. * sel_netnode_hashfn_ipv4 - IPv4 hashing function for the node table
  73. * @addr: IPv4 address
  74. *
  75. * Description:
  76. * This is the IPv4 hashing function for the node interface table, it returns
  77. * the bucket number for the given IP address.
  78. *
  79. */
  80. static u32 sel_netnode_hashfn_ipv4(__be32 addr)
  81. {
  82. /* at some point we should determine if the mismatch in byte order
  83. * affects the hash function dramatically */
  84. return (addr & (SEL_NETNODE_HASH_SIZE - 1));
  85. }
  86. /**
  87. * sel_netnode_hashfn_ipv6 - IPv6 hashing function for the node table
  88. * @addr: IPv6 address
  89. *
  90. * Description:
  91. * This is the IPv6 hashing function for the node interface table, it returns
  92. * the bucket number for the given IP address.
  93. *
  94. */
  95. static u32 sel_netnode_hashfn_ipv6(const struct in6_addr *addr)
  96. {
  97. /* just hash the least significant 32 bits to keep things fast (they
  98. * are the most likely to be different anyway), we can revisit this
  99. * later if needed */
  100. return (addr->s6_addr32[3] & (SEL_NETNODE_HASH_SIZE - 1));
  101. }
  102. /**
  103. * sel_netnode_find - Search for a node record
  104. * @addr: IP address
  105. * @family: address family
  106. *
  107. * Description:
  108. * Search the network node table and return the record matching @addr. If an
  109. * entry can not be found in the table return NULL.
  110. *
  111. */
  112. static struct sel_netnode *sel_netnode_find(const void *addr, u16 family)
  113. {
  114. u32 idx;
  115. struct sel_netnode *node;
  116. switch (family) {
  117. case PF_INET:
  118. idx = sel_netnode_hashfn_ipv4(*(__be32 *)addr);
  119. break;
  120. case PF_INET6:
  121. idx = sel_netnode_hashfn_ipv6(addr);
  122. break;
  123. default:
  124. BUG();
  125. }
  126. list_for_each_entry_rcu(node, &sel_netnode_hash[idx], list)
  127. if (node->nsec.family == family)
  128. switch (family) {
  129. case PF_INET:
  130. if (node->nsec.addr.ipv4 == *(__be32 *)addr)
  131. return node;
  132. break;
  133. case PF_INET6:
  134. if (ipv6_addr_equal(&node->nsec.addr.ipv6,
  135. addr))
  136. return node;
  137. break;
  138. }
  139. return NULL;
  140. }
  141. /**
  142. * sel_netnode_insert - Insert a new node into the table
  143. * @node: the new node record
  144. *
  145. * Description:
  146. * Add a new node record to the network address hash table. Returns zero on
  147. * success, negative values on failure.
  148. *
  149. */
  150. static int sel_netnode_insert(struct sel_netnode *node)
  151. {
  152. u32 idx;
  153. u32 count = 0;
  154. struct sel_netnode *iter;
  155. switch (node->nsec.family) {
  156. case PF_INET:
  157. idx = sel_netnode_hashfn_ipv4(node->nsec.addr.ipv4);
  158. break;
  159. case PF_INET6:
  160. idx = sel_netnode_hashfn_ipv6(&node->nsec.addr.ipv6);
  161. break;
  162. default:
  163. BUG();
  164. }
  165. list_add_rcu(&node->list, &sel_netnode_hash[idx]);
  166. /* we need to impose a limit on the growth of the hash table so check
  167. * this bucket to make sure it is within the specified bounds */
  168. list_for_each_entry(iter, &sel_netnode_hash[idx], list)
  169. if (++count > SEL_NETNODE_HASH_BKT_LIMIT) {
  170. list_del_rcu(&iter->list);
  171. call_rcu(&iter->rcu, sel_netnode_free);
  172. break;
  173. }
  174. return 0;
  175. }
  176. /**
  177. * sel_netnode_destroy - Remove a node record from the table
  178. * @node: the existing node record
  179. *
  180. * Description:
  181. * Remove an existing node record from the network address table.
  182. *
  183. */
  184. static void sel_netnode_destroy(struct sel_netnode *node)
  185. {
  186. list_del_rcu(&node->list);
  187. call_rcu(&node->rcu, sel_netnode_free);
  188. }
  189. /**
  190. * sel_netnode_sid_slow - Lookup the SID of a network address using the policy
  191. * @addr: the IP address
  192. * @family: the address family
  193. * @sid: node SID
  194. *
  195. * Description:
  196. * This function determines the SID of a network address by quering the
  197. * security policy. The result is added to the network address table to
  198. * speedup future queries. Returns zero on success, negative values on
  199. * failure.
  200. *
  201. */
  202. static int sel_netnode_sid_slow(void *addr, u16 family, u32 *sid)
  203. {
  204. int ret;
  205. struct sel_netnode *node;
  206. struct sel_netnode *new = NULL;
  207. spin_lock_bh(&sel_netnode_lock);
  208. node = sel_netnode_find(addr, family);
  209. if (node != NULL) {
  210. *sid = node->nsec.sid;
  211. ret = 0;
  212. goto out;
  213. }
  214. new = kzalloc(sizeof(*new), GFP_ATOMIC);
  215. if (new == NULL) {
  216. ret = -ENOMEM;
  217. goto out;
  218. }
  219. switch (family) {
  220. case PF_INET:
  221. ret = security_node_sid(PF_INET,
  222. addr, sizeof(struct in_addr),
  223. &new->nsec.sid);
  224. new->nsec.addr.ipv4 = *(__be32 *)addr;
  225. break;
  226. case PF_INET6:
  227. ret = security_node_sid(PF_INET6,
  228. addr, sizeof(struct in6_addr),
  229. &new->nsec.sid);
  230. ipv6_addr_copy(&new->nsec.addr.ipv6, addr);
  231. break;
  232. default:
  233. BUG();
  234. }
  235. if (ret != 0)
  236. goto out;
  237. new->nsec.family = family;
  238. ret = sel_netnode_insert(new);
  239. if (ret != 0)
  240. goto out;
  241. *sid = new->nsec.sid;
  242. out:
  243. spin_unlock_bh(&sel_netnode_lock);
  244. if (unlikely(ret)) {
  245. printk(KERN_WARNING
  246. "SELinux: failure in sel_netnode_sid_slow(),"
  247. " unable to determine network node label\n");
  248. kfree(new);
  249. }
  250. return ret;
  251. }
  252. /**
  253. * sel_netnode_sid - Lookup the SID of a network address
  254. * @addr: the IP address
  255. * @family: the address family
  256. * @sid: node SID
  257. *
  258. * Description:
  259. * This function determines the SID of a network address using the fastest
  260. * method possible. First the address table is queried, but if an entry
  261. * can't be found then the policy is queried and the result is added to the
  262. * table to speedup future queries. Returns zero on success, negative values
  263. * on failure.
  264. *
  265. */
  266. int sel_netnode_sid(void *addr, u16 family, u32 *sid)
  267. {
  268. struct sel_netnode *node;
  269. rcu_read_lock();
  270. node = sel_netnode_find(addr, family);
  271. if (node != NULL) {
  272. *sid = node->nsec.sid;
  273. rcu_read_unlock();
  274. return 0;
  275. }
  276. rcu_read_unlock();
  277. return sel_netnode_sid_slow(addr, family, sid);
  278. }
  279. /**
  280. * sel_netnode_flush - Flush the entire network address table
  281. *
  282. * Description:
  283. * Remove all entries from the network address table.
  284. *
  285. */
  286. static void sel_netnode_flush(void)
  287. {
  288. u32 idx;
  289. struct sel_netnode *node;
  290. spin_lock_bh(&sel_netnode_lock);
  291. for (idx = 0; idx < SEL_NETNODE_HASH_SIZE; idx++)
  292. list_for_each_entry(node, &sel_netnode_hash[idx], list)
  293. sel_netnode_destroy(node);
  294. spin_unlock_bh(&sel_netnode_lock);
  295. }
  296. static int sel_netnode_avc_callback(u32 event, u32 ssid, u32 tsid,
  297. u16 class, u32 perms, u32 *retained)
  298. {
  299. if (event == AVC_CALLBACK_RESET) {
  300. sel_netnode_flush();
  301. synchronize_net();
  302. }
  303. return 0;
  304. }
  305. static __init int sel_netnode_init(void)
  306. {
  307. int iter;
  308. int ret;
  309. if (!selinux_enabled)
  310. return 0;
  311. for (iter = 0; iter < SEL_NETNODE_HASH_SIZE; iter++)
  312. INIT_LIST_HEAD(&sel_netnode_hash[iter]);
  313. ret = avc_add_callback(sel_netnode_avc_callback, AVC_CALLBACK_RESET,
  314. SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0);
  315. if (ret != 0)
  316. panic("avc_add_callback() failed, error %d\n", ret);
  317. return ret;
  318. }
  319. __initcall(sel_netnode_init);