netlabel_unlabeled.c 48 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792
  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_net(dev) != &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. return genlmsg_reply(ans_skb, info);
  1016. list_failure:
  1017. kfree_skb(ans_skb);
  1018. return ret_val;
  1019. }
  1020. /**
  1021. * netlbl_unlabel_staticadd - Handle a STATICADD message
  1022. * @skb: the NETLINK buffer
  1023. * @info: the Generic NETLINK info block
  1024. *
  1025. * Description:
  1026. * Process a user generated STATICADD message and add a new unlabeled
  1027. * connection entry to the hash table. Returns zero on success, negative
  1028. * values on failure.
  1029. *
  1030. */
  1031. static int netlbl_unlabel_staticadd(struct sk_buff *skb,
  1032. struct genl_info *info)
  1033. {
  1034. int ret_val;
  1035. char *dev_name;
  1036. void *addr;
  1037. void *mask;
  1038. u32 addr_len;
  1039. u32 secid;
  1040. struct netlbl_audit audit_info;
  1041. /* Don't allow users to add both IPv4 and IPv6 addresses for a
  1042. * single entry. However, allow users to create two entries, one each
  1043. * for IPv4 and IPv4, with the same LSM security context which should
  1044. * achieve the same result. */
  1045. if (!info->attrs[NLBL_UNLABEL_A_SECCTX] ||
  1046. !info->attrs[NLBL_UNLABEL_A_IFACE] ||
  1047. !((!info->attrs[NLBL_UNLABEL_A_IPV4ADDR] ||
  1048. !info->attrs[NLBL_UNLABEL_A_IPV4MASK]) ^
  1049. (!info->attrs[NLBL_UNLABEL_A_IPV6ADDR] ||
  1050. !info->attrs[NLBL_UNLABEL_A_IPV6MASK])))
  1051. return -EINVAL;
  1052. netlbl_netlink_auditinfo(skb, &audit_info);
  1053. ret_val = netlbl_unlabel_addrinfo_get(info, &addr, &mask, &addr_len);
  1054. if (ret_val != 0)
  1055. return ret_val;
  1056. dev_name = nla_data(info->attrs[NLBL_UNLABEL_A_IFACE]);
  1057. ret_val = security_secctx_to_secid(
  1058. nla_data(info->attrs[NLBL_UNLABEL_A_SECCTX]),
  1059. nla_len(info->attrs[NLBL_UNLABEL_A_SECCTX]),
  1060. &secid);
  1061. if (ret_val != 0)
  1062. return ret_val;
  1063. return netlbl_unlhsh_add(&init_net,
  1064. dev_name, addr, mask, addr_len, secid,
  1065. &audit_info);
  1066. }
  1067. /**
  1068. * netlbl_unlabel_staticadddef - Handle a STATICADDDEF message
  1069. * @skb: the NETLINK buffer
  1070. * @info: the Generic NETLINK info block
  1071. *
  1072. * Description:
  1073. * Process a user generated STATICADDDEF message and add a new default
  1074. * unlabeled connection entry. Returns zero on success, negative values on
  1075. * failure.
  1076. *
  1077. */
  1078. static int netlbl_unlabel_staticadddef(struct sk_buff *skb,
  1079. struct genl_info *info)
  1080. {
  1081. int ret_val;
  1082. void *addr;
  1083. void *mask;
  1084. u32 addr_len;
  1085. u32 secid;
  1086. struct netlbl_audit audit_info;
  1087. /* Don't allow users to add both IPv4 and IPv6 addresses for a
  1088. * single entry. However, allow users to create two entries, one each
  1089. * for IPv4 and IPv6, with the same LSM security context which should
  1090. * achieve the same result. */
  1091. if (!info->attrs[NLBL_UNLABEL_A_SECCTX] ||
  1092. !((!info->attrs[NLBL_UNLABEL_A_IPV4ADDR] ||
  1093. !info->attrs[NLBL_UNLABEL_A_IPV4MASK]) ^
  1094. (!info->attrs[NLBL_UNLABEL_A_IPV6ADDR] ||
  1095. !info->attrs[NLBL_UNLABEL_A_IPV6MASK])))
  1096. return -EINVAL;
  1097. netlbl_netlink_auditinfo(skb, &audit_info);
  1098. ret_val = netlbl_unlabel_addrinfo_get(info, &addr, &mask, &addr_len);
  1099. if (ret_val != 0)
  1100. return ret_val;
  1101. ret_val = security_secctx_to_secid(
  1102. nla_data(info->attrs[NLBL_UNLABEL_A_SECCTX]),
  1103. nla_len(info->attrs[NLBL_UNLABEL_A_SECCTX]),
  1104. &secid);
  1105. if (ret_val != 0)
  1106. return ret_val;
  1107. return netlbl_unlhsh_add(&init_net,
  1108. NULL, addr, mask, addr_len, secid,
  1109. &audit_info);
  1110. }
  1111. /**
  1112. * netlbl_unlabel_staticremove - Handle a STATICREMOVE message
  1113. * @skb: the NETLINK buffer
  1114. * @info: the Generic NETLINK info block
  1115. *
  1116. * Description:
  1117. * Process a user generated STATICREMOVE message and remove the specified
  1118. * unlabeled connection entry. Returns zero on success, negative values on
  1119. * failure.
  1120. *
  1121. */
  1122. static int netlbl_unlabel_staticremove(struct sk_buff *skb,
  1123. struct genl_info *info)
  1124. {
  1125. int ret_val;
  1126. char *dev_name;
  1127. void *addr;
  1128. void *mask;
  1129. u32 addr_len;
  1130. struct netlbl_audit audit_info;
  1131. /* See the note in netlbl_unlabel_staticadd() about not allowing both
  1132. * IPv4 and IPv6 in the same entry. */
  1133. if (!info->attrs[NLBL_UNLABEL_A_IFACE] ||
  1134. !((!info->attrs[NLBL_UNLABEL_A_IPV4ADDR] ||
  1135. !info->attrs[NLBL_UNLABEL_A_IPV4MASK]) ^
  1136. (!info->attrs[NLBL_UNLABEL_A_IPV6ADDR] ||
  1137. !info->attrs[NLBL_UNLABEL_A_IPV6MASK])))
  1138. return -EINVAL;
  1139. netlbl_netlink_auditinfo(skb, &audit_info);
  1140. ret_val = netlbl_unlabel_addrinfo_get(info, &addr, &mask, &addr_len);
  1141. if (ret_val != 0)
  1142. return ret_val;
  1143. dev_name = nla_data(info->attrs[NLBL_UNLABEL_A_IFACE]);
  1144. return netlbl_unlhsh_remove(&init_net,
  1145. dev_name, addr, mask, addr_len,
  1146. &audit_info);
  1147. }
  1148. /**
  1149. * netlbl_unlabel_staticremovedef - Handle a STATICREMOVEDEF message
  1150. * @skb: the NETLINK buffer
  1151. * @info: the Generic NETLINK info block
  1152. *
  1153. * Description:
  1154. * Process a user generated STATICREMOVEDEF message and remove the default
  1155. * unlabeled connection entry. Returns zero on success, negative values on
  1156. * failure.
  1157. *
  1158. */
  1159. static int netlbl_unlabel_staticremovedef(struct sk_buff *skb,
  1160. struct genl_info *info)
  1161. {
  1162. int ret_val;
  1163. void *addr;
  1164. void *mask;
  1165. u32 addr_len;
  1166. struct netlbl_audit audit_info;
  1167. /* See the note in netlbl_unlabel_staticadd() about not allowing both
  1168. * IPv4 and IPv6 in the same entry. */
  1169. if (!((!info->attrs[NLBL_UNLABEL_A_IPV4ADDR] ||
  1170. !info->attrs[NLBL_UNLABEL_A_IPV4MASK]) ^
  1171. (!info->attrs[NLBL_UNLABEL_A_IPV6ADDR] ||
  1172. !info->attrs[NLBL_UNLABEL_A_IPV6MASK])))
  1173. return -EINVAL;
  1174. netlbl_netlink_auditinfo(skb, &audit_info);
  1175. ret_val = netlbl_unlabel_addrinfo_get(info, &addr, &mask, &addr_len);
  1176. if (ret_val != 0)
  1177. return ret_val;
  1178. return netlbl_unlhsh_remove(&init_net,
  1179. NULL, addr, mask, addr_len,
  1180. &audit_info);
  1181. }
  1182. /**
  1183. * netlbl_unlabel_staticlist_gen - Generate messages for STATICLIST[DEF]
  1184. * @cmd: command/message
  1185. * @iface: the interface entry
  1186. * @addr4: the IPv4 address entry
  1187. * @addr6: the IPv6 address entry
  1188. * @arg: the netlbl_unlhsh_walk_arg structure
  1189. *
  1190. * Description:
  1191. * This function is designed to be used to generate a response for a
  1192. * STATICLIST or STATICLISTDEF message. When called either @addr4 or @addr6
  1193. * can be specified, not both, the other unspecified entry should be set to
  1194. * NULL by the caller. Returns the size of the message on success, negative
  1195. * values on failure.
  1196. *
  1197. */
  1198. static int netlbl_unlabel_staticlist_gen(u32 cmd,
  1199. const struct netlbl_unlhsh_iface *iface,
  1200. const struct netlbl_unlhsh_addr4 *addr4,
  1201. const struct netlbl_unlhsh_addr6 *addr6,
  1202. void *arg)
  1203. {
  1204. int ret_val = -ENOMEM;
  1205. struct netlbl_unlhsh_walk_arg *cb_arg = arg;
  1206. struct net_device *dev;
  1207. void *data;
  1208. u32 secid;
  1209. char *secctx;
  1210. u32 secctx_len;
  1211. data = genlmsg_put(cb_arg->skb, NETLINK_CB(cb_arg->nl_cb->skb).pid,
  1212. cb_arg->seq, &netlbl_unlabel_gnl_family,
  1213. NLM_F_MULTI, cmd);
  1214. if (data == NULL)
  1215. goto list_cb_failure;
  1216. if (iface->ifindex > 0) {
  1217. dev = dev_get_by_index(&init_net, iface->ifindex);
  1218. if (!dev) {
  1219. ret_val = -ENODEV;
  1220. goto list_cb_failure;
  1221. }
  1222. ret_val = nla_put_string(cb_arg->skb,
  1223. NLBL_UNLABEL_A_IFACE, dev->name);
  1224. dev_put(dev);
  1225. if (ret_val != 0)
  1226. goto list_cb_failure;
  1227. }
  1228. if (addr4) {
  1229. struct in_addr addr_struct;
  1230. addr_struct.s_addr = addr4->addr;
  1231. ret_val = nla_put(cb_arg->skb,
  1232. NLBL_UNLABEL_A_IPV4ADDR,
  1233. sizeof(struct in_addr),
  1234. &addr_struct);
  1235. if (ret_val != 0)
  1236. goto list_cb_failure;
  1237. addr_struct.s_addr = addr4->mask;
  1238. ret_val = nla_put(cb_arg->skb,
  1239. NLBL_UNLABEL_A_IPV4MASK,
  1240. sizeof(struct in_addr),
  1241. &addr_struct);
  1242. if (ret_val != 0)
  1243. goto list_cb_failure;
  1244. secid = addr4->secid;
  1245. } else {
  1246. ret_val = nla_put(cb_arg->skb,
  1247. NLBL_UNLABEL_A_IPV6ADDR,
  1248. sizeof(struct in6_addr),
  1249. &addr6->addr);
  1250. if (ret_val != 0)
  1251. goto list_cb_failure;
  1252. ret_val = nla_put(cb_arg->skb,
  1253. NLBL_UNLABEL_A_IPV6MASK,
  1254. sizeof(struct in6_addr),
  1255. &addr6->mask);
  1256. if (ret_val != 0)
  1257. goto list_cb_failure;
  1258. secid = addr6->secid;
  1259. }
  1260. ret_val = security_secid_to_secctx(secid, &secctx, &secctx_len);
  1261. if (ret_val != 0)
  1262. goto list_cb_failure;
  1263. ret_val = nla_put(cb_arg->skb,
  1264. NLBL_UNLABEL_A_SECCTX,
  1265. secctx_len,
  1266. secctx);
  1267. security_release_secctx(secctx, secctx_len);
  1268. if (ret_val != 0)
  1269. goto list_cb_failure;
  1270. cb_arg->seq++;
  1271. return genlmsg_end(cb_arg->skb, data);
  1272. list_cb_failure:
  1273. genlmsg_cancel(cb_arg->skb, data);
  1274. return ret_val;
  1275. }
  1276. /**
  1277. * netlbl_unlabel_staticlist - Handle a STATICLIST message
  1278. * @skb: the NETLINK buffer
  1279. * @cb: the NETLINK callback
  1280. *
  1281. * Description:
  1282. * Process a user generated STATICLIST message and dump the unlabeled
  1283. * connection hash table in a form suitable for use in a kernel generated
  1284. * STATICLIST message. Returns the length of @skb.
  1285. *
  1286. */
  1287. static int netlbl_unlabel_staticlist(struct sk_buff *skb,
  1288. struct netlink_callback *cb)
  1289. {
  1290. struct netlbl_unlhsh_walk_arg cb_arg;
  1291. u32 skip_bkt = cb->args[0];
  1292. u32 skip_chain = cb->args[1];
  1293. u32 skip_addr4 = cb->args[2];
  1294. u32 skip_addr6 = cb->args[3];
  1295. u32 iter_bkt;
  1296. u32 iter_chain = 0, iter_addr4 = 0, iter_addr6 = 0;
  1297. struct netlbl_unlhsh_iface *iface;
  1298. struct netlbl_unlhsh_addr4 *addr4;
  1299. struct netlbl_unlhsh_addr6 *addr6;
  1300. cb_arg.nl_cb = cb;
  1301. cb_arg.skb = skb;
  1302. cb_arg.seq = cb->nlh->nlmsg_seq;
  1303. rcu_read_lock();
  1304. for (iter_bkt = skip_bkt;
  1305. iter_bkt < rcu_dereference(netlbl_unlhsh)->size;
  1306. iter_bkt++, iter_chain = 0, iter_addr4 = 0, iter_addr6 = 0) {
  1307. list_for_each_entry_rcu(iface,
  1308. &rcu_dereference(netlbl_unlhsh)->tbl[iter_bkt],
  1309. list) {
  1310. if (!iface->valid ||
  1311. iter_chain++ < skip_chain)
  1312. continue;
  1313. list_for_each_entry_rcu(addr4,
  1314. &iface->addr4_list,
  1315. list) {
  1316. if (!addr4->valid || iter_addr4++ < skip_addr4)
  1317. continue;
  1318. if (netlbl_unlabel_staticlist_gen(
  1319. NLBL_UNLABEL_C_STATICLIST,
  1320. iface,
  1321. addr4,
  1322. NULL,
  1323. &cb_arg) < 0) {
  1324. iter_addr4--;
  1325. iter_chain--;
  1326. goto unlabel_staticlist_return;
  1327. }
  1328. }
  1329. list_for_each_entry_rcu(addr6,
  1330. &iface->addr6_list,
  1331. list) {
  1332. if (!addr6->valid || iter_addr6++ < skip_addr6)
  1333. continue;
  1334. if (netlbl_unlabel_staticlist_gen(
  1335. NLBL_UNLABEL_C_STATICLIST,
  1336. iface,
  1337. NULL,
  1338. addr6,
  1339. &cb_arg) < 0) {
  1340. iter_addr6--;
  1341. iter_chain--;
  1342. goto unlabel_staticlist_return;
  1343. }
  1344. }
  1345. }
  1346. }
  1347. unlabel_staticlist_return:
  1348. rcu_read_unlock();
  1349. cb->args[0] = skip_bkt;
  1350. cb->args[1] = skip_chain;
  1351. cb->args[2] = skip_addr4;
  1352. cb->args[3] = skip_addr6;
  1353. return skb->len;
  1354. }
  1355. /**
  1356. * netlbl_unlabel_staticlistdef - Handle a STATICLISTDEF message
  1357. * @skb: the NETLINK buffer
  1358. * @cb: the NETLINK callback
  1359. *
  1360. * Description:
  1361. * Process a user generated STATICLISTDEF message and dump the default
  1362. * unlabeled connection entry in a form suitable for use in a kernel generated
  1363. * STATICLISTDEF message. Returns the length of @skb.
  1364. *
  1365. */
  1366. static int netlbl_unlabel_staticlistdef(struct sk_buff *skb,
  1367. struct netlink_callback *cb)
  1368. {
  1369. struct netlbl_unlhsh_walk_arg cb_arg;
  1370. struct netlbl_unlhsh_iface *iface;
  1371. u32 skip_addr4 = cb->args[0];
  1372. u32 skip_addr6 = cb->args[1];
  1373. u32 iter_addr4 = 0, iter_addr6 = 0;
  1374. struct netlbl_unlhsh_addr4 *addr4;
  1375. struct netlbl_unlhsh_addr6 *addr6;
  1376. cb_arg.nl_cb = cb;
  1377. cb_arg.skb = skb;
  1378. cb_arg.seq = cb->nlh->nlmsg_seq;
  1379. rcu_read_lock();
  1380. iface = rcu_dereference(netlbl_unlhsh_def);
  1381. if (iface == NULL || !iface->valid)
  1382. goto unlabel_staticlistdef_return;
  1383. list_for_each_entry_rcu(addr4, &iface->addr4_list, list) {
  1384. if (!addr4->valid || iter_addr4++ < skip_addr4)
  1385. continue;
  1386. if (netlbl_unlabel_staticlist_gen(NLBL_UNLABEL_C_STATICLISTDEF,
  1387. iface,
  1388. addr4,
  1389. NULL,
  1390. &cb_arg) < 0) {
  1391. iter_addr4--;
  1392. goto unlabel_staticlistdef_return;
  1393. }
  1394. }
  1395. list_for_each_entry_rcu(addr6, &iface->addr6_list, list) {
  1396. if (!addr6->valid || iter_addr6++ < skip_addr6)
  1397. continue;
  1398. if (netlbl_unlabel_staticlist_gen(NLBL_UNLABEL_C_STATICLISTDEF,
  1399. iface,
  1400. NULL,
  1401. addr6,
  1402. &cb_arg) < 0) {
  1403. iter_addr6--;
  1404. goto unlabel_staticlistdef_return;
  1405. }
  1406. }
  1407. unlabel_staticlistdef_return:
  1408. rcu_read_unlock();
  1409. cb->args[0] = skip_addr4;
  1410. cb->args[1] = skip_addr6;
  1411. return skb->len;
  1412. }
  1413. /*
  1414. * NetLabel Generic NETLINK Command Definitions
  1415. */
  1416. static struct genl_ops netlbl_unlabel_genl_ops[] = {
  1417. {
  1418. .cmd = NLBL_UNLABEL_C_STATICADD,
  1419. .flags = GENL_ADMIN_PERM,
  1420. .policy = netlbl_unlabel_genl_policy,
  1421. .doit = netlbl_unlabel_staticadd,
  1422. .dumpit = NULL,
  1423. },
  1424. {
  1425. .cmd = NLBL_UNLABEL_C_STATICREMOVE,
  1426. .flags = GENL_ADMIN_PERM,
  1427. .policy = netlbl_unlabel_genl_policy,
  1428. .doit = netlbl_unlabel_staticremove,
  1429. .dumpit = NULL,
  1430. },
  1431. {
  1432. .cmd = NLBL_UNLABEL_C_STATICLIST,
  1433. .flags = 0,
  1434. .policy = netlbl_unlabel_genl_policy,
  1435. .doit = NULL,
  1436. .dumpit = netlbl_unlabel_staticlist,
  1437. },
  1438. {
  1439. .cmd = NLBL_UNLABEL_C_STATICADDDEF,
  1440. .flags = GENL_ADMIN_PERM,
  1441. .policy = netlbl_unlabel_genl_policy,
  1442. .doit = netlbl_unlabel_staticadddef,
  1443. .dumpit = NULL,
  1444. },
  1445. {
  1446. .cmd = NLBL_UNLABEL_C_STATICREMOVEDEF,
  1447. .flags = GENL_ADMIN_PERM,
  1448. .policy = netlbl_unlabel_genl_policy,
  1449. .doit = netlbl_unlabel_staticremovedef,
  1450. .dumpit = NULL,
  1451. },
  1452. {
  1453. .cmd = NLBL_UNLABEL_C_STATICLISTDEF,
  1454. .flags = 0,
  1455. .policy = netlbl_unlabel_genl_policy,
  1456. .doit = NULL,
  1457. .dumpit = netlbl_unlabel_staticlistdef,
  1458. },
  1459. {
  1460. .cmd = NLBL_UNLABEL_C_ACCEPT,
  1461. .flags = GENL_ADMIN_PERM,
  1462. .policy = netlbl_unlabel_genl_policy,
  1463. .doit = netlbl_unlabel_accept,
  1464. .dumpit = NULL,
  1465. },
  1466. {
  1467. .cmd = NLBL_UNLABEL_C_LIST,
  1468. .flags = 0,
  1469. .policy = netlbl_unlabel_genl_policy,
  1470. .doit = netlbl_unlabel_list,
  1471. .dumpit = NULL,
  1472. },
  1473. };
  1474. /*
  1475. * NetLabel Generic NETLINK Protocol Functions
  1476. */
  1477. /**
  1478. * netlbl_unlabel_genl_init - Register the Unlabeled NetLabel component
  1479. *
  1480. * Description:
  1481. * Register the unlabeled packet NetLabel component with the Generic NETLINK
  1482. * mechanism. Returns zero on success, negative values on failure.
  1483. *
  1484. */
  1485. int __init netlbl_unlabel_genl_init(void)
  1486. {
  1487. int ret_val, i;
  1488. ret_val = genl_register_family(&netlbl_unlabel_gnl_family);
  1489. if (ret_val != 0)
  1490. return ret_val;
  1491. for (i = 0; i < ARRAY_SIZE(netlbl_unlabel_genl_ops); i++) {
  1492. ret_val = genl_register_ops(&netlbl_unlabel_gnl_family,
  1493. &netlbl_unlabel_genl_ops[i]);
  1494. if (ret_val != 0)
  1495. return ret_val;
  1496. }
  1497. return 0;
  1498. }
  1499. /*
  1500. * NetLabel KAPI Hooks
  1501. */
  1502. static struct notifier_block netlbl_unlhsh_netdev_notifier = {
  1503. .notifier_call = netlbl_unlhsh_netdev_handler,
  1504. };
  1505. /**
  1506. * netlbl_unlabel_init - Initialize the unlabeled connection hash table
  1507. * @size: the number of bits to use for the hash buckets
  1508. *
  1509. * Description:
  1510. * Initializes the unlabeled connection hash table and registers a network
  1511. * device notification handler. This function should only be called by the
  1512. * NetLabel subsystem itself during initialization. Returns zero on success,
  1513. * non-zero values on error.
  1514. *
  1515. */
  1516. int __init netlbl_unlabel_init(u32 size)
  1517. {
  1518. u32 iter;
  1519. struct netlbl_unlhsh_tbl *hsh_tbl;
  1520. if (size == 0)
  1521. return -EINVAL;
  1522. hsh_tbl = kmalloc(sizeof(*hsh_tbl), GFP_KERNEL);
  1523. if (hsh_tbl == NULL)
  1524. return -ENOMEM;
  1525. hsh_tbl->size = 1 << size;
  1526. hsh_tbl->tbl = kcalloc(hsh_tbl->size,
  1527. sizeof(struct list_head),
  1528. GFP_KERNEL);
  1529. if (hsh_tbl->tbl == NULL) {
  1530. kfree(hsh_tbl);
  1531. return -ENOMEM;
  1532. }
  1533. for (iter = 0; iter < hsh_tbl->size; iter++)
  1534. INIT_LIST_HEAD(&hsh_tbl->tbl[iter]);
  1535. rcu_read_lock();
  1536. spin_lock(&netlbl_unlhsh_lock);
  1537. rcu_assign_pointer(netlbl_unlhsh, hsh_tbl);
  1538. spin_unlock(&netlbl_unlhsh_lock);
  1539. rcu_read_unlock();
  1540. register_netdevice_notifier(&netlbl_unlhsh_netdev_notifier);
  1541. return 0;
  1542. }
  1543. /**
  1544. * netlbl_unlabel_getattr - Get the security attributes for an unlabled packet
  1545. * @skb: the packet
  1546. * @family: protocol family
  1547. * @secattr: the security attributes
  1548. *
  1549. * Description:
  1550. * Determine the security attributes, if any, for an unlabled packet and return
  1551. * them in @secattr. Returns zero on success and negative values on failure.
  1552. *
  1553. */
  1554. int netlbl_unlabel_getattr(const struct sk_buff *skb,
  1555. u16 family,
  1556. struct netlbl_lsm_secattr *secattr)
  1557. {
  1558. struct netlbl_unlhsh_iface *iface;
  1559. rcu_read_lock();
  1560. iface = netlbl_unlhsh_search_iface_def(skb->iif);
  1561. if (iface == NULL)
  1562. goto unlabel_getattr_nolabel;
  1563. switch (family) {
  1564. case PF_INET: {
  1565. struct iphdr *hdr4;
  1566. struct netlbl_unlhsh_addr4 *addr4;
  1567. hdr4 = ip_hdr(skb);
  1568. addr4 = netlbl_unlhsh_search_addr4(hdr4->saddr, iface);
  1569. if (addr4 == NULL)
  1570. goto unlabel_getattr_nolabel;
  1571. secattr->attr.secid = addr4->secid;
  1572. break;
  1573. }
  1574. #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
  1575. case PF_INET6: {
  1576. struct ipv6hdr *hdr6;
  1577. struct netlbl_unlhsh_addr6 *addr6;
  1578. hdr6 = ipv6_hdr(skb);
  1579. addr6 = netlbl_unlhsh_search_addr6(&hdr6->saddr, iface);
  1580. if (addr6 == NULL)
  1581. goto unlabel_getattr_nolabel;
  1582. secattr->attr.secid = addr6->secid;
  1583. break;
  1584. }
  1585. #endif /* IPv6 */
  1586. default:
  1587. goto unlabel_getattr_nolabel;
  1588. }
  1589. rcu_read_unlock();
  1590. secattr->flags |= NETLBL_SECATTR_SECID;
  1591. secattr->type = NETLBL_NLTYPE_UNLABELED;
  1592. return 0;
  1593. unlabel_getattr_nolabel:
  1594. rcu_read_unlock();
  1595. if (netlabel_unlabel_acceptflg == 0)
  1596. return -ENOMSG;
  1597. secattr->type = NETLBL_NLTYPE_UNLABELED;
  1598. return 0;
  1599. }
  1600. /**
  1601. * netlbl_unlabel_defconf - Set the default config to allow unlabeled packets
  1602. *
  1603. * Description:
  1604. * Set the default NetLabel configuration to allow incoming unlabeled packets
  1605. * and to send unlabeled network traffic by default.
  1606. *
  1607. */
  1608. int __init netlbl_unlabel_defconf(void)
  1609. {
  1610. int ret_val;
  1611. struct netlbl_dom_map *entry;
  1612. struct netlbl_audit audit_info;
  1613. /* Only the kernel is allowed to call this function and the only time
  1614. * it is called is at bootup before the audit subsystem is reporting
  1615. * messages so don't worry to much about these values. */
  1616. security_task_getsecid(current, &audit_info.secid);
  1617. audit_info.loginuid = 0;
  1618. audit_info.sessionid = 0;
  1619. entry = kzalloc(sizeof(*entry), GFP_KERNEL);
  1620. if (entry == NULL)
  1621. return -ENOMEM;
  1622. entry->type = NETLBL_NLTYPE_UNLABELED;
  1623. ret_val = netlbl_domhsh_add_default(entry, &audit_info);
  1624. if (ret_val != 0)
  1625. return ret_val;
  1626. netlbl_unlabel_acceptflg_set(1, &audit_info);
  1627. return 0;
  1628. }