netlabel_unlabeled.c 48 KB

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