netlabel_kapi.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590
  1. /*
  2. * NetLabel Kernel API
  3. *
  4. * This file defines the kernel API for the NetLabel system. The NetLabel
  5. * system manages static and dynamic label mappings for network protocols such
  6. * 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
  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/init.h>
  30. #include <linux/types.h>
  31. #include <linux/audit.h>
  32. #include <net/ip.h>
  33. #include <net/netlabel.h>
  34. #include <net/cipso_ipv4.h>
  35. #include <asm/bug.h>
  36. #include <asm/atomic.h>
  37. #include "netlabel_domainhash.h"
  38. #include "netlabel_unlabeled.h"
  39. #include "netlabel_cipso_v4.h"
  40. #include "netlabel_user.h"
  41. #include "netlabel_mgmt.h"
  42. /*
  43. * Configuration Functions
  44. */
  45. /**
  46. * netlbl_cfg_map_del - Remove a NetLabel/LSM domain mapping
  47. * @domain: the domain mapping to remove
  48. * @audit_info: NetLabel audit information
  49. *
  50. * Description:
  51. * Removes a NetLabel/LSM domain mapping. A @domain value of NULL causes the
  52. * default domain mapping to be removed. Returns zero on success, negative
  53. * values on failure.
  54. *
  55. */
  56. int netlbl_cfg_map_del(const char *domain, struct netlbl_audit *audit_info)
  57. {
  58. return netlbl_domhsh_remove(domain, audit_info);
  59. }
  60. /**
  61. * netlbl_cfg_unlbl_add_map - Add an unlabeled NetLabel/LSM domain mapping
  62. * @domain: the domain mapping to add
  63. * @audit_info: NetLabel audit information
  64. *
  65. * Description:
  66. * Adds a new unlabeled NetLabel/LSM domain mapping. A @domain value of NULL
  67. * causes a new default domain mapping to be added. Returns zero on success,
  68. * negative values on failure.
  69. *
  70. */
  71. int netlbl_cfg_unlbl_add_map(const char *domain,
  72. struct netlbl_audit *audit_info)
  73. {
  74. int ret_val = -ENOMEM;
  75. struct netlbl_dom_map *entry;
  76. entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
  77. if (entry == NULL)
  78. return -ENOMEM;
  79. if (domain != NULL) {
  80. entry->domain = kstrdup(domain, GFP_ATOMIC);
  81. if (entry->domain == NULL)
  82. goto cfg_unlbl_add_map_failure;
  83. }
  84. entry->type = NETLBL_NLTYPE_UNLABELED;
  85. ret_val = netlbl_domhsh_add(entry, audit_info);
  86. if (ret_val != 0)
  87. goto cfg_unlbl_add_map_failure;
  88. return 0;
  89. cfg_unlbl_add_map_failure:
  90. if (entry != NULL)
  91. kfree(entry->domain);
  92. kfree(entry);
  93. return ret_val;
  94. }
  95. /**
  96. * netlbl_cfg_cipsov4_add_map - Add a new CIPSOv4 DOI definition and mapping
  97. * @doi_def: the DOI definition
  98. * @domain: the domain mapping to add
  99. * @audit_info: NetLabel audit information
  100. *
  101. * Description:
  102. * Add a new CIPSOv4 DOI definition and NetLabel/LSM domain mapping for this
  103. * new DOI definition to the NetLabel subsystem. A @domain value of NULL adds
  104. * a new default domain mapping. Returns zero on success, negative values on
  105. * failure.
  106. *
  107. */
  108. int netlbl_cfg_cipsov4_add_map(struct cipso_v4_doi *doi_def,
  109. const char *domain,
  110. struct netlbl_audit *audit_info)
  111. {
  112. int ret_val = -ENOMEM;
  113. struct netlbl_dom_map *entry;
  114. const char *type_str;
  115. struct audit_buffer *audit_buf;
  116. entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
  117. if (entry == NULL)
  118. return -ENOMEM;
  119. if (domain != NULL) {
  120. entry->domain = kstrdup(domain, GFP_ATOMIC);
  121. if (entry->domain == NULL)
  122. goto cfg_cipsov4_add_map_failure;
  123. }
  124. entry->type = NETLBL_NLTYPE_CIPSOV4;
  125. entry->type_def.cipsov4 = doi_def;
  126. /* Grab a RCU read lock here so nothing happens to the doi_def variable
  127. * between adding it to the CIPSOv4 protocol engine and adding a
  128. * domain mapping for it. */
  129. rcu_read_lock();
  130. ret_val = cipso_v4_doi_add(doi_def);
  131. if (ret_val != 0)
  132. goto cfg_cipsov4_add_map_failure_unlock;
  133. ret_val = netlbl_domhsh_add(entry, audit_info);
  134. if (ret_val != 0)
  135. goto cfg_cipsov4_add_map_failure_remove_doi;
  136. rcu_read_unlock();
  137. return 0;
  138. cfg_cipsov4_add_map_failure_remove_doi:
  139. cipso_v4_doi_remove(doi_def->doi, audit_info, netlbl_cipsov4_doi_free);
  140. cfg_cipsov4_add_map_failure_unlock:
  141. rcu_read_unlock();
  142. audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_ADD,
  143. audit_info);
  144. if (audit_buf != NULL) {
  145. switch (doi_def->type) {
  146. case CIPSO_V4_MAP_STD:
  147. type_str = "std";
  148. break;
  149. case CIPSO_V4_MAP_PASS:
  150. type_str = "pass";
  151. break;
  152. default:
  153. type_str = "(unknown)";
  154. }
  155. audit_log_format(audit_buf,
  156. " cipso_doi=%u cipso_type=%s res=%u",
  157. doi_def->doi, type_str, ret_val == 0 ? 1 : 0);
  158. audit_log_end(audit_buf);
  159. }
  160. cfg_cipsov4_add_map_failure:
  161. if (entry != NULL)
  162. kfree(entry->domain);
  163. kfree(entry);
  164. return ret_val;
  165. }
  166. /*
  167. * Security Attribute Functions
  168. */
  169. /**
  170. * netlbl_secattr_catmap_walk - Walk a LSM secattr catmap looking for a bit
  171. * @catmap: the category bitmap
  172. * @offset: the offset to start searching at, in bits
  173. *
  174. * Description:
  175. * This function walks a LSM secattr category bitmap starting at @offset and
  176. * returns the spot of the first set bit or -ENOENT if no bits are set.
  177. *
  178. */
  179. int netlbl_secattr_catmap_walk(struct netlbl_lsm_secattr_catmap *catmap,
  180. u32 offset)
  181. {
  182. struct netlbl_lsm_secattr_catmap *iter = catmap;
  183. u32 node_idx;
  184. u32 node_bit;
  185. NETLBL_CATMAP_MAPTYPE bitmap;
  186. if (offset > iter->startbit) {
  187. while (offset >= (iter->startbit + NETLBL_CATMAP_SIZE)) {
  188. iter = iter->next;
  189. if (iter == NULL)
  190. return -ENOENT;
  191. }
  192. node_idx = (offset - iter->startbit) / NETLBL_CATMAP_MAPSIZE;
  193. node_bit = offset - iter->startbit -
  194. (NETLBL_CATMAP_MAPSIZE * node_idx);
  195. } else {
  196. node_idx = 0;
  197. node_bit = 0;
  198. }
  199. bitmap = iter->bitmap[node_idx] >> node_bit;
  200. for (;;) {
  201. if (bitmap != 0) {
  202. while ((bitmap & NETLBL_CATMAP_BIT) == 0) {
  203. bitmap >>= 1;
  204. node_bit++;
  205. }
  206. return iter->startbit +
  207. (NETLBL_CATMAP_MAPSIZE * node_idx) + node_bit;
  208. }
  209. if (++node_idx >= NETLBL_CATMAP_MAPCNT) {
  210. if (iter->next != NULL) {
  211. iter = iter->next;
  212. node_idx = 0;
  213. } else
  214. return -ENOENT;
  215. }
  216. bitmap = iter->bitmap[node_idx];
  217. node_bit = 0;
  218. }
  219. return -ENOENT;
  220. }
  221. /**
  222. * netlbl_secattr_catmap_walk_rng - Find the end of a string of set bits
  223. * @catmap: the category bitmap
  224. * @offset: the offset to start searching at, in bits
  225. *
  226. * Description:
  227. * This function walks a LSM secattr category bitmap starting at @offset and
  228. * returns the spot of the first cleared bit or -ENOENT if the offset is past
  229. * the end of the bitmap.
  230. *
  231. */
  232. int netlbl_secattr_catmap_walk_rng(struct netlbl_lsm_secattr_catmap *catmap,
  233. u32 offset)
  234. {
  235. struct netlbl_lsm_secattr_catmap *iter = catmap;
  236. u32 node_idx;
  237. u32 node_bit;
  238. NETLBL_CATMAP_MAPTYPE bitmask;
  239. NETLBL_CATMAP_MAPTYPE bitmap;
  240. if (offset > iter->startbit) {
  241. while (offset >= (iter->startbit + NETLBL_CATMAP_SIZE)) {
  242. iter = iter->next;
  243. if (iter == NULL)
  244. return -ENOENT;
  245. }
  246. node_idx = (offset - iter->startbit) / NETLBL_CATMAP_MAPSIZE;
  247. node_bit = offset - iter->startbit -
  248. (NETLBL_CATMAP_MAPSIZE * node_idx);
  249. } else {
  250. node_idx = 0;
  251. node_bit = 0;
  252. }
  253. bitmask = NETLBL_CATMAP_BIT << node_bit;
  254. for (;;) {
  255. bitmap = iter->bitmap[node_idx];
  256. while (bitmask != 0 && (bitmap & bitmask) != 0) {
  257. bitmask <<= 1;
  258. node_bit++;
  259. }
  260. if (bitmask != 0)
  261. return iter->startbit +
  262. (NETLBL_CATMAP_MAPSIZE * node_idx) +
  263. node_bit - 1;
  264. else if (++node_idx >= NETLBL_CATMAP_MAPCNT) {
  265. if (iter->next == NULL)
  266. return iter->startbit + NETLBL_CATMAP_SIZE - 1;
  267. iter = iter->next;
  268. node_idx = 0;
  269. }
  270. bitmask = NETLBL_CATMAP_BIT;
  271. node_bit = 0;
  272. }
  273. return -ENOENT;
  274. }
  275. /**
  276. * netlbl_secattr_catmap_setbit - Set a bit in a LSM secattr catmap
  277. * @catmap: the category bitmap
  278. * @bit: the bit to set
  279. * @flags: memory allocation flags
  280. *
  281. * Description:
  282. * Set the bit specified by @bit in @catmap. Returns zero on success,
  283. * negative values on failure.
  284. *
  285. */
  286. int netlbl_secattr_catmap_setbit(struct netlbl_lsm_secattr_catmap *catmap,
  287. u32 bit,
  288. gfp_t flags)
  289. {
  290. struct netlbl_lsm_secattr_catmap *iter = catmap;
  291. u32 node_bit;
  292. u32 node_idx;
  293. while (iter->next != NULL &&
  294. bit >= (iter->startbit + NETLBL_CATMAP_SIZE))
  295. iter = iter->next;
  296. if (bit >= (iter->startbit + NETLBL_CATMAP_SIZE)) {
  297. iter->next = netlbl_secattr_catmap_alloc(flags);
  298. if (iter->next == NULL)
  299. return -ENOMEM;
  300. iter = iter->next;
  301. iter->startbit = bit & ~(NETLBL_CATMAP_SIZE - 1);
  302. }
  303. /* gcc always rounds to zero when doing integer division */
  304. node_idx = (bit - iter->startbit) / NETLBL_CATMAP_MAPSIZE;
  305. node_bit = bit - iter->startbit - (NETLBL_CATMAP_MAPSIZE * node_idx);
  306. iter->bitmap[node_idx] |= NETLBL_CATMAP_BIT << node_bit;
  307. return 0;
  308. }
  309. /**
  310. * netlbl_secattr_catmap_setrng - Set a range of bits in a LSM secattr catmap
  311. * @catmap: the category bitmap
  312. * @start: the starting bit
  313. * @end: the last bit in the string
  314. * @flags: memory allocation flags
  315. *
  316. * Description:
  317. * Set a range of bits, starting at @start and ending with @end. Returns zero
  318. * on success, negative values on failure.
  319. *
  320. */
  321. int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap *catmap,
  322. u32 start,
  323. u32 end,
  324. gfp_t flags)
  325. {
  326. int ret_val = 0;
  327. struct netlbl_lsm_secattr_catmap *iter = catmap;
  328. u32 iter_max_spot;
  329. u32 spot;
  330. /* XXX - This could probably be made a bit faster by combining writes
  331. * to the catmap instead of setting a single bit each time, but for
  332. * right now skipping to the start of the range in the catmap should
  333. * be a nice improvement over calling the individual setbit function
  334. * repeatedly from a loop. */
  335. while (iter->next != NULL &&
  336. start >= (iter->startbit + NETLBL_CATMAP_SIZE))
  337. iter = iter->next;
  338. iter_max_spot = iter->startbit + NETLBL_CATMAP_SIZE;
  339. for (spot = start; spot <= end && ret_val == 0; spot++) {
  340. if (spot >= iter_max_spot && iter->next != NULL) {
  341. iter = iter->next;
  342. iter_max_spot = iter->startbit + NETLBL_CATMAP_SIZE;
  343. }
  344. ret_val = netlbl_secattr_catmap_setbit(iter, spot, GFP_ATOMIC);
  345. }
  346. return ret_val;
  347. }
  348. /*
  349. * LSM Functions
  350. */
  351. /**
  352. * netlbl_enabled - Determine if the NetLabel subsystem is enabled
  353. *
  354. * Description:
  355. * The LSM can use this function to determine if it should use NetLabel
  356. * security attributes in it's enforcement mechanism. Currently, NetLabel is
  357. * considered to be enabled when it's configuration contains a valid setup for
  358. * at least one labeled protocol (i.e. NetLabel can understand incoming
  359. * labeled packets of at least one type); otherwise NetLabel is considered to
  360. * be disabled.
  361. *
  362. */
  363. int netlbl_enabled(void)
  364. {
  365. /* At some point we probably want to expose this mechanism to the user
  366. * as well so that admins can toggle NetLabel regardless of the
  367. * configuration */
  368. return (atomic_read(&netlabel_mgmt_protocount) > 0);
  369. }
  370. /**
  371. * netlbl_socket_setattr - Label a socket using the correct protocol
  372. * @sk: the socket to label
  373. * @secattr: the security attributes
  374. *
  375. * Description:
  376. * Attach the correct label to the given socket using the security attributes
  377. * specified in @secattr. This function requires exclusive access to @sk,
  378. * which means it either needs to be in the process of being created or locked.
  379. * Returns zero on success, negative values on failure.
  380. *
  381. */
  382. int netlbl_sock_setattr(struct sock *sk,
  383. const struct netlbl_lsm_secattr *secattr)
  384. {
  385. int ret_val = -ENOENT;
  386. struct netlbl_dom_map *dom_entry;
  387. rcu_read_lock();
  388. dom_entry = netlbl_domhsh_getentry(secattr->domain);
  389. if (dom_entry == NULL)
  390. goto socket_setattr_return;
  391. switch (dom_entry->type) {
  392. case NETLBL_NLTYPE_CIPSOV4:
  393. ret_val = cipso_v4_sock_setattr(sk,
  394. dom_entry->type_def.cipsov4,
  395. secattr);
  396. break;
  397. case NETLBL_NLTYPE_UNLABELED:
  398. ret_val = 0;
  399. break;
  400. default:
  401. ret_val = -ENOENT;
  402. }
  403. socket_setattr_return:
  404. rcu_read_unlock();
  405. return ret_val;
  406. }
  407. /**
  408. * netlbl_sock_getattr - Determine the security attributes of a sock
  409. * @sk: the sock
  410. * @secattr: the security attributes
  411. *
  412. * Description:
  413. * Examines the given sock to see if any NetLabel style labeling has been
  414. * applied to the sock, if so it parses the socket label and returns the
  415. * security attributes in @secattr. Returns zero on success, negative values
  416. * on failure.
  417. *
  418. */
  419. int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
  420. {
  421. return cipso_v4_sock_getattr(sk, secattr);
  422. }
  423. /**
  424. * netlbl_skbuff_getattr - Determine the security attributes of a packet
  425. * @skb: the packet
  426. * @family: protocol family
  427. * @secattr: the security attributes
  428. *
  429. * Description:
  430. * Examines the given packet to see if a recognized form of packet labeling
  431. * is present, if so it parses the packet label and returns the security
  432. * attributes in @secattr. Returns zero on success, negative values on
  433. * failure.
  434. *
  435. */
  436. int netlbl_skbuff_getattr(const struct sk_buff *skb,
  437. u16 family,
  438. struct netlbl_lsm_secattr *secattr)
  439. {
  440. if (CIPSO_V4_OPTEXIST(skb) &&
  441. cipso_v4_skbuff_getattr(skb, secattr) == 0)
  442. return 0;
  443. return netlbl_unlabel_getattr(skb, family, secattr);
  444. }
  445. /**
  446. * netlbl_skbuff_err - Handle a LSM error on a sk_buff
  447. * @skb: the packet
  448. * @error: the error code
  449. * @gateway: true if host is acting as a gateway, false otherwise
  450. *
  451. * Description:
  452. * Deal with a LSM problem when handling the packet in @skb, typically this is
  453. * a permission denied problem (-EACCES). The correct action is determined
  454. * according to the packet's labeling protocol.
  455. *
  456. */
  457. void netlbl_skbuff_err(struct sk_buff *skb, int error, int gateway)
  458. {
  459. if (CIPSO_V4_OPTEXIST(skb))
  460. cipso_v4_error(skb, error, gateway);
  461. }
  462. /**
  463. * netlbl_cache_invalidate - Invalidate all of the NetLabel protocol caches
  464. *
  465. * Description:
  466. * For all of the NetLabel protocols that support some form of label mapping
  467. * cache, invalidate the cache. Returns zero on success, negative values on
  468. * error.
  469. *
  470. */
  471. void netlbl_cache_invalidate(void)
  472. {
  473. cipso_v4_cache_invalidate();
  474. }
  475. /**
  476. * netlbl_cache_add - Add an entry to a NetLabel protocol cache
  477. * @skb: the packet
  478. * @secattr: the packet's security attributes
  479. *
  480. * Description:
  481. * Add the LSM security attributes for the given packet to the underlying
  482. * NetLabel protocol's label mapping cache. Returns zero on success, negative
  483. * values on error.
  484. *
  485. */
  486. int netlbl_cache_add(const struct sk_buff *skb,
  487. const struct netlbl_lsm_secattr *secattr)
  488. {
  489. if ((secattr->flags & NETLBL_SECATTR_CACHE) == 0)
  490. return -ENOMSG;
  491. if (CIPSO_V4_OPTEXIST(skb))
  492. return cipso_v4_cache_add(skb, secattr);
  493. return -ENOMSG;
  494. }
  495. /*
  496. * Setup Functions
  497. */
  498. /**
  499. * netlbl_init - Initialize NetLabel
  500. *
  501. * Description:
  502. * Perform the required NetLabel initialization before first use.
  503. *
  504. */
  505. static int __init netlbl_init(void)
  506. {
  507. int ret_val;
  508. printk(KERN_INFO "NetLabel: Initializing\n");
  509. printk(KERN_INFO "NetLabel: domain hash size = %u\n",
  510. (1 << NETLBL_DOMHSH_BITSIZE));
  511. printk(KERN_INFO "NetLabel: protocols ="
  512. " UNLABELED"
  513. " CIPSOv4"
  514. "\n");
  515. ret_val = netlbl_domhsh_init(NETLBL_DOMHSH_BITSIZE);
  516. if (ret_val != 0)
  517. goto init_failure;
  518. ret_val = netlbl_unlabel_init(NETLBL_UNLHSH_BITSIZE);
  519. if (ret_val != 0)
  520. goto init_failure;
  521. ret_val = netlbl_netlink_init();
  522. if (ret_val != 0)
  523. goto init_failure;
  524. ret_val = netlbl_unlabel_defconf();
  525. if (ret_val != 0)
  526. goto init_failure;
  527. printk(KERN_INFO "NetLabel: unlabeled traffic allowed by default\n");
  528. return 0;
  529. init_failure:
  530. panic("NetLabel: failed to initialize properly (%d)\n", ret_val);
  531. }
  532. subsys_initcall(netlbl_init);