netlabel_unlabeled.c 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629
  1. /*
  2. * NetLabel Unlabeled Support
  3. *
  4. * This file defines functions for dealing with unlabeled packets for the
  5. * NetLabel system. The NetLabel system manages static and dynamic label
  6. * mappings for network protocols such as CIPSO and RIPSO.
  7. *
  8. * Author: Paul Moore <paul.moore@hp.com>
  9. *
  10. */
  11. /*
  12. * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 - 2008
  13. *
  14. * This program is free software; you can redistribute it and/or modify
  15. * it under the terms of the GNU General Public License as published by
  16. * the Free Software Foundation; either version 2 of the License, or
  17. * (at your option) any later version.
  18. *
  19. * This program is distributed in the hope that it will be useful,
  20. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
  22. * the GNU General Public License for more details.
  23. *
  24. * You should have received a copy of the GNU General Public License
  25. * along with this program; if not, write to the Free Software
  26. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  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/socket.h>
  34. #include <linux/string.h>
  35. #include <linux/skbuff.h>
  36. #include <linux/audit.h>
  37. #include <linux/in.h>
  38. #include <linux/in6.h>
  39. #include <linux/ip.h>
  40. #include <linux/ipv6.h>
  41. #include <linux/notifier.h>
  42. #include <linux/netdevice.h>
  43. #include <linux/security.h>
  44. #include <net/sock.h>
  45. #include <net/netlink.h>
  46. #include <net/genetlink.h>
  47. #include <net/ip.h>
  48. #include <net/ipv6.h>
  49. #include <net/net_namespace.h>
  50. #include <net/netlabel.h>
  51. #include <asm/bug.h>
  52. #include <asm/atomic.h>
  53. #include "netlabel_user.h"
  54. #include "netlabel_addrlist.h"
  55. #include "netlabel_domainhash.h"
  56. #include "netlabel_unlabeled.h"
  57. #include "netlabel_mgmt.h"
  58. /* NOTE: at present we always use init's network namespace since we don't
  59. * presently support different namespaces even though the majority of
  60. * the functions in this file are "namespace safe" */
  61. /* The unlabeled connection hash table which we use to map network interfaces
  62. * and addresses of unlabeled packets to a user specified secid value for the
  63. * LSM. The hash table is used to lookup the network interface entry
  64. * (struct netlbl_unlhsh_iface) and then the interface entry is used to
  65. * lookup an IP address match from an ordered list. If a network interface
  66. * match can not be found in the hash table then the default entry
  67. * (netlbl_unlhsh_def) is used. The IP address entry list
  68. * (struct netlbl_unlhsh_addr) is ordered such that the entries with a
  69. * larger netmask come first.
  70. */
  71. struct netlbl_unlhsh_tbl {
  72. struct list_head *tbl;
  73. u32 size;
  74. };
  75. #define netlbl_unlhsh_addr4_entry(iter) \
  76. container_of(iter, struct netlbl_unlhsh_addr4, list)
  77. struct netlbl_unlhsh_addr4 {
  78. u32 secid;
  79. struct netlbl_af4list list;
  80. struct rcu_head rcu;
  81. };
  82. #define netlbl_unlhsh_addr6_entry(iter) \
  83. container_of(iter, struct netlbl_unlhsh_addr6, list)
  84. struct netlbl_unlhsh_addr6 {
  85. u32 secid;
  86. struct netlbl_af6list list;
  87. struct rcu_head rcu;
  88. };
  89. struct netlbl_unlhsh_iface {
  90. int ifindex;
  91. struct list_head addr4_list;
  92. struct list_head addr6_list;
  93. u32 valid;
  94. struct list_head list;
  95. struct rcu_head rcu;
  96. };
  97. /* Argument struct for netlbl_unlhsh_walk() */
  98. struct netlbl_unlhsh_walk_arg {
  99. struct netlink_callback *nl_cb;
  100. struct sk_buff *skb;
  101. u32 seq;
  102. };
  103. /* Unlabeled connection hash table */
  104. /* updates should be so rare that having one spinlock for the entire
  105. * hash table should be okay */
  106. static DEFINE_SPINLOCK(netlbl_unlhsh_lock);
  107. static struct netlbl_unlhsh_tbl *netlbl_unlhsh = NULL;
  108. static struct netlbl_unlhsh_iface *netlbl_unlhsh_def = NULL;
  109. /* Accept unlabeled packets flag */
  110. static u8 netlabel_unlabel_acceptflg = 0;
  111. /* NetLabel Generic NETLINK unlabeled family */
  112. static struct genl_family netlbl_unlabel_gnl_family = {
  113. .id = GENL_ID_GENERATE,
  114. .hdrsize = 0,
  115. .name = NETLBL_NLTYPE_UNLABELED_NAME,
  116. .version = NETLBL_PROTO_VERSION,
  117. .maxattr = NLBL_UNLABEL_A_MAX,
  118. };
  119. /* NetLabel Netlink attribute policy */
  120. static const struct nla_policy netlbl_unlabel_genl_policy[NLBL_UNLABEL_A_MAX + 1] = {
  121. [NLBL_UNLABEL_A_ACPTFLG] = { .type = NLA_U8 },
  122. [NLBL_UNLABEL_A_IPV6ADDR] = { .type = NLA_BINARY,
  123. .len = sizeof(struct in6_addr) },
  124. [NLBL_UNLABEL_A_IPV6MASK] = { .type = NLA_BINARY,
  125. .len = sizeof(struct in6_addr) },
  126. [NLBL_UNLABEL_A_IPV4ADDR] = { .type = NLA_BINARY,
  127. .len = sizeof(struct in_addr) },
  128. [NLBL_UNLABEL_A_IPV4MASK] = { .type = NLA_BINARY,
  129. .len = sizeof(struct in_addr) },
  130. [NLBL_UNLABEL_A_IFACE] = { .type = NLA_NUL_STRING,
  131. .len = IFNAMSIZ - 1 },
  132. [NLBL_UNLABEL_A_SECCTX] = { .type = NLA_BINARY }
  133. };
  134. /*
  135. * Unlabeled Connection Hash Table Functions
  136. */
  137. /**
  138. * netlbl_unlhsh_free_addr4 - Frees an IPv4 address entry from the hash table
  139. * @entry: the entry's RCU field
  140. *
  141. * Description:
  142. * This function is designed to be used as a callback to the call_rcu()
  143. * function so that memory allocated to a hash table address entry can be
  144. * released safely.
  145. *
  146. */
  147. static void netlbl_unlhsh_free_addr4(struct rcu_head *entry)
  148. {
  149. struct netlbl_unlhsh_addr4 *ptr;
  150. ptr = container_of(entry, struct netlbl_unlhsh_addr4, rcu);
  151. kfree(ptr);
  152. }
  153. #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
  154. /**
  155. * netlbl_unlhsh_free_addr6 - Frees an IPv6 address entry from the hash table
  156. * @entry: the entry's RCU field
  157. *
  158. * Description:
  159. * This function is designed to be used as a callback to the call_rcu()
  160. * function so that memory allocated to a hash table address entry can be
  161. * released safely.
  162. *
  163. */
  164. static void netlbl_unlhsh_free_addr6(struct rcu_head *entry)
  165. {
  166. struct netlbl_unlhsh_addr6 *ptr;
  167. ptr = container_of(entry, struct netlbl_unlhsh_addr6, rcu);
  168. kfree(ptr);
  169. }
  170. #endif /* IPv6 */
  171. /**
  172. * netlbl_unlhsh_free_iface - Frees an interface entry from the hash table
  173. * @entry: the entry's RCU field
  174. *
  175. * Description:
  176. * This function is designed to be used as a callback to the call_rcu()
  177. * function so that memory allocated to a hash table interface entry can be
  178. * released safely. It is important to note that this function does not free
  179. * the IPv4 and IPv6 address lists contained as part of an interface entry. It
  180. * is up to the rest of the code to make sure an interface entry is only freed
  181. * once it's address lists are empty.
  182. *
  183. */
  184. static void netlbl_unlhsh_free_iface(struct rcu_head *entry)
  185. {
  186. struct netlbl_unlhsh_iface *iface;
  187. struct netlbl_af4list *iter4;
  188. struct netlbl_af4list *tmp4;
  189. #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
  190. struct netlbl_af6list *iter6;
  191. struct netlbl_af6list *tmp6;
  192. #endif /* IPv6 */
  193. iface = container_of(entry, struct netlbl_unlhsh_iface, rcu);
  194. /* no need for locks here since we are the only one with access to this
  195. * structure */
  196. netlbl_af4list_foreach_safe(iter4, tmp4, &iface->addr4_list) {
  197. netlbl_af4list_remove_entry(iter4);
  198. kfree(netlbl_unlhsh_addr4_entry(iter4));
  199. }
  200. #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
  201. netlbl_af6list_foreach_safe(iter6, tmp6, &iface->addr6_list) {
  202. netlbl_af6list_remove_entry(iter6);
  203. kfree(netlbl_unlhsh_addr6_entry(iter6));
  204. }
  205. #endif /* IPv6 */
  206. kfree(iface);
  207. }
  208. /**
  209. * netlbl_unlhsh_hash - Hashing function for the hash table
  210. * @ifindex: the network interface/device to hash
  211. *
  212. * Description:
  213. * This is the hashing function for the unlabeled hash table, it returns the
  214. * bucket number for the given device/interface. The caller is responsible for
  215. * calling the rcu_read_[un]lock() functions.
  216. *
  217. */
  218. static u32 netlbl_unlhsh_hash(int ifindex)
  219. {
  220. /* this is taken _almost_ directly from
  221. * security/selinux/netif.c:sel_netif_hasfn() as they do pretty much
  222. * the same thing */
  223. return ifindex & (rcu_dereference(netlbl_unlhsh)->size - 1);
  224. }
  225. /**
  226. * netlbl_unlhsh_search_iface - Search for a matching interface entry
  227. * @ifindex: the network interface
  228. *
  229. * Description:
  230. * Searches the unlabeled connection hash table and returns a pointer to the
  231. * interface entry which matches @ifindex, otherwise NULL is returned. The
  232. * caller is responsible for calling the rcu_read_[un]lock() functions.
  233. *
  234. */
  235. static struct netlbl_unlhsh_iface *netlbl_unlhsh_search_iface(int ifindex)
  236. {
  237. u32 bkt;
  238. struct list_head *bkt_list;
  239. struct netlbl_unlhsh_iface *iter;
  240. bkt = netlbl_unlhsh_hash(ifindex);
  241. bkt_list = &rcu_dereference(netlbl_unlhsh)->tbl[bkt];
  242. list_for_each_entry_rcu(iter, bkt_list, list)
  243. if (iter->valid && iter->ifindex == ifindex)
  244. return iter;
  245. return NULL;
  246. }
  247. /**
  248. * netlbl_unlhsh_search_iface_def - Search for a matching interface entry
  249. * @ifindex: the network interface
  250. *
  251. * Description:
  252. * Searches the unlabeled connection hash table and returns a pointer to the
  253. * interface entry which matches @ifindex. If an exact match can not be found
  254. * and there is a valid default entry, the default entry is returned, otherwise
  255. * NULL is returned. The caller is responsible for calling the
  256. * rcu_read_[un]lock() functions.
  257. *
  258. */
  259. static struct netlbl_unlhsh_iface *netlbl_unlhsh_search_iface_def(int ifindex)
  260. {
  261. struct netlbl_unlhsh_iface *entry;
  262. entry = netlbl_unlhsh_search_iface(ifindex);
  263. if (entry != NULL)
  264. return entry;
  265. entry = rcu_dereference(netlbl_unlhsh_def);
  266. if (entry != NULL && entry->valid)
  267. return entry;
  268. return NULL;
  269. }
  270. /**
  271. * netlbl_unlhsh_add_addr4 - Add a new IPv4 address entry to the hash table
  272. * @iface: the associated interface entry
  273. * @addr: IPv4 address in network byte order
  274. * @mask: IPv4 address mask in network byte order
  275. * @secid: LSM secid value for entry
  276. *
  277. * Description:
  278. * Add a new address entry into the unlabeled connection hash table using the
  279. * interface entry specified by @iface. On success zero is returned, otherwise
  280. * a negative value is returned. The caller is responsible for calling the
  281. * rcu_read_[un]lock() functions.
  282. *
  283. */
  284. static int netlbl_unlhsh_add_addr4(struct netlbl_unlhsh_iface *iface,
  285. const struct in_addr *addr,
  286. const struct in_addr *mask,
  287. u32 secid)
  288. {
  289. int ret_val;
  290. struct netlbl_unlhsh_addr4 *entry;
  291. entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
  292. if (entry == NULL)
  293. return -ENOMEM;
  294. entry->list.addr = addr->s_addr & mask->s_addr;
  295. entry->list.mask = mask->s_addr;
  296. entry->list.valid = 1;
  297. entry->secid = secid;
  298. spin_lock(&netlbl_unlhsh_lock);
  299. ret_val = netlbl_af4list_add(&entry->list, &iface->addr4_list);
  300. spin_unlock(&netlbl_unlhsh_lock);
  301. if (ret_val != 0)
  302. kfree(entry);
  303. return ret_val;
  304. }
  305. #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
  306. /**
  307. * netlbl_unlhsh_add_addr6 - Add a new IPv6 address entry to the hash table
  308. * @iface: the associated interface entry
  309. * @addr: IPv6 address in network byte order
  310. * @mask: IPv6 address mask in network byte order
  311. * @secid: LSM secid value for entry
  312. *
  313. * Description:
  314. * Add a new address entry into the unlabeled connection hash table using the
  315. * interface entry specified by @iface. On success zero is returned, otherwise
  316. * a negative value is returned. The caller is responsible for calling the
  317. * rcu_read_[un]lock() functions.
  318. *
  319. */
  320. static int netlbl_unlhsh_add_addr6(struct netlbl_unlhsh_iface *iface,
  321. const struct in6_addr *addr,
  322. const struct in6_addr *mask,
  323. u32 secid)
  324. {
  325. int ret_val;
  326. struct netlbl_unlhsh_addr6 *entry;
  327. entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
  328. if (entry == NULL)
  329. return -ENOMEM;
  330. ipv6_addr_copy(&entry->list.addr, addr);
  331. entry->list.addr.s6_addr32[0] &= mask->s6_addr32[0];
  332. entry->list.addr.s6_addr32[1] &= mask->s6_addr32[1];
  333. entry->list.addr.s6_addr32[2] &= mask->s6_addr32[2];
  334. entry->list.addr.s6_addr32[3] &= mask->s6_addr32[3];
  335. ipv6_addr_copy(&entry->list.mask, mask);
  336. entry->list.valid = 1;
  337. entry->secid = secid;
  338. spin_lock(&netlbl_unlhsh_lock);
  339. ret_val = netlbl_af6list_add(&entry->list, &iface->addr6_list);
  340. spin_unlock(&netlbl_unlhsh_lock);
  341. if (ret_val != 0)
  342. kfree(entry);
  343. return 0;
  344. }
  345. #endif /* IPv6 */
  346. /**
  347. * netlbl_unlhsh_add_iface - Adds a new interface entry to the hash table
  348. * @ifindex: network interface
  349. *
  350. * Description:
  351. * Add a new, empty, interface entry into the unlabeled connection hash table.
  352. * On success a pointer to the new interface entry is returned, on failure NULL
  353. * is returned. The caller is responsible for calling the rcu_read_[un]lock()
  354. * functions.
  355. *
  356. */
  357. static struct netlbl_unlhsh_iface *netlbl_unlhsh_add_iface(int ifindex)
  358. {
  359. u32 bkt;
  360. struct netlbl_unlhsh_iface *iface;
  361. iface = kzalloc(sizeof(*iface), GFP_ATOMIC);
  362. if (iface == NULL)
  363. return NULL;
  364. iface->ifindex = ifindex;
  365. INIT_LIST_HEAD(&iface->addr4_list);
  366. INIT_LIST_HEAD(&iface->addr6_list);
  367. iface->valid = 1;
  368. spin_lock(&netlbl_unlhsh_lock);
  369. if (ifindex > 0) {
  370. bkt = netlbl_unlhsh_hash(ifindex);
  371. if (netlbl_unlhsh_search_iface(ifindex) != NULL)
  372. goto add_iface_failure;
  373. list_add_tail_rcu(&iface->list,
  374. &rcu_dereference(netlbl_unlhsh)->tbl[bkt]);
  375. } else {
  376. INIT_LIST_HEAD(&iface->list);
  377. if (rcu_dereference(netlbl_unlhsh_def) != NULL)
  378. goto add_iface_failure;
  379. rcu_assign_pointer(netlbl_unlhsh_def, iface);
  380. }
  381. spin_unlock(&netlbl_unlhsh_lock);
  382. return iface;
  383. add_iface_failure:
  384. spin_unlock(&netlbl_unlhsh_lock);
  385. kfree(iface);
  386. return NULL;
  387. }
  388. /**
  389. * netlbl_unlhsh_add - Adds a new entry to the unlabeled connection hash table
  390. * @net: network namespace
  391. * @dev_name: interface name
  392. * @addr: IP address in network byte order
  393. * @mask: address mask in network byte order
  394. * @addr_len: length of address/mask (4 for IPv4, 16 for IPv6)
  395. * @secid: LSM secid value for the entry
  396. * @audit_info: NetLabel audit information
  397. *
  398. * Description:
  399. * Adds a new entry to the unlabeled connection hash table. Returns zero on
  400. * success, negative values on failure.
  401. *
  402. */
  403. int netlbl_unlhsh_add(struct net *net,
  404. const char *dev_name,
  405. const void *addr,
  406. const void *mask,
  407. u32 addr_len,
  408. u32 secid,
  409. struct netlbl_audit *audit_info)
  410. {
  411. int ret_val;
  412. int ifindex;
  413. struct net_device *dev;
  414. struct netlbl_unlhsh_iface *iface;
  415. struct audit_buffer *audit_buf = NULL;
  416. char *secctx = NULL;
  417. u32 secctx_len;
  418. if (addr_len != sizeof(struct in_addr) &&
  419. addr_len != sizeof(struct in6_addr))
  420. return -EINVAL;
  421. rcu_read_lock();
  422. if (dev_name != NULL) {
  423. dev = dev_get_by_name_rcu(net, dev_name);
  424. if (dev == NULL) {
  425. ret_val = -ENODEV;
  426. goto unlhsh_add_return;
  427. }
  428. ifindex = dev->ifindex;
  429. iface = netlbl_unlhsh_search_iface(ifindex);
  430. } else {
  431. ifindex = 0;
  432. iface = rcu_dereference(netlbl_unlhsh_def);
  433. }
  434. if (iface == NULL) {
  435. iface = netlbl_unlhsh_add_iface(ifindex);
  436. if (iface == NULL) {
  437. ret_val = -ENOMEM;
  438. goto unlhsh_add_return;
  439. }
  440. }
  441. audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_STCADD,
  442. audit_info);
  443. switch (addr_len) {
  444. case sizeof(struct in_addr): {
  445. struct in_addr *addr4, *mask4;
  446. addr4 = (struct in_addr *)addr;
  447. mask4 = (struct in_addr *)mask;
  448. ret_val = netlbl_unlhsh_add_addr4(iface, addr4, mask4, secid);
  449. if (audit_buf != NULL)
  450. netlbl_af4list_audit_addr(audit_buf, 1,
  451. dev_name,
  452. addr4->s_addr,
  453. mask4->s_addr);
  454. break;
  455. }
  456. #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
  457. case sizeof(struct in6_addr): {
  458. struct in6_addr *addr6, *mask6;
  459. addr6 = (struct in6_addr *)addr;
  460. mask6 = (struct in6_addr *)mask;
  461. ret_val = netlbl_unlhsh_add_addr6(iface, addr6, mask6, secid);
  462. if (audit_buf != NULL)
  463. netlbl_af6list_audit_addr(audit_buf, 1,
  464. dev_name,
  465. addr6, mask6);
  466. break;
  467. }
  468. #endif /* IPv6 */
  469. default:
  470. ret_val = -EINVAL;
  471. }
  472. if (ret_val == 0)
  473. atomic_inc(&netlabel_mgmt_protocount);
  474. unlhsh_add_return:
  475. rcu_read_unlock();
  476. if (audit_buf != NULL) {
  477. if (security_secid_to_secctx(secid,
  478. &secctx,
  479. &secctx_len) == 0) {
  480. audit_log_format(audit_buf, " sec_obj=%s", secctx);
  481. security_release_secctx(secctx, secctx_len);
  482. }
  483. audit_log_format(audit_buf, " res=%u", ret_val == 0 ? 1 : 0);
  484. audit_log_end(audit_buf);
  485. }
  486. return ret_val;
  487. }
  488. /**
  489. * netlbl_unlhsh_remove_addr4 - Remove an IPv4 address entry
  490. * @net: network namespace
  491. * @iface: interface entry
  492. * @addr: IP address
  493. * @mask: IP address mask
  494. * @audit_info: NetLabel audit information
  495. *
  496. * Description:
  497. * Remove an IP address entry from the unlabeled connection hash table.
  498. * Returns zero on success, negative values on failure. The caller is
  499. * responsible for calling the rcu_read_[un]lock() functions.
  500. *
  501. */
  502. static int netlbl_unlhsh_remove_addr4(struct net *net,
  503. struct netlbl_unlhsh_iface *iface,
  504. const struct in_addr *addr,
  505. const struct in_addr *mask,
  506. struct netlbl_audit *audit_info)
  507. {
  508. struct netlbl_af4list *list_entry;
  509. struct netlbl_unlhsh_addr4 *entry;
  510. struct audit_buffer *audit_buf;
  511. struct net_device *dev;
  512. char *secctx;
  513. u32 secctx_len;
  514. spin_lock(&netlbl_unlhsh_lock);
  515. list_entry = netlbl_af4list_remove(addr->s_addr, mask->s_addr,
  516. &iface->addr4_list);
  517. spin_unlock(&netlbl_unlhsh_lock);
  518. if (list_entry != NULL)
  519. entry = netlbl_unlhsh_addr4_entry(list_entry);
  520. else
  521. entry = NULL;
  522. audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_STCDEL,
  523. audit_info);
  524. if (audit_buf != NULL) {
  525. dev = dev_get_by_index(net, iface->ifindex);
  526. netlbl_af4list_audit_addr(audit_buf, 1,
  527. (dev != NULL ? dev->name : NULL),
  528. addr->s_addr, mask->s_addr);
  529. if (dev != NULL)
  530. dev_put(dev);
  531. if (entry != NULL &&
  532. security_secid_to_secctx(entry->secid,
  533. &secctx, &secctx_len) == 0) {
  534. audit_log_format(audit_buf, " sec_obj=%s", secctx);
  535. security_release_secctx(secctx, secctx_len);
  536. }
  537. audit_log_format(audit_buf, " res=%u", entry != NULL ? 1 : 0);
  538. audit_log_end(audit_buf);
  539. }
  540. if (entry == NULL)
  541. return -ENOENT;
  542. call_rcu(&entry->rcu, netlbl_unlhsh_free_addr4);
  543. return 0;
  544. }
  545. #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
  546. /**
  547. * netlbl_unlhsh_remove_addr6 - Remove an IPv6 address entry
  548. * @net: network namespace
  549. * @iface: interface entry
  550. * @addr: IP address
  551. * @mask: IP address mask
  552. * @audit_info: NetLabel audit information
  553. *
  554. * Description:
  555. * Remove an IP address entry from the unlabeled connection hash table.
  556. * Returns zero on success, negative values on failure. The caller is
  557. * responsible for calling the rcu_read_[un]lock() functions.
  558. *
  559. */
  560. static int netlbl_unlhsh_remove_addr6(struct net *net,
  561. struct netlbl_unlhsh_iface *iface,
  562. const struct in6_addr *addr,
  563. const struct in6_addr *mask,
  564. struct netlbl_audit *audit_info)
  565. {
  566. struct netlbl_af6list *list_entry;
  567. struct netlbl_unlhsh_addr6 *entry;
  568. struct audit_buffer *audit_buf;
  569. struct net_device *dev;
  570. char *secctx;
  571. u32 secctx_len;
  572. spin_lock(&netlbl_unlhsh_lock);
  573. list_entry = netlbl_af6list_remove(addr, mask, &iface->addr6_list);
  574. spin_unlock(&netlbl_unlhsh_lock);
  575. if (list_entry != NULL)
  576. entry = netlbl_unlhsh_addr6_entry(list_entry);
  577. else
  578. entry = NULL;
  579. audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_STCDEL,
  580. audit_info);
  581. if (audit_buf != NULL) {
  582. dev = dev_get_by_index(net, iface->ifindex);
  583. netlbl_af6list_audit_addr(audit_buf, 1,
  584. (dev != NULL ? dev->name : NULL),
  585. addr, mask);
  586. if (dev != NULL)
  587. dev_put(dev);
  588. if (entry != NULL &&
  589. security_secid_to_secctx(entry->secid,
  590. &secctx, &secctx_len) == 0) {
  591. audit_log_format(audit_buf, " sec_obj=%s", secctx);
  592. security_release_secctx(secctx, secctx_len);
  593. }
  594. audit_log_format(audit_buf, " res=%u", entry != NULL ? 1 : 0);
  595. audit_log_end(audit_buf);
  596. }
  597. if (entry == NULL)
  598. return -ENOENT;
  599. call_rcu(&entry->rcu, netlbl_unlhsh_free_addr6);
  600. return 0;
  601. }
  602. #endif /* IPv6 */
  603. /**
  604. * netlbl_unlhsh_condremove_iface - Remove an interface entry
  605. * @iface: the interface entry
  606. *
  607. * Description:
  608. * Remove an interface entry from the unlabeled connection hash table if it is
  609. * empty. An interface entry is considered to be empty if there are no
  610. * address entries assigned to it.
  611. *
  612. */
  613. static void netlbl_unlhsh_condremove_iface(struct netlbl_unlhsh_iface *iface)
  614. {
  615. struct netlbl_af4list *iter4;
  616. #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
  617. struct netlbl_af6list *iter6;
  618. #endif /* IPv6 */
  619. spin_lock(&netlbl_unlhsh_lock);
  620. netlbl_af4list_foreach_rcu(iter4, &iface->addr4_list)
  621. goto unlhsh_condremove_failure;
  622. #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
  623. netlbl_af6list_foreach_rcu(iter6, &iface->addr6_list)
  624. goto unlhsh_condremove_failure;
  625. #endif /* IPv6 */
  626. iface->valid = 0;
  627. if (iface->ifindex > 0)
  628. list_del_rcu(&iface->list);
  629. else
  630. rcu_assign_pointer(netlbl_unlhsh_def, NULL);
  631. spin_unlock(&netlbl_unlhsh_lock);
  632. call_rcu(&iface->rcu, netlbl_unlhsh_free_iface);
  633. return;
  634. unlhsh_condremove_failure:
  635. spin_unlock(&netlbl_unlhsh_lock);
  636. return;
  637. }
  638. /**
  639. * netlbl_unlhsh_remove - Remove an entry from the unlabeled hash table
  640. * @net: network namespace
  641. * @dev_name: interface name
  642. * @addr: IP address in network byte order
  643. * @mask: address mask in network byte order
  644. * @addr_len: length of address/mask (4 for IPv4, 16 for IPv6)
  645. * @audit_info: NetLabel audit information
  646. *
  647. * Description:
  648. * Removes and existing entry from the unlabeled connection hash table.
  649. * Returns zero on success, negative values on failure.
  650. *
  651. */
  652. int netlbl_unlhsh_remove(struct net *net,
  653. const char *dev_name,
  654. const void *addr,
  655. const void *mask,
  656. u32 addr_len,
  657. struct netlbl_audit *audit_info)
  658. {
  659. int ret_val;
  660. struct net_device *dev;
  661. struct netlbl_unlhsh_iface *iface;
  662. if (addr_len != sizeof(struct in_addr) &&
  663. addr_len != sizeof(struct in6_addr))
  664. return -EINVAL;
  665. rcu_read_lock();
  666. if (dev_name != NULL) {
  667. dev = dev_get_by_name_rcu(net, dev_name);
  668. if (dev == NULL) {
  669. ret_val = -ENODEV;
  670. goto unlhsh_remove_return;
  671. }
  672. iface = netlbl_unlhsh_search_iface(dev->ifindex);
  673. } else
  674. iface = rcu_dereference(netlbl_unlhsh_def);
  675. if (iface == NULL) {
  676. ret_val = -ENOENT;
  677. goto unlhsh_remove_return;
  678. }
  679. switch (addr_len) {
  680. case sizeof(struct in_addr):
  681. ret_val = netlbl_unlhsh_remove_addr4(net,
  682. iface, addr, mask,
  683. audit_info);
  684. break;
  685. #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
  686. case sizeof(struct in6_addr):
  687. ret_val = netlbl_unlhsh_remove_addr6(net,
  688. iface, addr, mask,
  689. audit_info);
  690. break;
  691. #endif /* IPv6 */
  692. default:
  693. ret_val = -EINVAL;
  694. }
  695. if (ret_val == 0) {
  696. netlbl_unlhsh_condremove_iface(iface);
  697. atomic_dec(&netlabel_mgmt_protocount);
  698. }
  699. unlhsh_remove_return:
  700. rcu_read_unlock();
  701. return ret_val;
  702. }
  703. /*
  704. * General Helper Functions
  705. */
  706. /**
  707. * netlbl_unlhsh_netdev_handler - Network device notification handler
  708. * @this: notifier block
  709. * @event: the event
  710. * @ptr: the network device (cast to void)
  711. *
  712. * Description:
  713. * Handle network device events, although at present all we care about is a
  714. * network device going away. In the case of a device going away we clear any
  715. * related entries from the unlabeled connection hash table.
  716. *
  717. */
  718. static int netlbl_unlhsh_netdev_handler(struct notifier_block *this,
  719. unsigned long event,
  720. void *ptr)
  721. {
  722. struct net_device *dev = ptr;
  723. struct netlbl_unlhsh_iface *iface = NULL;
  724. if (!net_eq(dev_net(dev), &init_net))
  725. return NOTIFY_DONE;
  726. /* XXX - should this be a check for NETDEV_DOWN or _UNREGISTER? */
  727. if (event == NETDEV_DOWN) {
  728. spin_lock(&netlbl_unlhsh_lock);
  729. iface = netlbl_unlhsh_search_iface(dev->ifindex);
  730. if (iface != NULL && iface->valid) {
  731. iface->valid = 0;
  732. list_del_rcu(&iface->list);
  733. } else
  734. iface = NULL;
  735. spin_unlock(&netlbl_unlhsh_lock);
  736. }
  737. if (iface != NULL)
  738. call_rcu(&iface->rcu, netlbl_unlhsh_free_iface);
  739. return NOTIFY_DONE;
  740. }
  741. /**
  742. * netlbl_unlabel_acceptflg_set - Set the unlabeled accept flag
  743. * @value: desired value
  744. * @audit_info: NetLabel audit information
  745. *
  746. * Description:
  747. * Set the value of the unlabeled accept flag to @value.
  748. *
  749. */
  750. static void netlbl_unlabel_acceptflg_set(u8 value,
  751. struct netlbl_audit *audit_info)
  752. {
  753. struct audit_buffer *audit_buf;
  754. u8 old_val;
  755. old_val = netlabel_unlabel_acceptflg;
  756. netlabel_unlabel_acceptflg = value;
  757. audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_ALLOW,
  758. audit_info);
  759. if (audit_buf != NULL) {
  760. audit_log_format(audit_buf,
  761. " unlbl_accept=%u old=%u", value, old_val);
  762. audit_log_end(audit_buf);
  763. }
  764. }
  765. /**
  766. * netlbl_unlabel_addrinfo_get - Get the IPv4/6 address information
  767. * @info: the Generic NETLINK info block
  768. * @addr: the IP address
  769. * @mask: the IP address mask
  770. * @len: the address length
  771. *
  772. * Description:
  773. * Examine the Generic NETLINK message and extract the IP address information.
  774. * Returns zero on success, negative values on failure.
  775. *
  776. */
  777. static int netlbl_unlabel_addrinfo_get(struct genl_info *info,
  778. void **addr,
  779. void **mask,
  780. u32 *len)
  781. {
  782. u32 addr_len;
  783. if (info->attrs[NLBL_UNLABEL_A_IPV4ADDR]) {
  784. addr_len = nla_len(info->attrs[NLBL_UNLABEL_A_IPV4ADDR]);
  785. if (addr_len != sizeof(struct in_addr) &&
  786. addr_len != nla_len(info->attrs[NLBL_UNLABEL_A_IPV4MASK]))
  787. return -EINVAL;
  788. *len = addr_len;
  789. *addr = nla_data(info->attrs[NLBL_UNLABEL_A_IPV4ADDR]);
  790. *mask = nla_data(info->attrs[NLBL_UNLABEL_A_IPV4MASK]);
  791. return 0;
  792. } else if (info->attrs[NLBL_UNLABEL_A_IPV6ADDR]) {
  793. addr_len = nla_len(info->attrs[NLBL_UNLABEL_A_IPV6ADDR]);
  794. if (addr_len != sizeof(struct in6_addr) &&
  795. addr_len != nla_len(info->attrs[NLBL_UNLABEL_A_IPV6MASK]))
  796. return -EINVAL;
  797. *len = addr_len;
  798. *addr = nla_data(info->attrs[NLBL_UNLABEL_A_IPV6ADDR]);
  799. *mask = nla_data(info->attrs[NLBL_UNLABEL_A_IPV6MASK]);
  800. return 0;
  801. }
  802. return -EINVAL;
  803. }
  804. /*
  805. * NetLabel Command Handlers
  806. */
  807. /**
  808. * netlbl_unlabel_accept - Handle an ACCEPT message
  809. * @skb: the NETLINK buffer
  810. * @info: the Generic NETLINK info block
  811. *
  812. * Description:
  813. * Process a user generated ACCEPT message and set the accept flag accordingly.
  814. * Returns zero on success, negative values on failure.
  815. *
  816. */
  817. static int netlbl_unlabel_accept(struct sk_buff *skb, struct genl_info *info)
  818. {
  819. u8 value;
  820. struct netlbl_audit audit_info;
  821. if (info->attrs[NLBL_UNLABEL_A_ACPTFLG]) {
  822. value = nla_get_u8(info->attrs[NLBL_UNLABEL_A_ACPTFLG]);
  823. if (value == 1 || value == 0) {
  824. netlbl_netlink_auditinfo(skb, &audit_info);
  825. netlbl_unlabel_acceptflg_set(value, &audit_info);
  826. return 0;
  827. }
  828. }
  829. return -EINVAL;
  830. }
  831. /**
  832. * netlbl_unlabel_list - Handle a LIST message
  833. * @skb: the NETLINK buffer
  834. * @info: the Generic NETLINK info block
  835. *
  836. * Description:
  837. * Process a user generated LIST message and respond with the current status.
  838. * Returns zero on success, negative values on failure.
  839. *
  840. */
  841. static int netlbl_unlabel_list(struct sk_buff *skb, struct genl_info *info)
  842. {
  843. int ret_val = -EINVAL;
  844. struct sk_buff *ans_skb;
  845. void *data;
  846. ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
  847. if (ans_skb == NULL)
  848. goto list_failure;
  849. data = genlmsg_put_reply(ans_skb, info, &netlbl_unlabel_gnl_family,
  850. 0, NLBL_UNLABEL_C_LIST);
  851. if (data == NULL) {
  852. ret_val = -ENOMEM;
  853. goto list_failure;
  854. }
  855. ret_val = nla_put_u8(ans_skb,
  856. NLBL_UNLABEL_A_ACPTFLG,
  857. netlabel_unlabel_acceptflg);
  858. if (ret_val != 0)
  859. goto list_failure;
  860. genlmsg_end(ans_skb, data);
  861. return genlmsg_reply(ans_skb, info);
  862. list_failure:
  863. kfree_skb(ans_skb);
  864. return ret_val;
  865. }
  866. /**
  867. * netlbl_unlabel_staticadd - Handle a STATICADD message
  868. * @skb: the NETLINK buffer
  869. * @info: the Generic NETLINK info block
  870. *
  871. * Description:
  872. * Process a user generated STATICADD message and add a new unlabeled
  873. * connection entry to the hash table. Returns zero on success, negative
  874. * values on failure.
  875. *
  876. */
  877. static int netlbl_unlabel_staticadd(struct sk_buff *skb,
  878. struct genl_info *info)
  879. {
  880. int ret_val;
  881. char *dev_name;
  882. void *addr;
  883. void *mask;
  884. u32 addr_len;
  885. u32 secid;
  886. struct netlbl_audit audit_info;
  887. /* Don't allow users to add both IPv4 and IPv6 addresses for a
  888. * single entry. However, allow users to create two entries, one each
  889. * for IPv4 and IPv4, with the same LSM security context which should
  890. * achieve the same result. */
  891. if (!info->attrs[NLBL_UNLABEL_A_SECCTX] ||
  892. !info->attrs[NLBL_UNLABEL_A_IFACE] ||
  893. !((!info->attrs[NLBL_UNLABEL_A_IPV4ADDR] ||
  894. !info->attrs[NLBL_UNLABEL_A_IPV4MASK]) ^
  895. (!info->attrs[NLBL_UNLABEL_A_IPV6ADDR] ||
  896. !info->attrs[NLBL_UNLABEL_A_IPV6MASK])))
  897. return -EINVAL;
  898. netlbl_netlink_auditinfo(skb, &audit_info);
  899. ret_val = netlbl_unlabel_addrinfo_get(info, &addr, &mask, &addr_len);
  900. if (ret_val != 0)
  901. return ret_val;
  902. dev_name = nla_data(info->attrs[NLBL_UNLABEL_A_IFACE]);
  903. ret_val = security_secctx_to_secid(
  904. nla_data(info->attrs[NLBL_UNLABEL_A_SECCTX]),
  905. nla_len(info->attrs[NLBL_UNLABEL_A_SECCTX]),
  906. &secid);
  907. if (ret_val != 0)
  908. return ret_val;
  909. return netlbl_unlhsh_add(&init_net,
  910. dev_name, addr, mask, addr_len, secid,
  911. &audit_info);
  912. }
  913. /**
  914. * netlbl_unlabel_staticadddef - Handle a STATICADDDEF message
  915. * @skb: the NETLINK buffer
  916. * @info: the Generic NETLINK info block
  917. *
  918. * Description:
  919. * Process a user generated STATICADDDEF message and add a new default
  920. * unlabeled connection entry. Returns zero on success, negative values on
  921. * failure.
  922. *
  923. */
  924. static int netlbl_unlabel_staticadddef(struct sk_buff *skb,
  925. struct genl_info *info)
  926. {
  927. int ret_val;
  928. void *addr;
  929. void *mask;
  930. u32 addr_len;
  931. u32 secid;
  932. struct netlbl_audit audit_info;
  933. /* Don't allow users to add both IPv4 and IPv6 addresses for a
  934. * single entry. However, allow users to create two entries, one each
  935. * for IPv4 and IPv6, with the same LSM security context which should
  936. * achieve the same result. */
  937. if (!info->attrs[NLBL_UNLABEL_A_SECCTX] ||
  938. !((!info->attrs[NLBL_UNLABEL_A_IPV4ADDR] ||
  939. !info->attrs[NLBL_UNLABEL_A_IPV4MASK]) ^
  940. (!info->attrs[NLBL_UNLABEL_A_IPV6ADDR] ||
  941. !info->attrs[NLBL_UNLABEL_A_IPV6MASK])))
  942. return -EINVAL;
  943. netlbl_netlink_auditinfo(skb, &audit_info);
  944. ret_val = netlbl_unlabel_addrinfo_get(info, &addr, &mask, &addr_len);
  945. if (ret_val != 0)
  946. return ret_val;
  947. ret_val = security_secctx_to_secid(
  948. nla_data(info->attrs[NLBL_UNLABEL_A_SECCTX]),
  949. nla_len(info->attrs[NLBL_UNLABEL_A_SECCTX]),
  950. &secid);
  951. if (ret_val != 0)
  952. return ret_val;
  953. return netlbl_unlhsh_add(&init_net,
  954. NULL, addr, mask, addr_len, secid,
  955. &audit_info);
  956. }
  957. /**
  958. * netlbl_unlabel_staticremove - Handle a STATICREMOVE message
  959. * @skb: the NETLINK buffer
  960. * @info: the Generic NETLINK info block
  961. *
  962. * Description:
  963. * Process a user generated STATICREMOVE message and remove the specified
  964. * unlabeled connection entry. Returns zero on success, negative values on
  965. * failure.
  966. *
  967. */
  968. static int netlbl_unlabel_staticremove(struct sk_buff *skb,
  969. struct genl_info *info)
  970. {
  971. int ret_val;
  972. char *dev_name;
  973. void *addr;
  974. void *mask;
  975. u32 addr_len;
  976. struct netlbl_audit audit_info;
  977. /* See the note in netlbl_unlabel_staticadd() about not allowing both
  978. * IPv4 and IPv6 in the same entry. */
  979. if (!info->attrs[NLBL_UNLABEL_A_IFACE] ||
  980. !((!info->attrs[NLBL_UNLABEL_A_IPV4ADDR] ||
  981. !info->attrs[NLBL_UNLABEL_A_IPV4MASK]) ^
  982. (!info->attrs[NLBL_UNLABEL_A_IPV6ADDR] ||
  983. !info->attrs[NLBL_UNLABEL_A_IPV6MASK])))
  984. return -EINVAL;
  985. netlbl_netlink_auditinfo(skb, &audit_info);
  986. ret_val = netlbl_unlabel_addrinfo_get(info, &addr, &mask, &addr_len);
  987. if (ret_val != 0)
  988. return ret_val;
  989. dev_name = nla_data(info->attrs[NLBL_UNLABEL_A_IFACE]);
  990. return netlbl_unlhsh_remove(&init_net,
  991. dev_name, addr, mask, addr_len,
  992. &audit_info);
  993. }
  994. /**
  995. * netlbl_unlabel_staticremovedef - Handle a STATICREMOVEDEF message
  996. * @skb: the NETLINK buffer
  997. * @info: the Generic NETLINK info block
  998. *
  999. * Description:
  1000. * Process a user generated STATICREMOVEDEF message and remove the default
  1001. * unlabeled connection entry. Returns zero on success, negative values on
  1002. * failure.
  1003. *
  1004. */
  1005. static int netlbl_unlabel_staticremovedef(struct sk_buff *skb,
  1006. struct genl_info *info)
  1007. {
  1008. int ret_val;
  1009. void *addr;
  1010. void *mask;
  1011. u32 addr_len;
  1012. struct netlbl_audit audit_info;
  1013. /* See the note in netlbl_unlabel_staticadd() about not allowing both
  1014. * IPv4 and IPv6 in the same entry. */
  1015. if (!((!info->attrs[NLBL_UNLABEL_A_IPV4ADDR] ||
  1016. !info->attrs[NLBL_UNLABEL_A_IPV4MASK]) ^
  1017. (!info->attrs[NLBL_UNLABEL_A_IPV6ADDR] ||
  1018. !info->attrs[NLBL_UNLABEL_A_IPV6MASK])))
  1019. return -EINVAL;
  1020. netlbl_netlink_auditinfo(skb, &audit_info);
  1021. ret_val = netlbl_unlabel_addrinfo_get(info, &addr, &mask, &addr_len);
  1022. if (ret_val != 0)
  1023. return ret_val;
  1024. return netlbl_unlhsh_remove(&init_net,
  1025. NULL, addr, mask, addr_len,
  1026. &audit_info);
  1027. }
  1028. /**
  1029. * netlbl_unlabel_staticlist_gen - Generate messages for STATICLIST[DEF]
  1030. * @cmd: command/message
  1031. * @iface: the interface entry
  1032. * @addr4: the IPv4 address entry
  1033. * @addr6: the IPv6 address entry
  1034. * @arg: the netlbl_unlhsh_walk_arg structure
  1035. *
  1036. * Description:
  1037. * This function is designed to be used to generate a response for a
  1038. * STATICLIST or STATICLISTDEF message. When called either @addr4 or @addr6
  1039. * can be specified, not both, the other unspecified entry should be set to
  1040. * NULL by the caller. Returns the size of the message on success, negative
  1041. * values on failure.
  1042. *
  1043. */
  1044. static int netlbl_unlabel_staticlist_gen(u32 cmd,
  1045. const struct netlbl_unlhsh_iface *iface,
  1046. const struct netlbl_unlhsh_addr4 *addr4,
  1047. const struct netlbl_unlhsh_addr6 *addr6,
  1048. void *arg)
  1049. {
  1050. int ret_val = -ENOMEM;
  1051. struct netlbl_unlhsh_walk_arg *cb_arg = arg;
  1052. struct net_device *dev;
  1053. void *data;
  1054. u32 secid;
  1055. char *secctx;
  1056. u32 secctx_len;
  1057. data = genlmsg_put(cb_arg->skb, NETLINK_CB(cb_arg->nl_cb->skb).pid,
  1058. cb_arg->seq, &netlbl_unlabel_gnl_family,
  1059. NLM_F_MULTI, cmd);
  1060. if (data == NULL)
  1061. goto list_cb_failure;
  1062. if (iface->ifindex > 0) {
  1063. dev = dev_get_by_index(&init_net, iface->ifindex);
  1064. if (!dev) {
  1065. ret_val = -ENODEV;
  1066. goto list_cb_failure;
  1067. }
  1068. ret_val = nla_put_string(cb_arg->skb,
  1069. NLBL_UNLABEL_A_IFACE, dev->name);
  1070. dev_put(dev);
  1071. if (ret_val != 0)
  1072. goto list_cb_failure;
  1073. }
  1074. if (addr4) {
  1075. struct in_addr addr_struct;
  1076. addr_struct.s_addr = addr4->list.addr;
  1077. ret_val = nla_put(cb_arg->skb,
  1078. NLBL_UNLABEL_A_IPV4ADDR,
  1079. sizeof(struct in_addr),
  1080. &addr_struct);
  1081. if (ret_val != 0)
  1082. goto list_cb_failure;
  1083. addr_struct.s_addr = addr4->list.mask;
  1084. ret_val = nla_put(cb_arg->skb,
  1085. NLBL_UNLABEL_A_IPV4MASK,
  1086. sizeof(struct in_addr),
  1087. &addr_struct);
  1088. if (ret_val != 0)
  1089. goto list_cb_failure;
  1090. secid = addr4->secid;
  1091. } else {
  1092. ret_val = nla_put(cb_arg->skb,
  1093. NLBL_UNLABEL_A_IPV6ADDR,
  1094. sizeof(struct in6_addr),
  1095. &addr6->list.addr);
  1096. if (ret_val != 0)
  1097. goto list_cb_failure;
  1098. ret_val = nla_put(cb_arg->skb,
  1099. NLBL_UNLABEL_A_IPV6MASK,
  1100. sizeof(struct in6_addr),
  1101. &addr6->list.mask);
  1102. if (ret_val != 0)
  1103. goto list_cb_failure;
  1104. secid = addr6->secid;
  1105. }
  1106. ret_val = security_secid_to_secctx(secid, &secctx, &secctx_len);
  1107. if (ret_val != 0)
  1108. goto list_cb_failure;
  1109. ret_val = nla_put(cb_arg->skb,
  1110. NLBL_UNLABEL_A_SECCTX,
  1111. secctx_len,
  1112. secctx);
  1113. security_release_secctx(secctx, secctx_len);
  1114. if (ret_val != 0)
  1115. goto list_cb_failure;
  1116. cb_arg->seq++;
  1117. return genlmsg_end(cb_arg->skb, data);
  1118. list_cb_failure:
  1119. genlmsg_cancel(cb_arg->skb, data);
  1120. return ret_val;
  1121. }
  1122. /**
  1123. * netlbl_unlabel_staticlist - Handle a STATICLIST message
  1124. * @skb: the NETLINK buffer
  1125. * @cb: the NETLINK callback
  1126. *
  1127. * Description:
  1128. * Process a user generated STATICLIST message and dump the unlabeled
  1129. * connection hash table in a form suitable for use in a kernel generated
  1130. * STATICLIST message. Returns the length of @skb.
  1131. *
  1132. */
  1133. static int netlbl_unlabel_staticlist(struct sk_buff *skb,
  1134. struct netlink_callback *cb)
  1135. {
  1136. struct netlbl_unlhsh_walk_arg cb_arg;
  1137. u32 skip_bkt = cb->args[0];
  1138. u32 skip_chain = cb->args[1];
  1139. u32 skip_addr4 = cb->args[2];
  1140. u32 skip_addr6 = cb->args[3];
  1141. u32 iter_bkt;
  1142. u32 iter_chain = 0, iter_addr4 = 0, iter_addr6 = 0;
  1143. struct netlbl_unlhsh_iface *iface;
  1144. struct list_head *iter_list;
  1145. struct netlbl_af4list *addr4;
  1146. #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
  1147. struct netlbl_af6list *addr6;
  1148. #endif
  1149. cb_arg.nl_cb = cb;
  1150. cb_arg.skb = skb;
  1151. cb_arg.seq = cb->nlh->nlmsg_seq;
  1152. rcu_read_lock();
  1153. for (iter_bkt = skip_bkt;
  1154. iter_bkt < rcu_dereference(netlbl_unlhsh)->size;
  1155. iter_bkt++, iter_chain = 0, iter_addr4 = 0, iter_addr6 = 0) {
  1156. iter_list = &rcu_dereference(netlbl_unlhsh)->tbl[iter_bkt];
  1157. list_for_each_entry_rcu(iface, iter_list, list) {
  1158. if (!iface->valid ||
  1159. iter_chain++ < skip_chain)
  1160. continue;
  1161. netlbl_af4list_foreach_rcu(addr4,
  1162. &iface->addr4_list) {
  1163. if (iter_addr4++ < skip_addr4)
  1164. continue;
  1165. if (netlbl_unlabel_staticlist_gen(
  1166. NLBL_UNLABEL_C_STATICLIST,
  1167. iface,
  1168. netlbl_unlhsh_addr4_entry(addr4),
  1169. NULL,
  1170. &cb_arg) < 0) {
  1171. iter_addr4--;
  1172. iter_chain--;
  1173. goto unlabel_staticlist_return;
  1174. }
  1175. }
  1176. #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
  1177. netlbl_af6list_foreach_rcu(addr6,
  1178. &iface->addr6_list) {
  1179. if (iter_addr6++ < skip_addr6)
  1180. continue;
  1181. if (netlbl_unlabel_staticlist_gen(
  1182. NLBL_UNLABEL_C_STATICLIST,
  1183. iface,
  1184. NULL,
  1185. netlbl_unlhsh_addr6_entry(addr6),
  1186. &cb_arg) < 0) {
  1187. iter_addr6--;
  1188. iter_chain--;
  1189. goto unlabel_staticlist_return;
  1190. }
  1191. }
  1192. #endif /* IPv6 */
  1193. }
  1194. }
  1195. unlabel_staticlist_return:
  1196. rcu_read_unlock();
  1197. cb->args[0] = skip_bkt;
  1198. cb->args[1] = skip_chain;
  1199. cb->args[2] = skip_addr4;
  1200. cb->args[3] = skip_addr6;
  1201. return skb->len;
  1202. }
  1203. /**
  1204. * netlbl_unlabel_staticlistdef - Handle a STATICLISTDEF message
  1205. * @skb: the NETLINK buffer
  1206. * @cb: the NETLINK callback
  1207. *
  1208. * Description:
  1209. * Process a user generated STATICLISTDEF message and dump the default
  1210. * unlabeled connection entry in a form suitable for use in a kernel generated
  1211. * STATICLISTDEF message. Returns the length of @skb.
  1212. *
  1213. */
  1214. static int netlbl_unlabel_staticlistdef(struct sk_buff *skb,
  1215. struct netlink_callback *cb)
  1216. {
  1217. struct netlbl_unlhsh_walk_arg cb_arg;
  1218. struct netlbl_unlhsh_iface *iface;
  1219. u32 skip_addr4 = cb->args[0];
  1220. u32 skip_addr6 = cb->args[1];
  1221. u32 iter_addr4 = 0;
  1222. struct netlbl_af4list *addr4;
  1223. #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
  1224. u32 iter_addr6 = 0;
  1225. struct netlbl_af6list *addr6;
  1226. #endif
  1227. cb_arg.nl_cb = cb;
  1228. cb_arg.skb = skb;
  1229. cb_arg.seq = cb->nlh->nlmsg_seq;
  1230. rcu_read_lock();
  1231. iface = rcu_dereference(netlbl_unlhsh_def);
  1232. if (iface == NULL || !iface->valid)
  1233. goto unlabel_staticlistdef_return;
  1234. netlbl_af4list_foreach_rcu(addr4, &iface->addr4_list) {
  1235. if (iter_addr4++ < skip_addr4)
  1236. continue;
  1237. if (netlbl_unlabel_staticlist_gen(NLBL_UNLABEL_C_STATICLISTDEF,
  1238. iface,
  1239. netlbl_unlhsh_addr4_entry(addr4),
  1240. NULL,
  1241. &cb_arg) < 0) {
  1242. iter_addr4--;
  1243. goto unlabel_staticlistdef_return;
  1244. }
  1245. }
  1246. #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
  1247. netlbl_af6list_foreach_rcu(addr6, &iface->addr6_list) {
  1248. if (iter_addr6++ < skip_addr6)
  1249. continue;
  1250. if (netlbl_unlabel_staticlist_gen(NLBL_UNLABEL_C_STATICLISTDEF,
  1251. iface,
  1252. NULL,
  1253. netlbl_unlhsh_addr6_entry(addr6),
  1254. &cb_arg) < 0) {
  1255. iter_addr6--;
  1256. goto unlabel_staticlistdef_return;
  1257. }
  1258. }
  1259. #endif /* IPv6 */
  1260. unlabel_staticlistdef_return:
  1261. rcu_read_unlock();
  1262. cb->args[0] = skip_addr4;
  1263. cb->args[1] = skip_addr6;
  1264. return skb->len;
  1265. }
  1266. /*
  1267. * NetLabel Generic NETLINK Command Definitions
  1268. */
  1269. static struct genl_ops netlbl_unlabel_genl_ops[] = {
  1270. {
  1271. .cmd = NLBL_UNLABEL_C_STATICADD,
  1272. .flags = GENL_ADMIN_PERM,
  1273. .policy = netlbl_unlabel_genl_policy,
  1274. .doit = netlbl_unlabel_staticadd,
  1275. .dumpit = NULL,
  1276. },
  1277. {
  1278. .cmd = NLBL_UNLABEL_C_STATICREMOVE,
  1279. .flags = GENL_ADMIN_PERM,
  1280. .policy = netlbl_unlabel_genl_policy,
  1281. .doit = netlbl_unlabel_staticremove,
  1282. .dumpit = NULL,
  1283. },
  1284. {
  1285. .cmd = NLBL_UNLABEL_C_STATICLIST,
  1286. .flags = 0,
  1287. .policy = netlbl_unlabel_genl_policy,
  1288. .doit = NULL,
  1289. .dumpit = netlbl_unlabel_staticlist,
  1290. },
  1291. {
  1292. .cmd = NLBL_UNLABEL_C_STATICADDDEF,
  1293. .flags = GENL_ADMIN_PERM,
  1294. .policy = netlbl_unlabel_genl_policy,
  1295. .doit = netlbl_unlabel_staticadddef,
  1296. .dumpit = NULL,
  1297. },
  1298. {
  1299. .cmd = NLBL_UNLABEL_C_STATICREMOVEDEF,
  1300. .flags = GENL_ADMIN_PERM,
  1301. .policy = netlbl_unlabel_genl_policy,
  1302. .doit = netlbl_unlabel_staticremovedef,
  1303. .dumpit = NULL,
  1304. },
  1305. {
  1306. .cmd = NLBL_UNLABEL_C_STATICLISTDEF,
  1307. .flags = 0,
  1308. .policy = netlbl_unlabel_genl_policy,
  1309. .doit = NULL,
  1310. .dumpit = netlbl_unlabel_staticlistdef,
  1311. },
  1312. {
  1313. .cmd = NLBL_UNLABEL_C_ACCEPT,
  1314. .flags = GENL_ADMIN_PERM,
  1315. .policy = netlbl_unlabel_genl_policy,
  1316. .doit = netlbl_unlabel_accept,
  1317. .dumpit = NULL,
  1318. },
  1319. {
  1320. .cmd = NLBL_UNLABEL_C_LIST,
  1321. .flags = 0,
  1322. .policy = netlbl_unlabel_genl_policy,
  1323. .doit = netlbl_unlabel_list,
  1324. .dumpit = NULL,
  1325. },
  1326. };
  1327. /*
  1328. * NetLabel Generic NETLINK Protocol Functions
  1329. */
  1330. /**
  1331. * netlbl_unlabel_genl_init - Register the Unlabeled NetLabel component
  1332. *
  1333. * Description:
  1334. * Register the unlabeled packet NetLabel component with the Generic NETLINK
  1335. * mechanism. Returns zero on success, negative values on failure.
  1336. *
  1337. */
  1338. int __init netlbl_unlabel_genl_init(void)
  1339. {
  1340. return genl_register_family_with_ops(&netlbl_unlabel_gnl_family,
  1341. netlbl_unlabel_genl_ops, ARRAY_SIZE(netlbl_unlabel_genl_ops));
  1342. }
  1343. /*
  1344. * NetLabel KAPI Hooks
  1345. */
  1346. static struct notifier_block netlbl_unlhsh_netdev_notifier = {
  1347. .notifier_call = netlbl_unlhsh_netdev_handler,
  1348. };
  1349. /**
  1350. * netlbl_unlabel_init - Initialize the unlabeled connection hash table
  1351. * @size: the number of bits to use for the hash buckets
  1352. *
  1353. * Description:
  1354. * Initializes the unlabeled connection hash table and registers a network
  1355. * device notification handler. This function should only be called by the
  1356. * NetLabel subsystem itself during initialization. Returns zero on success,
  1357. * non-zero values on error.
  1358. *
  1359. */
  1360. int __init netlbl_unlabel_init(u32 size)
  1361. {
  1362. u32 iter;
  1363. struct netlbl_unlhsh_tbl *hsh_tbl;
  1364. if (size == 0)
  1365. return -EINVAL;
  1366. hsh_tbl = kmalloc(sizeof(*hsh_tbl), GFP_KERNEL);
  1367. if (hsh_tbl == NULL)
  1368. return -ENOMEM;
  1369. hsh_tbl->size = 1 << size;
  1370. hsh_tbl->tbl = kcalloc(hsh_tbl->size,
  1371. sizeof(struct list_head),
  1372. GFP_KERNEL);
  1373. if (hsh_tbl->tbl == NULL) {
  1374. kfree(hsh_tbl);
  1375. return -ENOMEM;
  1376. }
  1377. for (iter = 0; iter < hsh_tbl->size; iter++)
  1378. INIT_LIST_HEAD(&hsh_tbl->tbl[iter]);
  1379. rcu_read_lock();
  1380. spin_lock(&netlbl_unlhsh_lock);
  1381. rcu_assign_pointer(netlbl_unlhsh, hsh_tbl);
  1382. spin_unlock(&netlbl_unlhsh_lock);
  1383. rcu_read_unlock();
  1384. register_netdevice_notifier(&netlbl_unlhsh_netdev_notifier);
  1385. return 0;
  1386. }
  1387. /**
  1388. * netlbl_unlabel_getattr - Get the security attributes for an unlabled packet
  1389. * @skb: the packet
  1390. * @family: protocol family
  1391. * @secattr: the security attributes
  1392. *
  1393. * Description:
  1394. * Determine the security attributes, if any, for an unlabled packet and return
  1395. * them in @secattr. Returns zero on success and negative values on failure.
  1396. *
  1397. */
  1398. int netlbl_unlabel_getattr(const struct sk_buff *skb,
  1399. u16 family,
  1400. struct netlbl_lsm_secattr *secattr)
  1401. {
  1402. struct netlbl_unlhsh_iface *iface;
  1403. rcu_read_lock();
  1404. iface = netlbl_unlhsh_search_iface_def(skb->skb_iif);
  1405. if (iface == NULL)
  1406. goto unlabel_getattr_nolabel;
  1407. switch (family) {
  1408. case PF_INET: {
  1409. struct iphdr *hdr4;
  1410. struct netlbl_af4list *addr4;
  1411. hdr4 = ip_hdr(skb);
  1412. addr4 = netlbl_af4list_search(hdr4->saddr,
  1413. &iface->addr4_list);
  1414. if (addr4 == NULL)
  1415. goto unlabel_getattr_nolabel;
  1416. secattr->attr.secid = netlbl_unlhsh_addr4_entry(addr4)->secid;
  1417. break;
  1418. }
  1419. #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
  1420. case PF_INET6: {
  1421. struct ipv6hdr *hdr6;
  1422. struct netlbl_af6list *addr6;
  1423. hdr6 = ipv6_hdr(skb);
  1424. addr6 = netlbl_af6list_search(&hdr6->saddr,
  1425. &iface->addr6_list);
  1426. if (addr6 == NULL)
  1427. goto unlabel_getattr_nolabel;
  1428. secattr->attr.secid = netlbl_unlhsh_addr6_entry(addr6)->secid;
  1429. break;
  1430. }
  1431. #endif /* IPv6 */
  1432. default:
  1433. goto unlabel_getattr_nolabel;
  1434. }
  1435. rcu_read_unlock();
  1436. secattr->flags |= NETLBL_SECATTR_SECID;
  1437. secattr->type = NETLBL_NLTYPE_UNLABELED;
  1438. return 0;
  1439. unlabel_getattr_nolabel:
  1440. rcu_read_unlock();
  1441. if (netlabel_unlabel_acceptflg == 0)
  1442. return -ENOMSG;
  1443. secattr->type = NETLBL_NLTYPE_UNLABELED;
  1444. return 0;
  1445. }
  1446. /**
  1447. * netlbl_unlabel_defconf - Set the default config to allow unlabeled packets
  1448. *
  1449. * Description:
  1450. * Set the default NetLabel configuration to allow incoming unlabeled packets
  1451. * and to send unlabeled network traffic by default.
  1452. *
  1453. */
  1454. int __init netlbl_unlabel_defconf(void)
  1455. {
  1456. int ret_val;
  1457. struct netlbl_dom_map *entry;
  1458. struct netlbl_audit audit_info;
  1459. /* Only the kernel is allowed to call this function and the only time
  1460. * it is called is at bootup before the audit subsystem is reporting
  1461. * messages so don't worry to much about these values. */
  1462. security_task_getsecid(current, &audit_info.secid);
  1463. audit_info.loginuid = 0;
  1464. audit_info.sessionid = 0;
  1465. entry = kzalloc(sizeof(*entry), GFP_KERNEL);
  1466. if (entry == NULL)
  1467. return -ENOMEM;
  1468. entry->type = NETLBL_NLTYPE_UNLABELED;
  1469. ret_val = netlbl_domhsh_add_default(entry, &audit_info);
  1470. if (ret_val != 0)
  1471. return ret_val;
  1472. netlbl_unlabel_acceptflg_set(1, &audit_info);
  1473. return 0;
  1474. }