cipso_ipv4.c 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470
  1. /*
  2. * CIPSO - Commercial IP Security Option
  3. *
  4. * This is an implementation of the CIPSO 2.2 protocol as specified in
  5. * draft-ietf-cipso-ipsecurity-01.txt with additional tag types as found in
  6. * FIPS-188, copies of both documents can be found in the Documentation
  7. * directory. While CIPSO never became a full IETF RFC standard many vendors
  8. * have chosen to adopt the protocol and over the years it has become a
  9. * de-facto standard for labeled networking.
  10. *
  11. * Author: Paul Moore <paul.moore@hp.com>
  12. *
  13. */
  14. /*
  15. * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
  16. *
  17. * This program is free software; you can redistribute it and/or modify
  18. * it under the terms of the GNU General Public License as published by
  19. * the Free Software Foundation; either version 2 of the License, or
  20. * (at your option) any later version.
  21. *
  22. * This program is distributed in the hope that it will be useful,
  23. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  24. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
  25. * the GNU General Public License for more details.
  26. *
  27. * You should have received a copy of the GNU General Public License
  28. * along with this program; if not, write to the Free Software
  29. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  30. *
  31. */
  32. #include <linux/init.h>
  33. #include <linux/types.h>
  34. #include <linux/rcupdate.h>
  35. #include <linux/list.h>
  36. #include <linux/spinlock.h>
  37. #include <linux/string.h>
  38. #include <linux/jhash.h>
  39. #include <net/ip.h>
  40. #include <net/icmp.h>
  41. #include <net/tcp.h>
  42. #include <net/netlabel.h>
  43. #include <net/cipso_ipv4.h>
  44. #include <asm/bug.h>
  45. struct cipso_v4_domhsh_entry {
  46. char *domain;
  47. u32 valid;
  48. struct list_head list;
  49. struct rcu_head rcu;
  50. };
  51. /* List of available DOI definitions */
  52. /* XXX - Updates should be minimal so having a single lock for the
  53. * cipso_v4_doi_list and the cipso_v4_doi_list->dom_list should be
  54. * okay. */
  55. /* XXX - This currently assumes a minimal number of different DOIs in use,
  56. * if in practice there are a lot of different DOIs this list should
  57. * probably be turned into a hash table or something similar so we
  58. * can do quick lookups. */
  59. static DEFINE_SPINLOCK(cipso_v4_doi_list_lock);
  60. static struct list_head cipso_v4_doi_list = LIST_HEAD_INIT(cipso_v4_doi_list);
  61. /* Label mapping cache */
  62. int cipso_v4_cache_enabled = 1;
  63. int cipso_v4_cache_bucketsize = 10;
  64. #define CIPSO_V4_CACHE_BUCKETBITS 7
  65. #define CIPSO_V4_CACHE_BUCKETS (1 << CIPSO_V4_CACHE_BUCKETBITS)
  66. #define CIPSO_V4_CACHE_REORDERLIMIT 10
  67. struct cipso_v4_map_cache_bkt {
  68. spinlock_t lock;
  69. u32 size;
  70. struct list_head list;
  71. };
  72. struct cipso_v4_map_cache_entry {
  73. u32 hash;
  74. unsigned char *key;
  75. size_t key_len;
  76. struct netlbl_lsm_cache lsm_data;
  77. u32 activity;
  78. struct list_head list;
  79. };
  80. static struct cipso_v4_map_cache_bkt *cipso_v4_cache = NULL;
  81. /* Restricted bitmap (tag #1) flags */
  82. int cipso_v4_rbm_optfmt = 0;
  83. int cipso_v4_rbm_strictvalid = 1;
  84. /*
  85. * Helper Functions
  86. */
  87. /**
  88. * cipso_v4_bitmap_walk - Walk a bitmap looking for a bit
  89. * @bitmap: the bitmap
  90. * @bitmap_len: length in bits
  91. * @offset: starting offset
  92. * @state: if non-zero, look for a set (1) bit else look for a cleared (0) bit
  93. *
  94. * Description:
  95. * Starting at @offset, walk the bitmap from left to right until either the
  96. * desired bit is found or we reach the end. Return the bit offset, -1 if
  97. * not found, or -2 if error.
  98. */
  99. static int cipso_v4_bitmap_walk(const unsigned char *bitmap,
  100. u32 bitmap_len,
  101. u32 offset,
  102. u8 state)
  103. {
  104. u32 bit_spot;
  105. u32 byte_offset;
  106. unsigned char bitmask;
  107. unsigned char byte;
  108. /* gcc always rounds to zero when doing integer division */
  109. byte_offset = offset / 8;
  110. byte = bitmap[byte_offset];
  111. bit_spot = offset;
  112. bitmask = 0x80 >> (offset % 8);
  113. while (bit_spot < bitmap_len) {
  114. if ((state && (byte & bitmask) == bitmask) ||
  115. (state == 0 && (byte & bitmask) == 0))
  116. return bit_spot;
  117. bit_spot++;
  118. bitmask >>= 1;
  119. if (bitmask == 0) {
  120. byte = bitmap[++byte_offset];
  121. bitmask = 0x80;
  122. }
  123. }
  124. return -1;
  125. }
  126. /**
  127. * cipso_v4_bitmap_setbit - Sets a single bit in a bitmap
  128. * @bitmap: the bitmap
  129. * @bit: the bit
  130. * @state: if non-zero, set the bit (1) else clear the bit (0)
  131. *
  132. * Description:
  133. * Set a single bit in the bitmask. Returns zero on success, negative values
  134. * on error.
  135. */
  136. static void cipso_v4_bitmap_setbit(unsigned char *bitmap,
  137. u32 bit,
  138. u8 state)
  139. {
  140. u32 byte_spot;
  141. u8 bitmask;
  142. /* gcc always rounds to zero when doing integer division */
  143. byte_spot = bit / 8;
  144. bitmask = 0x80 >> (bit % 8);
  145. if (state)
  146. bitmap[byte_spot] |= bitmask;
  147. else
  148. bitmap[byte_spot] &= ~bitmask;
  149. }
  150. /**
  151. * cipso_v4_doi_domhsh_free - Frees a domain list entry
  152. * @entry: the entry's RCU field
  153. *
  154. * Description:
  155. * This function is designed to be used as a callback to the call_rcu()
  156. * function so that the memory allocated to a domain list entry can be released
  157. * safely.
  158. *
  159. */
  160. static void cipso_v4_doi_domhsh_free(struct rcu_head *entry)
  161. {
  162. struct cipso_v4_domhsh_entry *ptr;
  163. ptr = container_of(entry, struct cipso_v4_domhsh_entry, rcu);
  164. kfree(ptr->domain);
  165. kfree(ptr);
  166. }
  167. /**
  168. * cipso_v4_cache_entry_free - Frees a cache entry
  169. * @entry: the entry to free
  170. *
  171. * Description:
  172. * This function frees the memory associated with a cache entry.
  173. *
  174. */
  175. static void cipso_v4_cache_entry_free(struct cipso_v4_map_cache_entry *entry)
  176. {
  177. if (entry->lsm_data.free)
  178. entry->lsm_data.free(entry->lsm_data.data);
  179. kfree(entry->key);
  180. kfree(entry);
  181. }
  182. /**
  183. * cipso_v4_map_cache_hash - Hashing function for the CIPSO cache
  184. * @key: the hash key
  185. * @key_len: the length of the key in bytes
  186. *
  187. * Description:
  188. * The CIPSO tag hashing function. Returns a 32-bit hash value.
  189. *
  190. */
  191. static u32 cipso_v4_map_cache_hash(const unsigned char *key, u32 key_len)
  192. {
  193. return jhash(key, key_len, 0);
  194. }
  195. /*
  196. * Label Mapping Cache Functions
  197. */
  198. /**
  199. * cipso_v4_cache_init - Initialize the CIPSO cache
  200. *
  201. * Description:
  202. * Initializes the CIPSO label mapping cache, this function should be called
  203. * before any of the other functions defined in this file. Returns zero on
  204. * success, negative values on error.
  205. *
  206. */
  207. static int cipso_v4_cache_init(void)
  208. {
  209. u32 iter;
  210. cipso_v4_cache = kcalloc(CIPSO_V4_CACHE_BUCKETS,
  211. sizeof(struct cipso_v4_map_cache_bkt),
  212. GFP_KERNEL);
  213. if (cipso_v4_cache == NULL)
  214. return -ENOMEM;
  215. for (iter = 0; iter < CIPSO_V4_CACHE_BUCKETS; iter++) {
  216. spin_lock_init(&cipso_v4_cache[iter].lock);
  217. cipso_v4_cache[iter].size = 0;
  218. INIT_LIST_HEAD(&cipso_v4_cache[iter].list);
  219. }
  220. return 0;
  221. }
  222. /**
  223. * cipso_v4_cache_invalidate - Invalidates the current CIPSO cache
  224. *
  225. * Description:
  226. * Invalidates and frees any entries in the CIPSO cache. Returns zero on
  227. * success and negative values on failure.
  228. *
  229. */
  230. void cipso_v4_cache_invalidate(void)
  231. {
  232. struct cipso_v4_map_cache_entry *entry, *tmp_entry;
  233. u32 iter;
  234. for (iter = 0; iter < CIPSO_V4_CACHE_BUCKETS; iter++) {
  235. spin_lock_bh(&cipso_v4_cache[iter].lock);
  236. list_for_each_entry_safe(entry,
  237. tmp_entry,
  238. &cipso_v4_cache[iter].list, list) {
  239. list_del(&entry->list);
  240. cipso_v4_cache_entry_free(entry);
  241. }
  242. cipso_v4_cache[iter].size = 0;
  243. spin_unlock_bh(&cipso_v4_cache[iter].lock);
  244. }
  245. return;
  246. }
  247. /**
  248. * cipso_v4_cache_check - Check the CIPSO cache for a label mapping
  249. * @key: the buffer to check
  250. * @key_len: buffer length in bytes
  251. * @secattr: the security attribute struct to use
  252. *
  253. * Description:
  254. * This function checks the cache to see if a label mapping already exists for
  255. * the given key. If there is a match then the cache is adjusted and the
  256. * @secattr struct is populated with the correct LSM security attributes. The
  257. * cache is adjusted in the following manner if the entry is not already the
  258. * first in the cache bucket:
  259. *
  260. * 1. The cache entry's activity counter is incremented
  261. * 2. The previous (higher ranking) entry's activity counter is decremented
  262. * 3. If the difference between the two activity counters is geater than
  263. * CIPSO_V4_CACHE_REORDERLIMIT the two entries are swapped
  264. *
  265. * Returns zero on success, -ENOENT for a cache miss, and other negative values
  266. * on error.
  267. *
  268. */
  269. static int cipso_v4_cache_check(const unsigned char *key,
  270. u32 key_len,
  271. struct netlbl_lsm_secattr *secattr)
  272. {
  273. u32 bkt;
  274. struct cipso_v4_map_cache_entry *entry;
  275. struct cipso_v4_map_cache_entry *prev_entry = NULL;
  276. u32 hash;
  277. if (!cipso_v4_cache_enabled)
  278. return -ENOENT;
  279. hash = cipso_v4_map_cache_hash(key, key_len);
  280. bkt = hash & (CIPSO_V4_CACHE_BUCKETBITS - 1);
  281. spin_lock_bh(&cipso_v4_cache[bkt].lock);
  282. list_for_each_entry(entry, &cipso_v4_cache[bkt].list, list) {
  283. if (entry->hash == hash &&
  284. entry->key_len == key_len &&
  285. memcmp(entry->key, key, key_len) == 0) {
  286. entry->activity += 1;
  287. secattr->cache.free = entry->lsm_data.free;
  288. secattr->cache.data = entry->lsm_data.data;
  289. if (prev_entry == NULL) {
  290. spin_unlock_bh(&cipso_v4_cache[bkt].lock);
  291. return 0;
  292. }
  293. if (prev_entry->activity > 0)
  294. prev_entry->activity -= 1;
  295. if (entry->activity > prev_entry->activity &&
  296. entry->activity - prev_entry->activity >
  297. CIPSO_V4_CACHE_REORDERLIMIT) {
  298. __list_del(entry->list.prev, entry->list.next);
  299. __list_add(&entry->list,
  300. prev_entry->list.prev,
  301. &prev_entry->list);
  302. }
  303. spin_unlock_bh(&cipso_v4_cache[bkt].lock);
  304. return 0;
  305. }
  306. prev_entry = entry;
  307. }
  308. spin_unlock_bh(&cipso_v4_cache[bkt].lock);
  309. return -ENOENT;
  310. }
  311. /**
  312. * cipso_v4_cache_add - Add an entry to the CIPSO cache
  313. * @skb: the packet
  314. * @secattr: the packet's security attributes
  315. *
  316. * Description:
  317. * Add a new entry into the CIPSO label mapping cache. Add the new entry to
  318. * head of the cache bucket's list, if the cache bucket is out of room remove
  319. * the last entry in the list first. It is important to note that there is
  320. * currently no checking for duplicate keys. Returns zero on success,
  321. * negative values on failure.
  322. *
  323. */
  324. int cipso_v4_cache_add(const struct sk_buff *skb,
  325. const struct netlbl_lsm_secattr *secattr)
  326. {
  327. int ret_val = -EPERM;
  328. u32 bkt;
  329. struct cipso_v4_map_cache_entry *entry = NULL;
  330. struct cipso_v4_map_cache_entry *old_entry = NULL;
  331. unsigned char *cipso_ptr;
  332. u32 cipso_ptr_len;
  333. if (!cipso_v4_cache_enabled || cipso_v4_cache_bucketsize <= 0)
  334. return 0;
  335. cipso_ptr = CIPSO_V4_OPTPTR(skb);
  336. cipso_ptr_len = cipso_ptr[1];
  337. entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
  338. if (entry == NULL)
  339. return -ENOMEM;
  340. entry->key = kmalloc(cipso_ptr_len, GFP_ATOMIC);
  341. if (entry->key == NULL) {
  342. ret_val = -ENOMEM;
  343. goto cache_add_failure;
  344. }
  345. memcpy(entry->key, cipso_ptr, cipso_ptr_len);
  346. entry->key_len = cipso_ptr_len;
  347. entry->hash = cipso_v4_map_cache_hash(cipso_ptr, cipso_ptr_len);
  348. entry->lsm_data.free = secattr->cache.free;
  349. entry->lsm_data.data = secattr->cache.data;
  350. bkt = entry->hash & (CIPSO_V4_CACHE_BUCKETBITS - 1);
  351. spin_lock_bh(&cipso_v4_cache[bkt].lock);
  352. if (cipso_v4_cache[bkt].size < cipso_v4_cache_bucketsize) {
  353. list_add(&entry->list, &cipso_v4_cache[bkt].list);
  354. cipso_v4_cache[bkt].size += 1;
  355. } else {
  356. old_entry = list_entry(cipso_v4_cache[bkt].list.prev,
  357. struct cipso_v4_map_cache_entry, list);
  358. list_del(&old_entry->list);
  359. list_add(&entry->list, &cipso_v4_cache[bkt].list);
  360. cipso_v4_cache_entry_free(old_entry);
  361. }
  362. spin_unlock_bh(&cipso_v4_cache[bkt].lock);
  363. return 0;
  364. cache_add_failure:
  365. if (entry)
  366. cipso_v4_cache_entry_free(entry);
  367. return ret_val;
  368. }
  369. /*
  370. * DOI List Functions
  371. */
  372. /**
  373. * cipso_v4_doi_search - Searches for a DOI definition
  374. * @doi: the DOI to search for
  375. *
  376. * Description:
  377. * Search the DOI definition list for a DOI definition with a DOI value that
  378. * matches @doi. The caller is responsibile for calling rcu_read_[un]lock().
  379. * Returns a pointer to the DOI definition on success and NULL on failure.
  380. */
  381. static struct cipso_v4_doi *cipso_v4_doi_search(u32 doi)
  382. {
  383. struct cipso_v4_doi *iter;
  384. list_for_each_entry_rcu(iter, &cipso_v4_doi_list, list)
  385. if (iter->doi == doi && iter->valid)
  386. return iter;
  387. return NULL;
  388. }
  389. /**
  390. * cipso_v4_doi_add - Add a new DOI to the CIPSO protocol engine
  391. * @doi_def: the DOI structure
  392. *
  393. * Description:
  394. * The caller defines a new DOI for use by the CIPSO engine and calls this
  395. * function to add it to the list of acceptable domains. The caller must
  396. * ensure that the mapping table specified in @doi_def->map meets all of the
  397. * requirements of the mapping type (see cipso_ipv4.h for details). Returns
  398. * zero on success and non-zero on failure.
  399. *
  400. */
  401. int cipso_v4_doi_add(struct cipso_v4_doi *doi_def)
  402. {
  403. if (doi_def == NULL || doi_def->doi == CIPSO_V4_DOI_UNKNOWN)
  404. return -EINVAL;
  405. doi_def->valid = 1;
  406. INIT_RCU_HEAD(&doi_def->rcu);
  407. INIT_LIST_HEAD(&doi_def->dom_list);
  408. rcu_read_lock();
  409. if (cipso_v4_doi_search(doi_def->doi) != NULL)
  410. goto doi_add_failure_rlock;
  411. spin_lock(&cipso_v4_doi_list_lock);
  412. if (cipso_v4_doi_search(doi_def->doi) != NULL)
  413. goto doi_add_failure_slock;
  414. list_add_tail_rcu(&doi_def->list, &cipso_v4_doi_list);
  415. spin_unlock(&cipso_v4_doi_list_lock);
  416. rcu_read_unlock();
  417. return 0;
  418. doi_add_failure_slock:
  419. spin_unlock(&cipso_v4_doi_list_lock);
  420. doi_add_failure_rlock:
  421. rcu_read_unlock();
  422. return -EEXIST;
  423. }
  424. /**
  425. * cipso_v4_doi_remove - Remove an existing DOI from the CIPSO protocol engine
  426. * @doi: the DOI value
  427. * @callback: the DOI cleanup/free callback
  428. *
  429. * Description:
  430. * Removes a DOI definition from the CIPSO engine, @callback is called to
  431. * free any memory. The NetLabel routines will be called to release their own
  432. * LSM domain mappings as well as our own domain list. Returns zero on
  433. * success and negative values on failure.
  434. *
  435. */
  436. int cipso_v4_doi_remove(u32 doi, void (*callback) (struct rcu_head * head))
  437. {
  438. struct cipso_v4_doi *doi_def;
  439. struct cipso_v4_domhsh_entry *dom_iter;
  440. rcu_read_lock();
  441. if (cipso_v4_doi_search(doi) != NULL) {
  442. spin_lock(&cipso_v4_doi_list_lock);
  443. doi_def = cipso_v4_doi_search(doi);
  444. if (doi_def == NULL) {
  445. spin_unlock(&cipso_v4_doi_list_lock);
  446. rcu_read_unlock();
  447. return -ENOENT;
  448. }
  449. doi_def->valid = 0;
  450. list_del_rcu(&doi_def->list);
  451. spin_unlock(&cipso_v4_doi_list_lock);
  452. list_for_each_entry_rcu(dom_iter, &doi_def->dom_list, list)
  453. if (dom_iter->valid)
  454. netlbl_domhsh_remove(dom_iter->domain);
  455. cipso_v4_cache_invalidate();
  456. rcu_read_unlock();
  457. call_rcu(&doi_def->rcu, callback);
  458. return 0;
  459. }
  460. rcu_read_unlock();
  461. return -ENOENT;
  462. }
  463. /**
  464. * cipso_v4_doi_getdef - Returns a pointer to a valid DOI definition
  465. * @doi: the DOI value
  466. *
  467. * Description:
  468. * Searches for a valid DOI definition and if one is found it is returned to
  469. * the caller. Otherwise NULL is returned. The caller must ensure that
  470. * rcu_read_lock() is held while accessing the returned definition.
  471. *
  472. */
  473. struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi)
  474. {
  475. return cipso_v4_doi_search(doi);
  476. }
  477. /**
  478. * cipso_v4_doi_walk - Iterate through the DOI definitions
  479. * @skip_cnt: skip past this number of DOI definitions, updated
  480. * @callback: callback for each DOI definition
  481. * @cb_arg: argument for the callback function
  482. *
  483. * Description:
  484. * Iterate over the DOI definition list, skipping the first @skip_cnt entries.
  485. * For each entry call @callback, if @callback returns a negative value stop
  486. * 'walking' through the list and return. Updates the value in @skip_cnt upon
  487. * return. Returns zero on success, negative values on failure.
  488. *
  489. */
  490. int cipso_v4_doi_walk(u32 *skip_cnt,
  491. int (*callback) (struct cipso_v4_doi *doi_def, void *arg),
  492. void *cb_arg)
  493. {
  494. int ret_val = -ENOENT;
  495. u32 doi_cnt = 0;
  496. struct cipso_v4_doi *iter_doi;
  497. rcu_read_lock();
  498. list_for_each_entry_rcu(iter_doi, &cipso_v4_doi_list, list)
  499. if (iter_doi->valid) {
  500. if (doi_cnt++ < *skip_cnt)
  501. continue;
  502. ret_val = callback(iter_doi, cb_arg);
  503. if (ret_val < 0) {
  504. doi_cnt--;
  505. goto doi_walk_return;
  506. }
  507. }
  508. doi_walk_return:
  509. rcu_read_unlock();
  510. *skip_cnt = doi_cnt;
  511. return ret_val;
  512. }
  513. /**
  514. * cipso_v4_doi_domhsh_add - Adds a domain entry to a DOI definition
  515. * @doi_def: the DOI definition
  516. * @domain: the domain to add
  517. *
  518. * Description:
  519. * Adds the @domain to the the DOI specified by @doi_def, this function
  520. * should only be called by external functions (i.e. NetLabel). This function
  521. * does allocate memory. Returns zero on success, negative values on failure.
  522. *
  523. */
  524. int cipso_v4_doi_domhsh_add(struct cipso_v4_doi *doi_def, const char *domain)
  525. {
  526. struct cipso_v4_domhsh_entry *iter;
  527. struct cipso_v4_domhsh_entry *new_dom;
  528. new_dom = kzalloc(sizeof(*new_dom), GFP_KERNEL);
  529. if (new_dom == NULL)
  530. return -ENOMEM;
  531. if (domain) {
  532. new_dom->domain = kstrdup(domain, GFP_KERNEL);
  533. if (new_dom->domain == NULL) {
  534. kfree(new_dom);
  535. return -ENOMEM;
  536. }
  537. }
  538. new_dom->valid = 1;
  539. INIT_RCU_HEAD(&new_dom->rcu);
  540. rcu_read_lock();
  541. spin_lock(&cipso_v4_doi_list_lock);
  542. list_for_each_entry_rcu(iter, &doi_def->dom_list, list)
  543. if (iter->valid &&
  544. ((domain != NULL && iter->domain != NULL &&
  545. strcmp(iter->domain, domain) == 0) ||
  546. (domain == NULL && iter->domain == NULL))) {
  547. spin_unlock(&cipso_v4_doi_list_lock);
  548. rcu_read_unlock();
  549. kfree(new_dom->domain);
  550. kfree(new_dom);
  551. return -EEXIST;
  552. }
  553. list_add_tail_rcu(&new_dom->list, &doi_def->dom_list);
  554. spin_unlock(&cipso_v4_doi_list_lock);
  555. rcu_read_unlock();
  556. return 0;
  557. }
  558. /**
  559. * cipso_v4_doi_domhsh_remove - Removes a domain entry from a DOI definition
  560. * @doi_def: the DOI definition
  561. * @domain: the domain to remove
  562. *
  563. * Description:
  564. * Removes the @domain from the DOI specified by @doi_def, this function
  565. * should only be called by external functions (i.e. NetLabel). Returns zero
  566. * on success and negative values on error.
  567. *
  568. */
  569. int cipso_v4_doi_domhsh_remove(struct cipso_v4_doi *doi_def,
  570. const char *domain)
  571. {
  572. struct cipso_v4_domhsh_entry *iter;
  573. rcu_read_lock();
  574. spin_lock(&cipso_v4_doi_list_lock);
  575. list_for_each_entry_rcu(iter, &doi_def->dom_list, list)
  576. if (iter->valid &&
  577. ((domain != NULL && iter->domain != NULL &&
  578. strcmp(iter->domain, domain) == 0) ||
  579. (domain == NULL && iter->domain == NULL))) {
  580. iter->valid = 0;
  581. list_del_rcu(&iter->list);
  582. spin_unlock(&cipso_v4_doi_list_lock);
  583. rcu_read_unlock();
  584. call_rcu(&iter->rcu, cipso_v4_doi_domhsh_free);
  585. return 0;
  586. }
  587. spin_unlock(&cipso_v4_doi_list_lock);
  588. rcu_read_unlock();
  589. return -ENOENT;
  590. }
  591. /*
  592. * Label Mapping Functions
  593. */
  594. /**
  595. * cipso_v4_map_lvl_valid - Checks to see if the given level is understood
  596. * @doi_def: the DOI definition
  597. * @level: the level to check
  598. *
  599. * Description:
  600. * Checks the given level against the given DOI definition and returns a
  601. * negative value if the level does not have a valid mapping and a zero value
  602. * if the level is defined by the DOI.
  603. *
  604. */
  605. static int cipso_v4_map_lvl_valid(const struct cipso_v4_doi *doi_def, u8 level)
  606. {
  607. switch (doi_def->type) {
  608. case CIPSO_V4_MAP_PASS:
  609. return 0;
  610. case CIPSO_V4_MAP_STD:
  611. if (doi_def->map.std->lvl.cipso[level] < CIPSO_V4_INV_LVL)
  612. return 0;
  613. break;
  614. }
  615. return -EFAULT;
  616. }
  617. /**
  618. * cipso_v4_map_lvl_hton - Perform a level mapping from the host to the network
  619. * @doi_def: the DOI definition
  620. * @host_lvl: the host MLS level
  621. * @net_lvl: the network/CIPSO MLS level
  622. *
  623. * Description:
  624. * Perform a label mapping to translate a local MLS level to the correct
  625. * CIPSO level using the given DOI definition. Returns zero on success,
  626. * negative values otherwise.
  627. *
  628. */
  629. static int cipso_v4_map_lvl_hton(const struct cipso_v4_doi *doi_def,
  630. u32 host_lvl,
  631. u32 *net_lvl)
  632. {
  633. switch (doi_def->type) {
  634. case CIPSO_V4_MAP_PASS:
  635. *net_lvl = host_lvl;
  636. return 0;
  637. case CIPSO_V4_MAP_STD:
  638. if (host_lvl < doi_def->map.std->lvl.local_size) {
  639. *net_lvl = doi_def->map.std->lvl.local[host_lvl];
  640. return 0;
  641. }
  642. break;
  643. }
  644. return -EINVAL;
  645. }
  646. /**
  647. * cipso_v4_map_lvl_ntoh - Perform a level mapping from the network to the host
  648. * @doi_def: the DOI definition
  649. * @net_lvl: the network/CIPSO MLS level
  650. * @host_lvl: the host MLS level
  651. *
  652. * Description:
  653. * Perform a label mapping to translate a CIPSO level to the correct local MLS
  654. * level using the given DOI definition. Returns zero on success, negative
  655. * values otherwise.
  656. *
  657. */
  658. static int cipso_v4_map_lvl_ntoh(const struct cipso_v4_doi *doi_def,
  659. u32 net_lvl,
  660. u32 *host_lvl)
  661. {
  662. struct cipso_v4_std_map_tbl *map_tbl;
  663. switch (doi_def->type) {
  664. case CIPSO_V4_MAP_PASS:
  665. *host_lvl = net_lvl;
  666. return 0;
  667. case CIPSO_V4_MAP_STD:
  668. map_tbl = doi_def->map.std;
  669. if (net_lvl < map_tbl->lvl.cipso_size &&
  670. map_tbl->lvl.cipso[net_lvl] < CIPSO_V4_INV_LVL) {
  671. *host_lvl = doi_def->map.std->lvl.cipso[net_lvl];
  672. return 0;
  673. }
  674. break;
  675. }
  676. return -EINVAL;
  677. }
  678. /**
  679. * cipso_v4_map_cat_rbm_valid - Checks to see if the category bitmap is valid
  680. * @doi_def: the DOI definition
  681. * @bitmap: category bitmap
  682. * @bitmap_len: bitmap length in bytes
  683. *
  684. * Description:
  685. * Checks the given category bitmap against the given DOI definition and
  686. * returns a negative value if any of the categories in the bitmap do not have
  687. * a valid mapping and a zero value if all of the categories are valid.
  688. *
  689. */
  690. static int cipso_v4_map_cat_rbm_valid(const struct cipso_v4_doi *doi_def,
  691. const unsigned char *bitmap,
  692. u32 bitmap_len)
  693. {
  694. int cat = -1;
  695. u32 bitmap_len_bits = bitmap_len * 8;
  696. u32 cipso_cat_size = doi_def->map.std->cat.cipso_size;
  697. u32 *cipso_array = doi_def->map.std->cat.cipso;
  698. switch (doi_def->type) {
  699. case CIPSO_V4_MAP_PASS:
  700. return 0;
  701. case CIPSO_V4_MAP_STD:
  702. for (;;) {
  703. cat = cipso_v4_bitmap_walk(bitmap,
  704. bitmap_len_bits,
  705. cat + 1,
  706. 1);
  707. if (cat < 0)
  708. break;
  709. if (cat >= cipso_cat_size ||
  710. cipso_array[cat] >= CIPSO_V4_INV_CAT)
  711. return -EFAULT;
  712. }
  713. if (cat == -1)
  714. return 0;
  715. break;
  716. }
  717. return -EFAULT;
  718. }
  719. /**
  720. * cipso_v4_map_cat_rbm_hton - Perform a category mapping from host to network
  721. * @doi_def: the DOI definition
  722. * @host_cat: the category bitmap in host format
  723. * @host_cat_len: the length of the host's category bitmap in bytes
  724. * @net_cat: the zero'd out category bitmap in network/CIPSO format
  725. * @net_cat_len: the length of the CIPSO bitmap in bytes
  726. *
  727. * Description:
  728. * Perform a label mapping to translate a local MLS category bitmap to the
  729. * correct CIPSO bitmap using the given DOI definition. Returns the minimum
  730. * size in bytes of the network bitmap on success, negative values otherwise.
  731. *
  732. */
  733. static int cipso_v4_map_cat_rbm_hton(const struct cipso_v4_doi *doi_def,
  734. const unsigned char *host_cat,
  735. u32 host_cat_len,
  736. unsigned char *net_cat,
  737. u32 net_cat_len)
  738. {
  739. int host_spot = -1;
  740. u32 net_spot;
  741. u32 net_spot_max = 0;
  742. u32 host_clen_bits = host_cat_len * 8;
  743. u32 net_clen_bits = net_cat_len * 8;
  744. u32 host_cat_size = doi_def->map.std->cat.local_size;
  745. u32 *host_cat_array = doi_def->map.std->cat.local;
  746. switch (doi_def->type) {
  747. case CIPSO_V4_MAP_PASS:
  748. net_spot_max = host_cat_len - 1;
  749. while (net_spot_max > 0 && host_cat[net_spot_max] == 0)
  750. net_spot_max--;
  751. if (net_spot_max > net_cat_len)
  752. return -EINVAL;
  753. memcpy(net_cat, host_cat, net_spot_max);
  754. return net_spot_max;
  755. case CIPSO_V4_MAP_STD:
  756. for (;;) {
  757. host_spot = cipso_v4_bitmap_walk(host_cat,
  758. host_clen_bits,
  759. host_spot + 1,
  760. 1);
  761. if (host_spot < 0)
  762. break;
  763. if (host_spot >= host_cat_size)
  764. return -EPERM;
  765. net_spot = host_cat_array[host_spot];
  766. if (net_spot >= net_clen_bits)
  767. return -ENOSPC;
  768. cipso_v4_bitmap_setbit(net_cat, net_spot, 1);
  769. if (net_spot > net_spot_max)
  770. net_spot_max = net_spot;
  771. }
  772. if (host_spot == -2)
  773. return -EFAULT;
  774. if (++net_spot_max % 8)
  775. return net_spot_max / 8 + 1;
  776. return net_spot_max / 8;
  777. }
  778. return -EINVAL;
  779. }
  780. /**
  781. * cipso_v4_map_cat_rbm_ntoh - Perform a category mapping from network to host
  782. * @doi_def: the DOI definition
  783. * @net_cat: the category bitmap in network/CIPSO format
  784. * @net_cat_len: the length of the CIPSO bitmap in bytes
  785. * @host_cat: the zero'd out category bitmap in host format
  786. * @host_cat_len: the length of the host's category bitmap in bytes
  787. *
  788. * Description:
  789. * Perform a label mapping to translate a CIPSO bitmap to the correct local
  790. * MLS category bitmap using the given DOI definition. Returns the minimum
  791. * size in bytes of the host bitmap on success, negative values otherwise.
  792. *
  793. */
  794. static int cipso_v4_map_cat_rbm_ntoh(const struct cipso_v4_doi *doi_def,
  795. const unsigned char *net_cat,
  796. u32 net_cat_len,
  797. unsigned char *host_cat,
  798. u32 host_cat_len)
  799. {
  800. u32 host_spot;
  801. u32 host_spot_max = 0;
  802. int net_spot = -1;
  803. u32 net_clen_bits = net_cat_len * 8;
  804. u32 host_clen_bits = host_cat_len * 8;
  805. u32 net_cat_size = doi_def->map.std->cat.cipso_size;
  806. u32 *net_cat_array = doi_def->map.std->cat.cipso;
  807. switch (doi_def->type) {
  808. case CIPSO_V4_MAP_PASS:
  809. if (net_cat_len > host_cat_len)
  810. return -EINVAL;
  811. memcpy(host_cat, net_cat, net_cat_len);
  812. return net_cat_len;
  813. case CIPSO_V4_MAP_STD:
  814. for (;;) {
  815. net_spot = cipso_v4_bitmap_walk(net_cat,
  816. net_clen_bits,
  817. net_spot + 1,
  818. 1);
  819. if (net_spot < 0)
  820. break;
  821. if (net_spot >= net_cat_size ||
  822. net_cat_array[net_spot] >= CIPSO_V4_INV_CAT)
  823. return -EPERM;
  824. host_spot = net_cat_array[net_spot];
  825. if (host_spot >= host_clen_bits)
  826. return -ENOSPC;
  827. cipso_v4_bitmap_setbit(host_cat, host_spot, 1);
  828. if (host_spot > host_spot_max)
  829. host_spot_max = host_spot;
  830. }
  831. if (net_spot == -2)
  832. return -EFAULT;
  833. if (++host_spot_max % 8)
  834. return host_spot_max / 8 + 1;
  835. return host_spot_max / 8;
  836. }
  837. return -EINVAL;
  838. }
  839. /*
  840. * Protocol Handling Functions
  841. */
  842. #define CIPSO_V4_HDR_LEN 6
  843. /**
  844. * cipso_v4_gentag_hdr - Generate a CIPSO option header
  845. * @doi_def: the DOI definition
  846. * @len: the total tag length in bytes
  847. * @buf: the CIPSO option buffer
  848. *
  849. * Description:
  850. * Write a CIPSO header into the beginning of @buffer. Return zero on success,
  851. * negative values on failure.
  852. *
  853. */
  854. static int cipso_v4_gentag_hdr(const struct cipso_v4_doi *doi_def,
  855. u32 len,
  856. unsigned char *buf)
  857. {
  858. if (CIPSO_V4_HDR_LEN + len > 40)
  859. return -ENOSPC;
  860. buf[0] = IPOPT_CIPSO;
  861. buf[1] = CIPSO_V4_HDR_LEN + len;
  862. *(u32 *)&buf[2] = htonl(doi_def->doi);
  863. return 0;
  864. }
  865. #define CIPSO_V4_TAG1_CAT_LEN 30
  866. /**
  867. * cipso_v4_gentag_rbm - Generate a CIPSO restricted bitmap tag (type #1)
  868. * @doi_def: the DOI definition
  869. * @secattr: the security attributes
  870. * @buffer: the option buffer
  871. * @buffer_len: length of buffer in bytes
  872. *
  873. * Description:
  874. * Generate a CIPSO option using the restricted bitmap tag, tag type #1. The
  875. * actual buffer length may be larger than the indicated size due to
  876. * translation between host and network category bitmaps. Returns zero on
  877. * success, negative values on failure.
  878. *
  879. */
  880. static int cipso_v4_gentag_rbm(const struct cipso_v4_doi *doi_def,
  881. const struct netlbl_lsm_secattr *secattr,
  882. unsigned char **buffer,
  883. u32 *buffer_len)
  884. {
  885. int ret_val = -EPERM;
  886. unsigned char *buf = NULL;
  887. u32 buf_len;
  888. u32 level;
  889. if (secattr->mls_cat) {
  890. buf = kzalloc(CIPSO_V4_HDR_LEN + 4 + CIPSO_V4_TAG1_CAT_LEN,
  891. GFP_ATOMIC);
  892. if (buf == NULL)
  893. return -ENOMEM;
  894. ret_val = cipso_v4_map_cat_rbm_hton(doi_def,
  895. secattr->mls_cat,
  896. secattr->mls_cat_len,
  897. &buf[CIPSO_V4_HDR_LEN + 4],
  898. CIPSO_V4_TAG1_CAT_LEN);
  899. if (ret_val < 0)
  900. goto gentag_failure;
  901. /* This will send packets using the "optimized" format when
  902. * possibile as specified in section 3.4.2.6 of the
  903. * CIPSO draft. */
  904. if (cipso_v4_rbm_optfmt && (ret_val > 0 && ret_val < 10))
  905. ret_val = 10;
  906. buf_len = 4 + ret_val;
  907. } else {
  908. buf = kzalloc(CIPSO_V4_HDR_LEN + 4, GFP_ATOMIC);
  909. if (buf == NULL)
  910. return -ENOMEM;
  911. buf_len = 4;
  912. }
  913. ret_val = cipso_v4_map_lvl_hton(doi_def, secattr->mls_lvl, &level);
  914. if (ret_val != 0)
  915. goto gentag_failure;
  916. ret_val = cipso_v4_gentag_hdr(doi_def, buf_len, buf);
  917. if (ret_val != 0)
  918. goto gentag_failure;
  919. buf[CIPSO_V4_HDR_LEN] = 0x01;
  920. buf[CIPSO_V4_HDR_LEN + 1] = buf_len;
  921. buf[CIPSO_V4_HDR_LEN + 3] = level;
  922. *buffer = buf;
  923. *buffer_len = CIPSO_V4_HDR_LEN + buf_len;
  924. return 0;
  925. gentag_failure:
  926. kfree(buf);
  927. return ret_val;
  928. }
  929. /**
  930. * cipso_v4_parsetag_rbm - Parse a CIPSO restricted bitmap tag
  931. * @doi_def: the DOI definition
  932. * @tag: the CIPSO tag
  933. * @secattr: the security attributes
  934. *
  935. * Description:
  936. * Parse a CIPSO restricted bitmap tag (tag type #1) and return the security
  937. * attributes in @secattr. Return zero on success, negatives values on
  938. * failure.
  939. *
  940. */
  941. static int cipso_v4_parsetag_rbm(const struct cipso_v4_doi *doi_def,
  942. const unsigned char *tag,
  943. struct netlbl_lsm_secattr *secattr)
  944. {
  945. int ret_val;
  946. u8 tag_len = tag[1];
  947. u32 level;
  948. ret_val = cipso_v4_map_lvl_ntoh(doi_def, tag[3], &level);
  949. if (ret_val != 0)
  950. return ret_val;
  951. secattr->mls_lvl = level;
  952. secattr->mls_lvl_vld = 1;
  953. if (tag_len > 4) {
  954. switch (doi_def->type) {
  955. case CIPSO_V4_MAP_PASS:
  956. secattr->mls_cat_len = tag_len - 4;
  957. break;
  958. case CIPSO_V4_MAP_STD:
  959. secattr->mls_cat_len =
  960. doi_def->map.std->cat.local_size;
  961. break;
  962. }
  963. secattr->mls_cat = kzalloc(secattr->mls_cat_len, GFP_ATOMIC);
  964. if (secattr->mls_cat == NULL)
  965. return -ENOMEM;
  966. ret_val = cipso_v4_map_cat_rbm_ntoh(doi_def,
  967. &tag[4],
  968. tag_len - 4,
  969. secattr->mls_cat,
  970. secattr->mls_cat_len);
  971. if (ret_val < 0) {
  972. kfree(secattr->mls_cat);
  973. return ret_val;
  974. }
  975. secattr->mls_cat_len = ret_val;
  976. }
  977. return 0;
  978. }
  979. /**
  980. * cipso_v4_validate - Validate a CIPSO option
  981. * @option: the start of the option, on error it is set to point to the error
  982. *
  983. * Description:
  984. * This routine is called to validate a CIPSO option, it checks all of the
  985. * fields to ensure that they are at least valid, see the draft snippet below
  986. * for details. If the option is valid then a zero value is returned and
  987. * the value of @option is unchanged. If the option is invalid then a
  988. * non-zero value is returned and @option is adjusted to point to the
  989. * offending portion of the option. From the IETF draft ...
  990. *
  991. * "If any field within the CIPSO options, such as the DOI identifier, is not
  992. * recognized the IP datagram is discarded and an ICMP 'parameter problem'
  993. * (type 12) is generated and returned. The ICMP code field is set to 'bad
  994. * parameter' (code 0) and the pointer is set to the start of the CIPSO field
  995. * that is unrecognized."
  996. *
  997. */
  998. int cipso_v4_validate(unsigned char **option)
  999. {
  1000. unsigned char *opt = *option;
  1001. unsigned char *tag;
  1002. unsigned char opt_iter;
  1003. unsigned char err_offset = 0;
  1004. u8 opt_len;
  1005. u8 tag_len;
  1006. struct cipso_v4_doi *doi_def = NULL;
  1007. u32 tag_iter;
  1008. /* caller already checks for length values that are too large */
  1009. opt_len = opt[1];
  1010. if (opt_len < 8) {
  1011. err_offset = 1;
  1012. goto validate_return;
  1013. }
  1014. rcu_read_lock();
  1015. doi_def = cipso_v4_doi_getdef(ntohl(*((u32 *)&opt[2])));
  1016. if (doi_def == NULL) {
  1017. err_offset = 2;
  1018. goto validate_return_locked;
  1019. }
  1020. opt_iter = 6;
  1021. tag = opt + opt_iter;
  1022. while (opt_iter < opt_len) {
  1023. for (tag_iter = 0; doi_def->tags[tag_iter] != tag[0];)
  1024. if (doi_def->tags[tag_iter] == CIPSO_V4_TAG_INVALID ||
  1025. ++tag_iter == CIPSO_V4_TAG_MAXCNT) {
  1026. err_offset = opt_iter;
  1027. goto validate_return_locked;
  1028. }
  1029. tag_len = tag[1];
  1030. if (tag_len > (opt_len - opt_iter)) {
  1031. err_offset = opt_iter + 1;
  1032. goto validate_return_locked;
  1033. }
  1034. switch (tag[0]) {
  1035. case CIPSO_V4_TAG_RBITMAP:
  1036. if (tag_len < 4) {
  1037. err_offset = opt_iter + 1;
  1038. goto validate_return_locked;
  1039. }
  1040. /* We are already going to do all the verification
  1041. * necessary at the socket layer so from our point of
  1042. * view it is safe to turn these checks off (and less
  1043. * work), however, the CIPSO draft says we should do
  1044. * all the CIPSO validations here but it doesn't
  1045. * really specify _exactly_ what we need to validate
  1046. * ... so, just make it a sysctl tunable. */
  1047. if (cipso_v4_rbm_strictvalid) {
  1048. if (cipso_v4_map_lvl_valid(doi_def,
  1049. tag[3]) < 0) {
  1050. err_offset = opt_iter + 3;
  1051. goto validate_return_locked;
  1052. }
  1053. if (tag_len > 4 &&
  1054. cipso_v4_map_cat_rbm_valid(doi_def,
  1055. &tag[4],
  1056. tag_len - 4) < 0) {
  1057. err_offset = opt_iter + 4;
  1058. goto validate_return_locked;
  1059. }
  1060. }
  1061. break;
  1062. default:
  1063. err_offset = opt_iter;
  1064. goto validate_return_locked;
  1065. }
  1066. tag += tag_len;
  1067. opt_iter += tag_len;
  1068. }
  1069. validate_return_locked:
  1070. rcu_read_unlock();
  1071. validate_return:
  1072. *option = opt + err_offset;
  1073. return err_offset;
  1074. }
  1075. /**
  1076. * cipso_v4_error - Send the correct reponse for a bad packet
  1077. * @skb: the packet
  1078. * @error: the error code
  1079. * @gateway: CIPSO gateway flag
  1080. *
  1081. * Description:
  1082. * Based on the error code given in @error, send an ICMP error message back to
  1083. * the originating host. From the IETF draft ...
  1084. *
  1085. * "If the contents of the CIPSO [option] are valid but the security label is
  1086. * outside of the configured host or port label range, the datagram is
  1087. * discarded and an ICMP 'destination unreachable' (type 3) is generated and
  1088. * returned. The code field of the ICMP is set to 'communication with
  1089. * destination network administratively prohibited' (code 9) or to
  1090. * 'communication with destination host administratively prohibited'
  1091. * (code 10). The value of the code is dependent on whether the originator
  1092. * of the ICMP message is acting as a CIPSO host or a CIPSO gateway. The
  1093. * recipient of the ICMP message MUST be able to handle either value. The
  1094. * same procedure is performed if a CIPSO [option] can not be added to an
  1095. * IP packet because it is too large to fit in the IP options area."
  1096. *
  1097. * "If the error is triggered by receipt of an ICMP message, the message is
  1098. * discarded and no response is permitted (consistent with general ICMP
  1099. * processing rules)."
  1100. *
  1101. */
  1102. void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway)
  1103. {
  1104. if (skb->nh.iph->protocol == IPPROTO_ICMP || error != -EACCES)
  1105. return;
  1106. if (gateway)
  1107. icmp_send(skb, ICMP_DEST_UNREACH, ICMP_NET_ANO, 0);
  1108. else
  1109. icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_ANO, 0);
  1110. }
  1111. /**
  1112. * cipso_v4_socket_setattr - Add a CIPSO option to a socket
  1113. * @sock: the socket
  1114. * @doi_def: the CIPSO DOI to use
  1115. * @secattr: the specific security attributes of the socket
  1116. *
  1117. * Description:
  1118. * Set the CIPSO option on the given socket using the DOI definition and
  1119. * security attributes passed to the function. This function requires
  1120. * exclusive access to @sock->sk, which means it either needs to be in the
  1121. * process of being created or locked via lock_sock(sock->sk). Returns zero on
  1122. * success and negative values on failure.
  1123. *
  1124. */
  1125. int cipso_v4_socket_setattr(const struct socket *sock,
  1126. const struct cipso_v4_doi *doi_def,
  1127. const struct netlbl_lsm_secattr *secattr)
  1128. {
  1129. int ret_val = -EPERM;
  1130. u32 iter;
  1131. unsigned char *buf = NULL;
  1132. u32 buf_len = 0;
  1133. u32 opt_len;
  1134. struct ip_options *opt = NULL;
  1135. struct sock *sk;
  1136. struct inet_sock *sk_inet;
  1137. struct inet_connection_sock *sk_conn;
  1138. /* In the case of sock_create_lite(), the sock->sk field is not
  1139. * defined yet but it is not a problem as the only users of these
  1140. * "lite" PF_INET sockets are functions which do an accept() call
  1141. * afterwards so we will label the socket as part of the accept(). */
  1142. sk = sock->sk;
  1143. if (sk == NULL)
  1144. return 0;
  1145. /* XXX - This code assumes only one tag per CIPSO option which isn't
  1146. * really a good assumption to make but since we only support the MAC
  1147. * tags right now it is a safe assumption. */
  1148. iter = 0;
  1149. do {
  1150. switch (doi_def->tags[iter]) {
  1151. case CIPSO_V4_TAG_RBITMAP:
  1152. ret_val = cipso_v4_gentag_rbm(doi_def,
  1153. secattr,
  1154. &buf,
  1155. &buf_len);
  1156. break;
  1157. default:
  1158. ret_val = -EPERM;
  1159. goto socket_setattr_failure;
  1160. }
  1161. iter++;
  1162. } while (ret_val != 0 &&
  1163. iter < CIPSO_V4_TAG_MAXCNT &&
  1164. doi_def->tags[iter] != CIPSO_V4_TAG_INVALID);
  1165. if (ret_val != 0)
  1166. goto socket_setattr_failure;
  1167. /* We can't use ip_options_get() directly because it makes a call to
  1168. * ip_options_get_alloc() which allocates memory with GFP_KERNEL and
  1169. * we can't block here. */
  1170. opt_len = (buf_len + 3) & ~3;
  1171. opt = kzalloc(sizeof(*opt) + opt_len, GFP_ATOMIC);
  1172. if (opt == NULL) {
  1173. ret_val = -ENOMEM;
  1174. goto socket_setattr_failure;
  1175. }
  1176. memcpy(opt->__data, buf, buf_len);
  1177. opt->optlen = opt_len;
  1178. opt->is_data = 1;
  1179. kfree(buf);
  1180. buf = NULL;
  1181. ret_val = ip_options_compile(opt, NULL);
  1182. if (ret_val != 0)
  1183. goto socket_setattr_failure;
  1184. sk_inet = inet_sk(sk);
  1185. if (sk_inet->is_icsk) {
  1186. sk_conn = inet_csk(sk);
  1187. if (sk_inet->opt)
  1188. sk_conn->icsk_ext_hdr_len -= sk_inet->opt->optlen;
  1189. sk_conn->icsk_ext_hdr_len += opt->optlen;
  1190. sk_conn->icsk_sync_mss(sk, sk_conn->icsk_pmtu_cookie);
  1191. }
  1192. opt = xchg(&sk_inet->opt, opt);
  1193. kfree(opt);
  1194. return 0;
  1195. socket_setattr_failure:
  1196. kfree(buf);
  1197. kfree(opt);
  1198. return ret_val;
  1199. }
  1200. /**
  1201. * cipso_v4_sock_getattr - Get the security attributes from a sock
  1202. * @sk: the sock
  1203. * @secattr: the security attributes
  1204. *
  1205. * Description:
  1206. * Query @sk to see if there is a CIPSO option attached to the sock and if
  1207. * there is return the CIPSO security attributes in @secattr. This function
  1208. * requires that @sk be locked, or privately held, but it does not do any
  1209. * locking itself. Returns zero on success and negative values on failure.
  1210. *
  1211. */
  1212. int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
  1213. {
  1214. int ret_val = -ENOMSG;
  1215. struct inet_sock *sk_inet;
  1216. unsigned char *cipso_ptr;
  1217. u32 doi;
  1218. struct cipso_v4_doi *doi_def;
  1219. sk_inet = inet_sk(sk);
  1220. if (sk_inet->opt == NULL || sk_inet->opt->cipso == 0)
  1221. return -ENOMSG;
  1222. cipso_ptr = sk_inet->opt->__data + sk_inet->opt->cipso -
  1223. sizeof(struct iphdr);
  1224. ret_val = cipso_v4_cache_check(cipso_ptr, cipso_ptr[1], secattr);
  1225. if (ret_val == 0)
  1226. return ret_val;
  1227. doi = ntohl(*(u32 *)&cipso_ptr[2]);
  1228. rcu_read_lock();
  1229. doi_def = cipso_v4_doi_getdef(doi);
  1230. if (doi_def == NULL) {
  1231. rcu_read_unlock();
  1232. return -ENOMSG;
  1233. }
  1234. switch (cipso_ptr[6]) {
  1235. case CIPSO_V4_TAG_RBITMAP:
  1236. ret_val = cipso_v4_parsetag_rbm(doi_def,
  1237. &cipso_ptr[6],
  1238. secattr);
  1239. break;
  1240. }
  1241. rcu_read_unlock();
  1242. return ret_val;
  1243. }
  1244. /**
  1245. * cipso_v4_socket_getattr - Get the security attributes from a socket
  1246. * @sock: the socket
  1247. * @secattr: the security attributes
  1248. *
  1249. * Description:
  1250. * Query @sock to see if there is a CIPSO option attached to the socket and if
  1251. * there is return the CIPSO security attributes in @secattr. Returns zero on
  1252. * success and negative values on failure.
  1253. *
  1254. */
  1255. int cipso_v4_socket_getattr(const struct socket *sock,
  1256. struct netlbl_lsm_secattr *secattr)
  1257. {
  1258. int ret_val;
  1259. lock_sock(sock->sk);
  1260. ret_val = cipso_v4_sock_getattr(sock->sk, secattr);
  1261. release_sock(sock->sk);
  1262. return ret_val;
  1263. }
  1264. /**
  1265. * cipso_v4_skbuff_getattr - Get the security attributes from the CIPSO option
  1266. * @skb: the packet
  1267. * @secattr: the security attributes
  1268. *
  1269. * Description:
  1270. * Parse the given packet's CIPSO option and return the security attributes.
  1271. * Returns zero on success and negative values on failure.
  1272. *
  1273. */
  1274. int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
  1275. struct netlbl_lsm_secattr *secattr)
  1276. {
  1277. int ret_val = -ENOMSG;
  1278. unsigned char *cipso_ptr;
  1279. u32 doi;
  1280. struct cipso_v4_doi *doi_def;
  1281. if (!CIPSO_V4_OPTEXIST(skb))
  1282. return -ENOMSG;
  1283. cipso_ptr = CIPSO_V4_OPTPTR(skb);
  1284. if (cipso_v4_cache_check(cipso_ptr, cipso_ptr[1], secattr) == 0)
  1285. return 0;
  1286. doi = ntohl(*(u32 *)&cipso_ptr[2]);
  1287. rcu_read_lock();
  1288. doi_def = cipso_v4_doi_getdef(doi);
  1289. if (doi_def == NULL)
  1290. goto skbuff_getattr_return;
  1291. switch (cipso_ptr[6]) {
  1292. case CIPSO_V4_TAG_RBITMAP:
  1293. ret_val = cipso_v4_parsetag_rbm(doi_def,
  1294. &cipso_ptr[6],
  1295. secattr);
  1296. break;
  1297. }
  1298. skbuff_getattr_return:
  1299. rcu_read_unlock();
  1300. return ret_val;
  1301. }
  1302. /*
  1303. * Setup Functions
  1304. */
  1305. /**
  1306. * cipso_v4_init - Initialize the CIPSO module
  1307. *
  1308. * Description:
  1309. * Initialize the CIPSO module and prepare it for use. Returns zero on success
  1310. * and negative values on failure.
  1311. *
  1312. */
  1313. static int __init cipso_v4_init(void)
  1314. {
  1315. int ret_val;
  1316. ret_val = cipso_v4_cache_init();
  1317. if (ret_val != 0)
  1318. panic("Failed to initialize the CIPSO/IPv4 cache (%d)\n",
  1319. ret_val);
  1320. return 0;
  1321. }
  1322. subsys_initcall(cipso_v4_init);