posix_acl.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. /*
  2. * linux/fs/posix_acl.c
  3. *
  4. * Copyright (C) 2002 by Andreas Gruenbacher <a.gruenbacher@computer.org>
  5. *
  6. * Fixes from William Schumacher incorporated on 15 March 2001.
  7. * (Reported by Charles Bertsch, <CBertsch@microtest.com>).
  8. */
  9. /*
  10. * This file contains generic functions for manipulating
  11. * POSIX 1003.1e draft standard 17 ACLs.
  12. */
  13. #include <linux/kernel.h>
  14. #include <linux/slab.h>
  15. #include <asm/atomic.h>
  16. #include <linux/fs.h>
  17. #include <linux/sched.h>
  18. #include <linux/posix_acl.h>
  19. #include <linux/module.h>
  20. #include <linux/errno.h>
  21. EXPORT_SYMBOL(posix_acl_alloc);
  22. EXPORT_SYMBOL(posix_acl_clone);
  23. EXPORT_SYMBOL(posix_acl_valid);
  24. EXPORT_SYMBOL(posix_acl_equiv_mode);
  25. EXPORT_SYMBOL(posix_acl_from_mode);
  26. EXPORT_SYMBOL(posix_acl_create_masq);
  27. EXPORT_SYMBOL(posix_acl_chmod_masq);
  28. EXPORT_SYMBOL(posix_acl_permission);
  29. /*
  30. * Allocate a new ACL with the specified number of entries.
  31. */
  32. struct posix_acl *
  33. posix_acl_alloc(int count, gfp_t flags)
  34. {
  35. const size_t size = sizeof(struct posix_acl) +
  36. count * sizeof(struct posix_acl_entry);
  37. struct posix_acl *acl = kmalloc(size, flags);
  38. if (acl) {
  39. atomic_set(&acl->a_refcount, 1);
  40. acl->a_count = count;
  41. }
  42. return acl;
  43. }
  44. /*
  45. * Clone an ACL.
  46. */
  47. struct posix_acl *
  48. posix_acl_clone(const struct posix_acl *acl, gfp_t flags)
  49. {
  50. struct posix_acl *clone = NULL;
  51. if (acl) {
  52. int size = sizeof(struct posix_acl) + acl->a_count *
  53. sizeof(struct posix_acl_entry);
  54. clone = kmalloc(size, flags);
  55. if (clone) {
  56. memcpy(clone, acl, size);
  57. atomic_set(&clone->a_refcount, 1);
  58. }
  59. }
  60. return clone;
  61. }
  62. /*
  63. * Check if an acl is valid. Returns 0 if it is, or -E... otherwise.
  64. */
  65. int
  66. posix_acl_valid(const struct posix_acl *acl)
  67. {
  68. const struct posix_acl_entry *pa, *pe;
  69. int state = ACL_USER_OBJ;
  70. unsigned int id = 0; /* keep gcc happy */
  71. int needs_mask = 0;
  72. FOREACH_ACL_ENTRY(pa, acl, pe) {
  73. if (pa->e_perm & ~(ACL_READ|ACL_WRITE|ACL_EXECUTE))
  74. return -EINVAL;
  75. switch (pa->e_tag) {
  76. case ACL_USER_OBJ:
  77. if (state == ACL_USER_OBJ) {
  78. id = 0;
  79. state = ACL_USER;
  80. break;
  81. }
  82. return -EINVAL;
  83. case ACL_USER:
  84. if (state != ACL_USER)
  85. return -EINVAL;
  86. if (pa->e_id == ACL_UNDEFINED_ID ||
  87. pa->e_id < id)
  88. return -EINVAL;
  89. id = pa->e_id + 1;
  90. needs_mask = 1;
  91. break;
  92. case ACL_GROUP_OBJ:
  93. if (state == ACL_USER) {
  94. id = 0;
  95. state = ACL_GROUP;
  96. break;
  97. }
  98. return -EINVAL;
  99. case ACL_GROUP:
  100. if (state != ACL_GROUP)
  101. return -EINVAL;
  102. if (pa->e_id == ACL_UNDEFINED_ID ||
  103. pa->e_id < id)
  104. return -EINVAL;
  105. id = pa->e_id + 1;
  106. needs_mask = 1;
  107. break;
  108. case ACL_MASK:
  109. if (state != ACL_GROUP)
  110. return -EINVAL;
  111. state = ACL_OTHER;
  112. break;
  113. case ACL_OTHER:
  114. if (state == ACL_OTHER ||
  115. (state == ACL_GROUP && !needs_mask)) {
  116. state = 0;
  117. break;
  118. }
  119. return -EINVAL;
  120. default:
  121. return -EINVAL;
  122. }
  123. }
  124. if (state == 0)
  125. return 0;
  126. return -EINVAL;
  127. }
  128. /*
  129. * Returns 0 if the acl can be exactly represented in the traditional
  130. * file mode permission bits, or else 1. Returns -E... on error.
  131. */
  132. int
  133. posix_acl_equiv_mode(const struct posix_acl *acl, mode_t *mode_p)
  134. {
  135. const struct posix_acl_entry *pa, *pe;
  136. mode_t mode = 0;
  137. int not_equiv = 0;
  138. FOREACH_ACL_ENTRY(pa, acl, pe) {
  139. switch (pa->e_tag) {
  140. case ACL_USER_OBJ:
  141. mode |= (pa->e_perm & S_IRWXO) << 6;
  142. break;
  143. case ACL_GROUP_OBJ:
  144. mode |= (pa->e_perm & S_IRWXO) << 3;
  145. break;
  146. case ACL_OTHER:
  147. mode |= pa->e_perm & S_IRWXO;
  148. break;
  149. case ACL_MASK:
  150. mode = (mode & ~S_IRWXG) |
  151. ((pa->e_perm & S_IRWXO) << 3);
  152. not_equiv = 1;
  153. break;
  154. case ACL_USER:
  155. case ACL_GROUP:
  156. not_equiv = 1;
  157. break;
  158. default:
  159. return -EINVAL;
  160. }
  161. }
  162. if (mode_p)
  163. *mode_p = (*mode_p & ~S_IRWXUGO) | mode;
  164. return not_equiv;
  165. }
  166. /*
  167. * Create an ACL representing the file mode permission bits of an inode.
  168. */
  169. struct posix_acl *
  170. posix_acl_from_mode(mode_t mode, gfp_t flags)
  171. {
  172. struct posix_acl *acl = posix_acl_alloc(3, flags);
  173. if (!acl)
  174. return ERR_PTR(-ENOMEM);
  175. acl->a_entries[0].e_tag = ACL_USER_OBJ;
  176. acl->a_entries[0].e_id = ACL_UNDEFINED_ID;
  177. acl->a_entries[0].e_perm = (mode & S_IRWXU) >> 6;
  178. acl->a_entries[1].e_tag = ACL_GROUP_OBJ;
  179. acl->a_entries[1].e_id = ACL_UNDEFINED_ID;
  180. acl->a_entries[1].e_perm = (mode & S_IRWXG) >> 3;
  181. acl->a_entries[2].e_tag = ACL_OTHER;
  182. acl->a_entries[2].e_id = ACL_UNDEFINED_ID;
  183. acl->a_entries[2].e_perm = (mode & S_IRWXO);
  184. return acl;
  185. }
  186. /*
  187. * Return 0 if current is granted want access to the inode
  188. * by the acl. Returns -E... otherwise.
  189. */
  190. int
  191. posix_acl_permission(struct inode *inode, const struct posix_acl *acl, int want)
  192. {
  193. const struct posix_acl_entry *pa, *pe, *mask_obj;
  194. int found = 0;
  195. FOREACH_ACL_ENTRY(pa, acl, pe) {
  196. switch(pa->e_tag) {
  197. case ACL_USER_OBJ:
  198. /* (May have been checked already) */
  199. if (inode->i_uid == current->fsuid)
  200. goto check_perm;
  201. break;
  202. case ACL_USER:
  203. if (pa->e_id == current->fsuid)
  204. goto mask;
  205. break;
  206. case ACL_GROUP_OBJ:
  207. if (in_group_p(inode->i_gid)) {
  208. found = 1;
  209. if ((pa->e_perm & want) == want)
  210. goto mask;
  211. }
  212. break;
  213. case ACL_GROUP:
  214. if (in_group_p(pa->e_id)) {
  215. found = 1;
  216. if ((pa->e_perm & want) == want)
  217. goto mask;
  218. }
  219. break;
  220. case ACL_MASK:
  221. break;
  222. case ACL_OTHER:
  223. if (found)
  224. return -EACCES;
  225. else
  226. goto check_perm;
  227. default:
  228. return -EIO;
  229. }
  230. }
  231. return -EIO;
  232. mask:
  233. for (mask_obj = pa+1; mask_obj != pe; mask_obj++) {
  234. if (mask_obj->e_tag == ACL_MASK) {
  235. if ((pa->e_perm & mask_obj->e_perm & want) == want)
  236. return 0;
  237. return -EACCES;
  238. }
  239. }
  240. check_perm:
  241. if ((pa->e_perm & want) == want)
  242. return 0;
  243. return -EACCES;
  244. }
  245. /*
  246. * Modify acl when creating a new inode. The caller must ensure the acl is
  247. * only referenced once.
  248. *
  249. * mode_p initially must contain the mode parameter to the open() / creat()
  250. * system calls. All permissions that are not granted by the acl are removed.
  251. * The permissions in the acl are changed to reflect the mode_p parameter.
  252. */
  253. int
  254. posix_acl_create_masq(struct posix_acl *acl, mode_t *mode_p)
  255. {
  256. struct posix_acl_entry *pa, *pe;
  257. struct posix_acl_entry *group_obj = NULL, *mask_obj = NULL;
  258. mode_t mode = *mode_p;
  259. int not_equiv = 0;
  260. /* assert(atomic_read(acl->a_refcount) == 1); */
  261. FOREACH_ACL_ENTRY(pa, acl, pe) {
  262. switch(pa->e_tag) {
  263. case ACL_USER_OBJ:
  264. pa->e_perm &= (mode >> 6) | ~S_IRWXO;
  265. mode &= (pa->e_perm << 6) | ~S_IRWXU;
  266. break;
  267. case ACL_USER:
  268. case ACL_GROUP:
  269. not_equiv = 1;
  270. break;
  271. case ACL_GROUP_OBJ:
  272. group_obj = pa;
  273. break;
  274. case ACL_OTHER:
  275. pa->e_perm &= mode | ~S_IRWXO;
  276. mode &= pa->e_perm | ~S_IRWXO;
  277. break;
  278. case ACL_MASK:
  279. mask_obj = pa;
  280. not_equiv = 1;
  281. break;
  282. default:
  283. return -EIO;
  284. }
  285. }
  286. if (mask_obj) {
  287. mask_obj->e_perm &= (mode >> 3) | ~S_IRWXO;
  288. mode &= (mask_obj->e_perm << 3) | ~S_IRWXG;
  289. } else {
  290. if (!group_obj)
  291. return -EIO;
  292. group_obj->e_perm &= (mode >> 3) | ~S_IRWXO;
  293. mode &= (group_obj->e_perm << 3) | ~S_IRWXG;
  294. }
  295. *mode_p = (*mode_p & ~S_IRWXUGO) | mode;
  296. return not_equiv;
  297. }
  298. /*
  299. * Modify the ACL for the chmod syscall.
  300. */
  301. int
  302. posix_acl_chmod_masq(struct posix_acl *acl, mode_t mode)
  303. {
  304. struct posix_acl_entry *group_obj = NULL, *mask_obj = NULL;
  305. struct posix_acl_entry *pa, *pe;
  306. /* assert(atomic_read(acl->a_refcount) == 1); */
  307. FOREACH_ACL_ENTRY(pa, acl, pe) {
  308. switch(pa->e_tag) {
  309. case ACL_USER_OBJ:
  310. pa->e_perm = (mode & S_IRWXU) >> 6;
  311. break;
  312. case ACL_USER:
  313. case ACL_GROUP:
  314. break;
  315. case ACL_GROUP_OBJ:
  316. group_obj = pa;
  317. break;
  318. case ACL_MASK:
  319. mask_obj = pa;
  320. break;
  321. case ACL_OTHER:
  322. pa->e_perm = (mode & S_IRWXO);
  323. break;
  324. default:
  325. return -EIO;
  326. }
  327. }
  328. if (mask_obj) {
  329. mask_obj->e_perm = (mode & S_IRWXG) >> 3;
  330. } else {
  331. if (!group_obj)
  332. return -EIO;
  333. group_obj->e_perm = (mode & S_IRWXG) >> 3;
  334. }
  335. return 0;
  336. }