ebitmap.c 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448
  1. /*
  2. * Implementation of the extensible bitmap type.
  3. *
  4. * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
  5. */
  6. /*
  7. * Updated: Hewlett-Packard <paul.moore@hp.com>
  8. *
  9. * Added support to import/export the NetLabel category bitmap
  10. *
  11. * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
  12. */
  13. /*
  14. * Updated: KaiGai Kohei <kaigai@ak.jp.nec.com>
  15. * Applied standard bit operations to improve bitmap scanning.
  16. */
  17. #include <linux/kernel.h>
  18. #include <linux/slab.h>
  19. #include <linux/errno.h>
  20. #include <net/netlabel.h>
  21. #include "ebitmap.h"
  22. #include "policydb.h"
  23. int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2)
  24. {
  25. struct ebitmap_node *n1, *n2;
  26. if (e1->highbit != e2->highbit)
  27. return 0;
  28. n1 = e1->node;
  29. n2 = e2->node;
  30. while (n1 && n2 &&
  31. (n1->startbit == n2->startbit) &&
  32. !memcmp(n1->maps, n2->maps, EBITMAP_SIZE / 8)) {
  33. n1 = n1->next;
  34. n2 = n2->next;
  35. }
  36. if (n1 || n2)
  37. return 0;
  38. return 1;
  39. }
  40. int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src)
  41. {
  42. struct ebitmap_node *n, *new, *prev;
  43. ebitmap_init(dst);
  44. n = src->node;
  45. prev = NULL;
  46. while (n) {
  47. new = kzalloc(sizeof(*new), GFP_ATOMIC);
  48. if (!new) {
  49. ebitmap_destroy(dst);
  50. return -ENOMEM;
  51. }
  52. new->startbit = n->startbit;
  53. memcpy(new->maps, n->maps, EBITMAP_SIZE / 8);
  54. new->next = NULL;
  55. if (prev)
  56. prev->next = new;
  57. else
  58. dst->node = new;
  59. prev = new;
  60. n = n->next;
  61. }
  62. dst->highbit = src->highbit;
  63. return 0;
  64. }
  65. #ifdef CONFIG_NETLABEL
  66. /**
  67. * ebitmap_netlbl_export - Export an ebitmap into a NetLabel category bitmap
  68. * @ebmap: the ebitmap to export
  69. * @catmap: the NetLabel category bitmap
  70. *
  71. * Description:
  72. * Export a SELinux extensibile bitmap into a NetLabel category bitmap.
  73. * Returns zero on success, negative values on error.
  74. *
  75. */
  76. int ebitmap_netlbl_export(struct ebitmap *ebmap,
  77. struct netlbl_lsm_secattr_catmap **catmap)
  78. {
  79. struct ebitmap_node *e_iter = ebmap->node;
  80. struct netlbl_lsm_secattr_catmap *c_iter;
  81. u32 cmap_idx, cmap_sft;
  82. int i;
  83. /* NetLabel's NETLBL_CATMAP_MAPTYPE is defined as an array of u64,
  84. * however, it is not always compatible with an array of unsigned long
  85. * in ebitmap_node.
  86. * In addition, you should pay attention the following implementation
  87. * assumes unsigned long has a width equal with or less than 64-bit.
  88. */
  89. if (e_iter == NULL) {
  90. *catmap = NULL;
  91. return 0;
  92. }
  93. c_iter = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
  94. if (c_iter == NULL)
  95. return -ENOMEM;
  96. *catmap = c_iter;
  97. c_iter->startbit = e_iter->startbit & ~(NETLBL_CATMAP_SIZE - 1);
  98. while (e_iter) {
  99. for (i = 0; i < EBITMAP_UNIT_NUMS; i++) {
  100. unsigned int delta, e_startbit, c_endbit;
  101. e_startbit = e_iter->startbit + i * EBITMAP_UNIT_SIZE;
  102. c_endbit = c_iter->startbit + NETLBL_CATMAP_SIZE;
  103. if (e_startbit >= c_endbit) {
  104. c_iter->next
  105. = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
  106. if (c_iter->next == NULL)
  107. goto netlbl_export_failure;
  108. c_iter = c_iter->next;
  109. c_iter->startbit
  110. = e_startbit & ~(NETLBL_CATMAP_SIZE - 1);
  111. }
  112. delta = e_startbit - c_iter->startbit;
  113. cmap_idx = delta / NETLBL_CATMAP_MAPSIZE;
  114. cmap_sft = delta % NETLBL_CATMAP_MAPSIZE;
  115. c_iter->bitmap[cmap_idx]
  116. |= e_iter->maps[cmap_idx] << cmap_sft;
  117. }
  118. e_iter = e_iter->next;
  119. }
  120. return 0;
  121. netlbl_export_failure:
  122. netlbl_secattr_catmap_free(*catmap);
  123. return -ENOMEM;
  124. }
  125. /**
  126. * ebitmap_netlbl_import - Import a NetLabel category bitmap into an ebitmap
  127. * @ebmap: the ebitmap to import
  128. * @catmap: the NetLabel category bitmap
  129. *
  130. * Description:
  131. * Import a NetLabel category bitmap into a SELinux extensibile bitmap.
  132. * Returns zero on success, negative values on error.
  133. *
  134. */
  135. int ebitmap_netlbl_import(struct ebitmap *ebmap,
  136. struct netlbl_lsm_secattr_catmap *catmap)
  137. {
  138. struct ebitmap_node *e_iter = NULL;
  139. struct ebitmap_node *emap_prev = NULL;
  140. struct netlbl_lsm_secattr_catmap *c_iter = catmap;
  141. u32 c_idx, c_pos, e_idx, e_sft;
  142. /* NetLabel's NETLBL_CATMAP_MAPTYPE is defined as an array of u64,
  143. * however, it is not always compatible with an array of unsigned long
  144. * in ebitmap_node.
  145. * In addition, you should pay attention the following implementation
  146. * assumes unsigned long has a width equal with or less than 64-bit.
  147. */
  148. do {
  149. for (c_idx = 0; c_idx < NETLBL_CATMAP_MAPCNT; c_idx++) {
  150. unsigned int delta;
  151. u64 map = c_iter->bitmap[c_idx];
  152. if (!map)
  153. continue;
  154. c_pos = c_iter->startbit
  155. + c_idx * NETLBL_CATMAP_MAPSIZE;
  156. if (!e_iter
  157. || c_pos >= e_iter->startbit + EBITMAP_SIZE) {
  158. e_iter = kzalloc(sizeof(*e_iter), GFP_ATOMIC);
  159. if (!e_iter)
  160. goto netlbl_import_failure;
  161. e_iter->startbit
  162. = c_pos - (c_pos % EBITMAP_SIZE);
  163. if (emap_prev == NULL)
  164. ebmap->node = e_iter;
  165. else
  166. emap_prev->next = e_iter;
  167. emap_prev = e_iter;
  168. }
  169. delta = c_pos - e_iter->startbit;
  170. e_idx = delta / EBITMAP_UNIT_SIZE;
  171. e_sft = delta % EBITMAP_UNIT_SIZE;
  172. while (map) {
  173. e_iter->maps[e_idx++] |= map & (-1UL);
  174. map = EBITMAP_SHIFT_UNIT_SIZE(map);
  175. }
  176. }
  177. c_iter = c_iter->next;
  178. } while (c_iter);
  179. if (e_iter != NULL)
  180. ebmap->highbit = e_iter->startbit + EBITMAP_SIZE;
  181. else
  182. ebitmap_destroy(ebmap);
  183. return 0;
  184. netlbl_import_failure:
  185. ebitmap_destroy(ebmap);
  186. return -ENOMEM;
  187. }
  188. #endif /* CONFIG_NETLABEL */
  189. int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2)
  190. {
  191. struct ebitmap_node *n1, *n2;
  192. int i;
  193. if (e1->highbit < e2->highbit)
  194. return 0;
  195. n1 = e1->node;
  196. n2 = e2->node;
  197. while (n1 && n2 && (n1->startbit <= n2->startbit)) {
  198. if (n1->startbit < n2->startbit) {
  199. n1 = n1->next;
  200. continue;
  201. }
  202. for (i = 0; i < EBITMAP_UNIT_NUMS; i++) {
  203. if ((n1->maps[i] & n2->maps[i]) != n2->maps[i])
  204. return 0;
  205. }
  206. n1 = n1->next;
  207. n2 = n2->next;
  208. }
  209. if (n2)
  210. return 0;
  211. return 1;
  212. }
  213. int ebitmap_get_bit(struct ebitmap *e, unsigned long bit)
  214. {
  215. struct ebitmap_node *n;
  216. if (e->highbit < bit)
  217. return 0;
  218. n = e->node;
  219. while (n && (n->startbit <= bit)) {
  220. if ((n->startbit + EBITMAP_SIZE) > bit)
  221. return ebitmap_node_get_bit(n, bit);
  222. n = n->next;
  223. }
  224. return 0;
  225. }
  226. int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value)
  227. {
  228. struct ebitmap_node *n, *prev, *new;
  229. prev = NULL;
  230. n = e->node;
  231. while (n && n->startbit <= bit) {
  232. if ((n->startbit + EBITMAP_SIZE) > bit) {
  233. if (value) {
  234. ebitmap_node_set_bit(n, bit);
  235. } else {
  236. unsigned int s;
  237. ebitmap_node_clr_bit(n, bit);
  238. s = find_first_bit(n->maps, EBITMAP_SIZE);
  239. if (s < EBITMAP_SIZE)
  240. return 0;
  241. /* drop this node from the bitmap */
  242. if (!n->next) {
  243. /*
  244. * this was the highest map
  245. * within the bitmap
  246. */
  247. if (prev)
  248. e->highbit = prev->startbit
  249. + EBITMAP_SIZE;
  250. else
  251. e->highbit = 0;
  252. }
  253. if (prev)
  254. prev->next = n->next;
  255. else
  256. e->node = n->next;
  257. kfree(n);
  258. }
  259. return 0;
  260. }
  261. prev = n;
  262. n = n->next;
  263. }
  264. if (!value)
  265. return 0;
  266. new = kzalloc(sizeof(*new), GFP_ATOMIC);
  267. if (!new)
  268. return -ENOMEM;
  269. new->startbit = bit - (bit % EBITMAP_SIZE);
  270. ebitmap_node_set_bit(new, bit);
  271. if (!n)
  272. /* this node will be the highest map within the bitmap */
  273. e->highbit = new->startbit + EBITMAP_SIZE;
  274. if (prev) {
  275. new->next = prev->next;
  276. prev->next = new;
  277. } else {
  278. new->next = e->node;
  279. e->node = new;
  280. }
  281. return 0;
  282. }
  283. void ebitmap_destroy(struct ebitmap *e)
  284. {
  285. struct ebitmap_node *n, *temp;
  286. if (!e)
  287. return;
  288. n = e->node;
  289. while (n) {
  290. temp = n;
  291. n = n->next;
  292. kfree(temp);
  293. }
  294. e->highbit = 0;
  295. e->node = NULL;
  296. return;
  297. }
  298. int ebitmap_read(struct ebitmap *e, void *fp)
  299. {
  300. struct ebitmap_node *n = NULL;
  301. u32 mapunit, count, startbit, index;
  302. u64 map;
  303. __le32 buf[3];
  304. int rc, i;
  305. ebitmap_init(e);
  306. rc = next_entry(buf, fp, sizeof buf);
  307. if (rc < 0)
  308. goto out;
  309. mapunit = le32_to_cpu(buf[0]);
  310. e->highbit = le32_to_cpu(buf[1]);
  311. count = le32_to_cpu(buf[2]);
  312. if (mapunit != sizeof(u64) * 8) {
  313. printk(KERN_ERR "SELinux: ebitmap: map size %u does not "
  314. "match my size %Zd (high bit was %d)\n",
  315. mapunit, sizeof(u64) * 8, e->highbit);
  316. goto bad;
  317. }
  318. /* round up e->highbit */
  319. e->highbit += EBITMAP_SIZE - 1;
  320. e->highbit -= (e->highbit % EBITMAP_SIZE);
  321. if (!e->highbit) {
  322. e->node = NULL;
  323. goto ok;
  324. }
  325. for (i = 0; i < count; i++) {
  326. rc = next_entry(&startbit, fp, sizeof(u32));
  327. if (rc < 0) {
  328. printk(KERN_ERR "SELinux: ebitmap: truncated map\n");
  329. goto bad;
  330. }
  331. startbit = le32_to_cpu(startbit);
  332. if (startbit & (mapunit - 1)) {
  333. printk(KERN_ERR "SELinux: ebitmap start bit (%d) is "
  334. "not a multiple of the map unit size (%u)\n",
  335. startbit, mapunit);
  336. goto bad;
  337. }
  338. if (startbit > e->highbit - mapunit) {
  339. printk(KERN_ERR "SELinux: ebitmap start bit (%d) is "
  340. "beyond the end of the bitmap (%u)\n",
  341. startbit, (e->highbit - mapunit));
  342. goto bad;
  343. }
  344. if (!n || startbit >= n->startbit + EBITMAP_SIZE) {
  345. struct ebitmap_node *tmp;
  346. tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
  347. if (!tmp) {
  348. printk(KERN_ERR
  349. "SELinux: ebitmap: out of memory\n");
  350. rc = -ENOMEM;
  351. goto bad;
  352. }
  353. /* round down */
  354. tmp->startbit = startbit - (startbit % EBITMAP_SIZE);
  355. if (n)
  356. n->next = tmp;
  357. else
  358. e->node = tmp;
  359. n = tmp;
  360. } else if (startbit <= n->startbit) {
  361. printk(KERN_ERR "SELinux: ebitmap: start bit %d"
  362. " comes after start bit %d\n",
  363. startbit, n->startbit);
  364. goto bad;
  365. }
  366. rc = next_entry(&map, fp, sizeof(u64));
  367. if (rc < 0) {
  368. printk(KERN_ERR "SELinux: ebitmap: truncated map\n");
  369. goto bad;
  370. }
  371. map = le64_to_cpu(map);
  372. index = (startbit - n->startbit) / EBITMAP_UNIT_SIZE;
  373. while (map) {
  374. n->maps[index++] = map & (-1UL);
  375. map = EBITMAP_SHIFT_UNIT_SIZE(map);
  376. }
  377. }
  378. ok:
  379. rc = 0;
  380. out:
  381. return rc;
  382. bad:
  383. if (!rc)
  384. rc = -EINVAL;
  385. ebitmap_destroy(e);
  386. goto out;
  387. }