xfs_acl.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923
  1. /*
  2. * Copyright (c) 2001-2002,2005 Silicon Graphics, Inc.
  3. * All Rights Reserved.
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it would be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write the Free Software Foundation,
  16. * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  17. */
  18. #include "xfs.h"
  19. #include "xfs_fs.h"
  20. #include "xfs_types.h"
  21. #include "xfs_bit.h"
  22. #include "xfs_inum.h"
  23. #include "xfs_ag.h"
  24. #include "xfs_dir2.h"
  25. #include "xfs_bmap_btree.h"
  26. #include "xfs_alloc_btree.h"
  27. #include "xfs_ialloc_btree.h"
  28. #include "xfs_dir2_sf.h"
  29. #include "xfs_attr_sf.h"
  30. #include "xfs_dinode.h"
  31. #include "xfs_inode.h"
  32. #include "xfs_btree.h"
  33. #include "xfs_acl.h"
  34. #include "xfs_attr.h"
  35. #include <linux/capability.h>
  36. #include <linux/posix_acl_xattr.h>
  37. STATIC int xfs_acl_setmode(bhv_vnode_t *, xfs_acl_t *, int *);
  38. STATIC void xfs_acl_filter_mode(mode_t, xfs_acl_t *);
  39. STATIC void xfs_acl_get_endian(xfs_acl_t *);
  40. STATIC int xfs_acl_access(uid_t, gid_t, xfs_acl_t *, mode_t, cred_t *);
  41. STATIC int xfs_acl_invalid(xfs_acl_t *);
  42. STATIC void xfs_acl_sync_mode(mode_t, xfs_acl_t *);
  43. STATIC void xfs_acl_get_attr(bhv_vnode_t *, xfs_acl_t *, int, int, int *);
  44. STATIC void xfs_acl_set_attr(bhv_vnode_t *, xfs_acl_t *, int, int *);
  45. STATIC int xfs_acl_allow_set(bhv_vnode_t *, int);
  46. kmem_zone_t *xfs_acl_zone;
  47. /*
  48. * Test for existence of access ACL attribute as efficiently as possible.
  49. */
  50. int
  51. xfs_acl_vhasacl_access(
  52. bhv_vnode_t *vp)
  53. {
  54. int error;
  55. xfs_acl_get_attr(vp, NULL, _ACL_TYPE_ACCESS, ATTR_KERNOVAL, &error);
  56. return (error == 0);
  57. }
  58. /*
  59. * Test for existence of default ACL attribute as efficiently as possible.
  60. */
  61. int
  62. xfs_acl_vhasacl_default(
  63. bhv_vnode_t *vp)
  64. {
  65. int error;
  66. if (!VN_ISDIR(vp))
  67. return 0;
  68. xfs_acl_get_attr(vp, NULL, _ACL_TYPE_DEFAULT, ATTR_KERNOVAL, &error);
  69. return (error == 0);
  70. }
  71. /*
  72. * Convert from extended attribute representation to in-memory for XFS.
  73. */
  74. STATIC int
  75. posix_acl_xattr_to_xfs(
  76. posix_acl_xattr_header *src,
  77. size_t size,
  78. xfs_acl_t *dest)
  79. {
  80. posix_acl_xattr_entry *src_entry;
  81. xfs_acl_entry_t *dest_entry;
  82. int n;
  83. if (!src || !dest)
  84. return EINVAL;
  85. if (size < sizeof(posix_acl_xattr_header))
  86. return EINVAL;
  87. if (src->a_version != cpu_to_le32(POSIX_ACL_XATTR_VERSION))
  88. return EOPNOTSUPP;
  89. memset(dest, 0, sizeof(xfs_acl_t));
  90. dest->acl_cnt = posix_acl_xattr_count(size);
  91. if (dest->acl_cnt < 0 || dest->acl_cnt > XFS_ACL_MAX_ENTRIES)
  92. return EINVAL;
  93. /*
  94. * acl_set_file(3) may request that we set default ACLs with
  95. * zero length -- defend (gracefully) against that here.
  96. */
  97. if (!dest->acl_cnt)
  98. return 0;
  99. src_entry = (posix_acl_xattr_entry *)((char *)src + sizeof(*src));
  100. dest_entry = &dest->acl_entry[0];
  101. for (n = 0; n < dest->acl_cnt; n++, src_entry++, dest_entry++) {
  102. dest_entry->ae_perm = le16_to_cpu(src_entry->e_perm);
  103. if (_ACL_PERM_INVALID(dest_entry->ae_perm))
  104. return EINVAL;
  105. dest_entry->ae_tag = le16_to_cpu(src_entry->e_tag);
  106. switch(dest_entry->ae_tag) {
  107. case ACL_USER:
  108. case ACL_GROUP:
  109. dest_entry->ae_id = le32_to_cpu(src_entry->e_id);
  110. break;
  111. case ACL_USER_OBJ:
  112. case ACL_GROUP_OBJ:
  113. case ACL_MASK:
  114. case ACL_OTHER:
  115. dest_entry->ae_id = ACL_UNDEFINED_ID;
  116. break;
  117. default:
  118. return EINVAL;
  119. }
  120. }
  121. if (xfs_acl_invalid(dest))
  122. return EINVAL;
  123. return 0;
  124. }
  125. /*
  126. * Comparison function called from xfs_sort().
  127. * Primary key is ae_tag, secondary key is ae_id.
  128. */
  129. STATIC int
  130. xfs_acl_entry_compare(
  131. const void *va,
  132. const void *vb)
  133. {
  134. xfs_acl_entry_t *a = (xfs_acl_entry_t *)va,
  135. *b = (xfs_acl_entry_t *)vb;
  136. if (a->ae_tag == b->ae_tag)
  137. return (a->ae_id - b->ae_id);
  138. return (a->ae_tag - b->ae_tag);
  139. }
  140. /*
  141. * Convert from in-memory XFS to extended attribute representation.
  142. */
  143. STATIC int
  144. posix_acl_xfs_to_xattr(
  145. xfs_acl_t *src,
  146. posix_acl_xattr_header *dest,
  147. size_t size)
  148. {
  149. int n;
  150. size_t new_size = posix_acl_xattr_size(src->acl_cnt);
  151. posix_acl_xattr_entry *dest_entry;
  152. xfs_acl_entry_t *src_entry;
  153. if (size < new_size)
  154. return -ERANGE;
  155. /* Need to sort src XFS ACL by <ae_tag,ae_id> */
  156. xfs_sort(src->acl_entry, src->acl_cnt, sizeof(src->acl_entry[0]),
  157. xfs_acl_entry_compare);
  158. dest->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
  159. dest_entry = &dest->a_entries[0];
  160. src_entry = &src->acl_entry[0];
  161. for (n = 0; n < src->acl_cnt; n++, dest_entry++, src_entry++) {
  162. dest_entry->e_perm = cpu_to_le16(src_entry->ae_perm);
  163. if (_ACL_PERM_INVALID(src_entry->ae_perm))
  164. return -EINVAL;
  165. dest_entry->e_tag = cpu_to_le16(src_entry->ae_tag);
  166. switch (src_entry->ae_tag) {
  167. case ACL_USER:
  168. case ACL_GROUP:
  169. dest_entry->e_id = cpu_to_le32(src_entry->ae_id);
  170. break;
  171. case ACL_USER_OBJ:
  172. case ACL_GROUP_OBJ:
  173. case ACL_MASK:
  174. case ACL_OTHER:
  175. dest_entry->e_id = cpu_to_le32(ACL_UNDEFINED_ID);
  176. break;
  177. default:
  178. return -EINVAL;
  179. }
  180. }
  181. return new_size;
  182. }
  183. int
  184. xfs_acl_vget(
  185. bhv_vnode_t *vp,
  186. void *acl,
  187. size_t size,
  188. int kind)
  189. {
  190. int error;
  191. xfs_acl_t *xfs_acl = NULL;
  192. posix_acl_xattr_header *ext_acl = acl;
  193. int flags = 0;
  194. VN_HOLD(vp);
  195. if(size) {
  196. if (!(_ACL_ALLOC(xfs_acl))) {
  197. error = ENOMEM;
  198. goto out;
  199. }
  200. memset(xfs_acl, 0, sizeof(xfs_acl_t));
  201. } else
  202. flags = ATTR_KERNOVAL;
  203. xfs_acl_get_attr(vp, xfs_acl, kind, flags, &error);
  204. if (error)
  205. goto out;
  206. if (!size) {
  207. error = -posix_acl_xattr_size(XFS_ACL_MAX_ENTRIES);
  208. } else {
  209. if (xfs_acl_invalid(xfs_acl)) {
  210. error = EINVAL;
  211. goto out;
  212. }
  213. if (kind == _ACL_TYPE_ACCESS) {
  214. bhv_vattr_t va;
  215. va.va_mask = XFS_AT_MODE;
  216. error = bhv_vop_getattr(vp, &va, 0, sys_cred);
  217. if (error)
  218. goto out;
  219. xfs_acl_sync_mode(va.va_mode, xfs_acl);
  220. }
  221. error = -posix_acl_xfs_to_xattr(xfs_acl, ext_acl, size);
  222. }
  223. out:
  224. VN_RELE(vp);
  225. if(xfs_acl)
  226. _ACL_FREE(xfs_acl);
  227. return -error;
  228. }
  229. int
  230. xfs_acl_vremove(
  231. bhv_vnode_t *vp,
  232. int kind)
  233. {
  234. int error;
  235. VN_HOLD(vp);
  236. error = xfs_acl_allow_set(vp, kind);
  237. if (!error) {
  238. error = bhv_vop_attr_remove(vp, kind == _ACL_TYPE_DEFAULT?
  239. SGI_ACL_DEFAULT: SGI_ACL_FILE,
  240. ATTR_ROOT, sys_cred);
  241. if (error == ENOATTR)
  242. error = 0; /* 'scool */
  243. }
  244. VN_RELE(vp);
  245. return -error;
  246. }
  247. int
  248. xfs_acl_vset(
  249. bhv_vnode_t *vp,
  250. void *acl,
  251. size_t size,
  252. int kind)
  253. {
  254. posix_acl_xattr_header *ext_acl = acl;
  255. xfs_acl_t *xfs_acl;
  256. int error;
  257. int basicperms = 0; /* more than std unix perms? */
  258. if (!acl)
  259. return -EINVAL;
  260. if (!(_ACL_ALLOC(xfs_acl)))
  261. return -ENOMEM;
  262. error = posix_acl_xattr_to_xfs(ext_acl, size, xfs_acl);
  263. if (error) {
  264. _ACL_FREE(xfs_acl);
  265. return -error;
  266. }
  267. if (!xfs_acl->acl_cnt) {
  268. _ACL_FREE(xfs_acl);
  269. return 0;
  270. }
  271. VN_HOLD(vp);
  272. error = xfs_acl_allow_set(vp, kind);
  273. if (error)
  274. goto out;
  275. /* Incoming ACL exists, set file mode based on its value */
  276. if (kind == _ACL_TYPE_ACCESS)
  277. xfs_acl_setmode(vp, xfs_acl, &basicperms);
  278. /*
  279. * If we have more than std unix permissions, set up the actual attr.
  280. * Otherwise, delete any existing attr. This prevents us from
  281. * having actual attrs for permissions that can be stored in the
  282. * standard permission bits.
  283. */
  284. if (!basicperms) {
  285. xfs_acl_set_attr(vp, xfs_acl, kind, &error);
  286. } else {
  287. xfs_acl_vremove(vp, _ACL_TYPE_ACCESS);
  288. }
  289. out:
  290. VN_RELE(vp);
  291. _ACL_FREE(xfs_acl);
  292. return -error;
  293. }
  294. int
  295. xfs_acl_iaccess(
  296. xfs_inode_t *ip,
  297. mode_t mode,
  298. cred_t *cr)
  299. {
  300. xfs_acl_t *acl;
  301. int rval;
  302. if (!(_ACL_ALLOC(acl)))
  303. return -1;
  304. /* If the file has no ACL return -1. */
  305. rval = sizeof(xfs_acl_t);
  306. if (xfs_attr_fetch(ip, SGI_ACL_FILE, SGI_ACL_FILE_SIZE,
  307. (char *)acl, &rval, ATTR_ROOT | ATTR_KERNACCESS, cr)) {
  308. _ACL_FREE(acl);
  309. return -1;
  310. }
  311. xfs_acl_get_endian(acl);
  312. /* If the file has an empty ACL return -1. */
  313. if (acl->acl_cnt == XFS_ACL_NOT_PRESENT) {
  314. _ACL_FREE(acl);
  315. return -1;
  316. }
  317. /* Synchronize ACL with mode bits */
  318. xfs_acl_sync_mode(ip->i_d.di_mode, acl);
  319. rval = xfs_acl_access(ip->i_d.di_uid, ip->i_d.di_gid, acl, mode, cr);
  320. _ACL_FREE(acl);
  321. return rval;
  322. }
  323. STATIC int
  324. xfs_acl_allow_set(
  325. bhv_vnode_t *vp,
  326. int kind)
  327. {
  328. bhv_vattr_t va;
  329. int error;
  330. if (vp->v_inode.i_flags & (S_IMMUTABLE|S_APPEND))
  331. return EPERM;
  332. if (kind == _ACL_TYPE_DEFAULT && !VN_ISDIR(vp))
  333. return ENOTDIR;
  334. if (vp->v_vfsp->vfs_flag & VFS_RDONLY)
  335. return EROFS;
  336. va.va_mask = XFS_AT_UID;
  337. error = bhv_vop_getattr(vp, &va, 0, NULL);
  338. if (error)
  339. return error;
  340. if (va.va_uid != current->fsuid && !capable(CAP_FOWNER))
  341. return EPERM;
  342. return error;
  343. }
  344. /*
  345. * The access control process to determine the access permission:
  346. * if uid == file owner id, use the file owner bits.
  347. * if gid == file owner group id, use the file group bits.
  348. * scan ACL for a matching user or group, and use matched entry
  349. * permission. Use total permissions of all matching group entries,
  350. * until all acl entries are exhausted. The final permission produced
  351. * by matching acl entry or entries needs to be & with group permission.
  352. * if not owner, owning group, or matching entry in ACL, use file
  353. * other bits.
  354. */
  355. STATIC int
  356. xfs_acl_capability_check(
  357. mode_t mode,
  358. cred_t *cr)
  359. {
  360. if ((mode & ACL_READ) && !capable_cred(cr, CAP_DAC_READ_SEARCH))
  361. return EACCES;
  362. if ((mode & ACL_WRITE) && !capable_cred(cr, CAP_DAC_OVERRIDE))
  363. return EACCES;
  364. if ((mode & ACL_EXECUTE) && !capable_cred(cr, CAP_DAC_OVERRIDE))
  365. return EACCES;
  366. return 0;
  367. }
  368. /*
  369. * Note: cr is only used here for the capability check if the ACL test fails.
  370. * It is not used to find out the credentials uid or groups etc, as was
  371. * done in IRIX. It is assumed that the uid and groups for the current
  372. * thread are taken from "current" instead of the cr parameter.
  373. */
  374. STATIC int
  375. xfs_acl_access(
  376. uid_t fuid,
  377. gid_t fgid,
  378. xfs_acl_t *fap,
  379. mode_t md,
  380. cred_t *cr)
  381. {
  382. xfs_acl_entry_t matched;
  383. int i, allows;
  384. int maskallows = -1; /* true, but not 1, either */
  385. int seen_userobj = 0;
  386. matched.ae_tag = 0; /* Invalid type */
  387. matched.ae_perm = 0;
  388. md >>= 6; /* Normalize the bits for comparison */
  389. for (i = 0; i < fap->acl_cnt; i++) {
  390. /*
  391. * Break out if we've got a user_obj entry or
  392. * a user entry and the mask (and have processed USER_OBJ)
  393. */
  394. if (matched.ae_tag == ACL_USER_OBJ)
  395. break;
  396. if (matched.ae_tag == ACL_USER) {
  397. if (maskallows != -1 && seen_userobj)
  398. break;
  399. if (fap->acl_entry[i].ae_tag != ACL_MASK &&
  400. fap->acl_entry[i].ae_tag != ACL_USER_OBJ)
  401. continue;
  402. }
  403. /* True if this entry allows the requested access */
  404. allows = ((fap->acl_entry[i].ae_perm & md) == md);
  405. switch (fap->acl_entry[i].ae_tag) {
  406. case ACL_USER_OBJ:
  407. seen_userobj = 1;
  408. if (fuid != current->fsuid)
  409. continue;
  410. matched.ae_tag = ACL_USER_OBJ;
  411. matched.ae_perm = allows;
  412. break;
  413. case ACL_USER:
  414. if (fap->acl_entry[i].ae_id != current->fsuid)
  415. continue;
  416. matched.ae_tag = ACL_USER;
  417. matched.ae_perm = allows;
  418. break;
  419. case ACL_GROUP_OBJ:
  420. if ((matched.ae_tag == ACL_GROUP_OBJ ||
  421. matched.ae_tag == ACL_GROUP) && !allows)
  422. continue;
  423. if (!in_group_p(fgid))
  424. continue;
  425. matched.ae_tag = ACL_GROUP_OBJ;
  426. matched.ae_perm = allows;
  427. break;
  428. case ACL_GROUP:
  429. if ((matched.ae_tag == ACL_GROUP_OBJ ||
  430. matched.ae_tag == ACL_GROUP) && !allows)
  431. continue;
  432. if (!in_group_p(fap->acl_entry[i].ae_id))
  433. continue;
  434. matched.ae_tag = ACL_GROUP;
  435. matched.ae_perm = allows;
  436. break;
  437. case ACL_MASK:
  438. maskallows = allows;
  439. break;
  440. case ACL_OTHER:
  441. if (matched.ae_tag != 0)
  442. continue;
  443. matched.ae_tag = ACL_OTHER;
  444. matched.ae_perm = allows;
  445. break;
  446. }
  447. }
  448. /*
  449. * First possibility is that no matched entry allows access.
  450. * The capability to override DAC may exist, so check for it.
  451. */
  452. switch (matched.ae_tag) {
  453. case ACL_OTHER:
  454. case ACL_USER_OBJ:
  455. if (matched.ae_perm)
  456. return 0;
  457. break;
  458. case ACL_USER:
  459. case ACL_GROUP_OBJ:
  460. case ACL_GROUP:
  461. if (maskallows && matched.ae_perm)
  462. return 0;
  463. break;
  464. case 0:
  465. break;
  466. }
  467. return xfs_acl_capability_check(md, cr);
  468. }
  469. /*
  470. * ACL validity checker.
  471. * This acl validation routine checks each ACL entry read in makes sense.
  472. */
  473. STATIC int
  474. xfs_acl_invalid(
  475. xfs_acl_t *aclp)
  476. {
  477. xfs_acl_entry_t *entry, *e;
  478. int user = 0, group = 0, other = 0, mask = 0;
  479. int mask_required = 0;
  480. int i, j;
  481. if (!aclp)
  482. goto acl_invalid;
  483. if (aclp->acl_cnt > XFS_ACL_MAX_ENTRIES)
  484. goto acl_invalid;
  485. for (i = 0; i < aclp->acl_cnt; i++) {
  486. entry = &aclp->acl_entry[i];
  487. switch (entry->ae_tag) {
  488. case ACL_USER_OBJ:
  489. if (user++)
  490. goto acl_invalid;
  491. break;
  492. case ACL_GROUP_OBJ:
  493. if (group++)
  494. goto acl_invalid;
  495. break;
  496. case ACL_OTHER:
  497. if (other++)
  498. goto acl_invalid;
  499. break;
  500. case ACL_USER:
  501. case ACL_GROUP:
  502. for (j = i + 1; j < aclp->acl_cnt; j++) {
  503. e = &aclp->acl_entry[j];
  504. if (e->ae_id == entry->ae_id &&
  505. e->ae_tag == entry->ae_tag)
  506. goto acl_invalid;
  507. }
  508. mask_required++;
  509. break;
  510. case ACL_MASK:
  511. if (mask++)
  512. goto acl_invalid;
  513. break;
  514. default:
  515. goto acl_invalid;
  516. }
  517. }
  518. if (!user || !group || !other || (mask_required && !mask))
  519. goto acl_invalid;
  520. else
  521. return 0;
  522. acl_invalid:
  523. return EINVAL;
  524. }
  525. /*
  526. * Do ACL endian conversion.
  527. */
  528. STATIC void
  529. xfs_acl_get_endian(
  530. xfs_acl_t *aclp)
  531. {
  532. xfs_acl_entry_t *ace, *end;
  533. INT_SET(aclp->acl_cnt, ARCH_CONVERT, aclp->acl_cnt);
  534. end = &aclp->acl_entry[0]+aclp->acl_cnt;
  535. for (ace = &aclp->acl_entry[0]; ace < end; ace++) {
  536. INT_SET(ace->ae_tag, ARCH_CONVERT, ace->ae_tag);
  537. INT_SET(ace->ae_id, ARCH_CONVERT, ace->ae_id);
  538. INT_SET(ace->ae_perm, ARCH_CONVERT, ace->ae_perm);
  539. }
  540. }
  541. /*
  542. * Get the ACL from the EA and do endian conversion.
  543. */
  544. STATIC void
  545. xfs_acl_get_attr(
  546. bhv_vnode_t *vp,
  547. xfs_acl_t *aclp,
  548. int kind,
  549. int flags,
  550. int *error)
  551. {
  552. int len = sizeof(xfs_acl_t);
  553. ASSERT((flags & ATTR_KERNOVAL) ? (aclp == NULL) : 1);
  554. flags |= ATTR_ROOT;
  555. *error = bhv_vop_attr_get(vp, kind == _ACL_TYPE_ACCESS ?
  556. SGI_ACL_FILE : SGI_ACL_DEFAULT,
  557. (char *)aclp, &len, flags, sys_cred);
  558. if (*error || (flags & ATTR_KERNOVAL))
  559. return;
  560. xfs_acl_get_endian(aclp);
  561. }
  562. /*
  563. * Set the EA with the ACL and do endian conversion.
  564. */
  565. STATIC void
  566. xfs_acl_set_attr(
  567. bhv_vnode_t *vp,
  568. xfs_acl_t *aclp,
  569. int kind,
  570. int *error)
  571. {
  572. xfs_acl_entry_t *ace, *newace, *end;
  573. xfs_acl_t *newacl;
  574. int len;
  575. if (!(_ACL_ALLOC(newacl))) {
  576. *error = ENOMEM;
  577. return;
  578. }
  579. len = sizeof(xfs_acl_t) -
  580. (sizeof(xfs_acl_entry_t) * (XFS_ACL_MAX_ENTRIES - aclp->acl_cnt));
  581. end = &aclp->acl_entry[0]+aclp->acl_cnt;
  582. for (ace = &aclp->acl_entry[0], newace = &newacl->acl_entry[0];
  583. ace < end;
  584. ace++, newace++) {
  585. INT_SET(newace->ae_tag, ARCH_CONVERT, ace->ae_tag);
  586. INT_SET(newace->ae_id, ARCH_CONVERT, ace->ae_id);
  587. INT_SET(newace->ae_perm, ARCH_CONVERT, ace->ae_perm);
  588. }
  589. INT_SET(newacl->acl_cnt, ARCH_CONVERT, aclp->acl_cnt);
  590. *error = bhv_vop_attr_set(vp, kind == _ACL_TYPE_ACCESS ?
  591. SGI_ACL_FILE: SGI_ACL_DEFAULT,
  592. (char *)newacl, len, ATTR_ROOT, sys_cred);
  593. _ACL_FREE(newacl);
  594. }
  595. int
  596. xfs_acl_vtoacl(
  597. bhv_vnode_t *vp,
  598. xfs_acl_t *access_acl,
  599. xfs_acl_t *default_acl)
  600. {
  601. bhv_vattr_t va;
  602. int error = 0;
  603. if (access_acl) {
  604. /*
  605. * Get the Access ACL and the mode. If either cannot
  606. * be obtained for some reason, invalidate the access ACL.
  607. */
  608. xfs_acl_get_attr(vp, access_acl, _ACL_TYPE_ACCESS, 0, &error);
  609. if (!error) {
  610. /* Got the ACL, need the mode... */
  611. va.va_mask = XFS_AT_MODE;
  612. error = bhv_vop_getattr(vp, &va, 0, sys_cred);
  613. }
  614. if (error)
  615. access_acl->acl_cnt = XFS_ACL_NOT_PRESENT;
  616. else /* We have a good ACL and the file mode, synchronize. */
  617. xfs_acl_sync_mode(va.va_mode, access_acl);
  618. }
  619. if (default_acl) {
  620. xfs_acl_get_attr(vp, default_acl, _ACL_TYPE_DEFAULT, 0, &error);
  621. if (error)
  622. default_acl->acl_cnt = XFS_ACL_NOT_PRESENT;
  623. }
  624. return error;
  625. }
  626. /*
  627. * This function retrieves the parent directory's acl, processes it
  628. * and lets the child inherit the acl(s) that it should.
  629. */
  630. int
  631. xfs_acl_inherit(
  632. bhv_vnode_t *vp,
  633. bhv_vattr_t *vap,
  634. xfs_acl_t *pdaclp)
  635. {
  636. xfs_acl_t *cacl;
  637. int error = 0;
  638. int basicperms = 0;
  639. /*
  640. * If the parent does not have a default ACL, or it's an
  641. * invalid ACL, we're done.
  642. */
  643. if (!vp)
  644. return 0;
  645. if (!pdaclp || xfs_acl_invalid(pdaclp))
  646. return 0;
  647. /*
  648. * Copy the default ACL of the containing directory to
  649. * the access ACL of the new file and use the mode that
  650. * was passed in to set up the correct initial values for
  651. * the u::,g::[m::], and o:: entries. This is what makes
  652. * umask() "work" with ACL's.
  653. */
  654. if (!(_ACL_ALLOC(cacl)))
  655. return ENOMEM;
  656. memcpy(cacl, pdaclp, sizeof(xfs_acl_t));
  657. xfs_acl_filter_mode(vap->va_mode, cacl);
  658. xfs_acl_setmode(vp, cacl, &basicperms);
  659. /*
  660. * Set the Default and Access ACL on the file. The mode is already
  661. * set on the file, so we don't need to worry about that.
  662. *
  663. * If the new file is a directory, its default ACL is a copy of
  664. * the containing directory's default ACL.
  665. */
  666. if (VN_ISDIR(vp))
  667. xfs_acl_set_attr(vp, pdaclp, _ACL_TYPE_DEFAULT, &error);
  668. if (!error && !basicperms)
  669. xfs_acl_set_attr(vp, cacl, _ACL_TYPE_ACCESS, &error);
  670. _ACL_FREE(cacl);
  671. return error;
  672. }
  673. /*
  674. * Set up the correct mode on the file based on the supplied ACL. This
  675. * makes sure that the mode on the file reflects the state of the
  676. * u::,g::[m::], and o:: entries in the ACL. Since the mode is where
  677. * the ACL is going to get the permissions for these entries, we must
  678. * synchronize the mode whenever we set the ACL on a file.
  679. */
  680. STATIC int
  681. xfs_acl_setmode(
  682. bhv_vnode_t *vp,
  683. xfs_acl_t *acl,
  684. int *basicperms)
  685. {
  686. bhv_vattr_t va;
  687. xfs_acl_entry_t *ap;
  688. xfs_acl_entry_t *gap = NULL;
  689. int i, error, nomask = 1;
  690. *basicperms = 1;
  691. if (acl->acl_cnt == XFS_ACL_NOT_PRESENT)
  692. return 0;
  693. /*
  694. * Copy the u::, g::, o::, and m:: bits from the ACL into the
  695. * mode. The m:: bits take precedence over the g:: bits.
  696. */
  697. va.va_mask = XFS_AT_MODE;
  698. error = bhv_vop_getattr(vp, &va, 0, sys_cred);
  699. if (error)
  700. return error;
  701. va.va_mask = XFS_AT_MODE;
  702. va.va_mode &= ~(S_IRWXU|S_IRWXG|S_IRWXO);
  703. ap = acl->acl_entry;
  704. for (i = 0; i < acl->acl_cnt; ++i) {
  705. switch (ap->ae_tag) {
  706. case ACL_USER_OBJ:
  707. va.va_mode |= ap->ae_perm << 6;
  708. break;
  709. case ACL_GROUP_OBJ:
  710. gap = ap;
  711. break;
  712. case ACL_MASK: /* more than just standard modes */
  713. nomask = 0;
  714. va.va_mode |= ap->ae_perm << 3;
  715. *basicperms = 0;
  716. break;
  717. case ACL_OTHER:
  718. va.va_mode |= ap->ae_perm;
  719. break;
  720. default: /* more than just standard modes */
  721. *basicperms = 0;
  722. break;
  723. }
  724. ap++;
  725. }
  726. /* Set the group bits from ACL_GROUP_OBJ if there's no ACL_MASK */
  727. if (gap && nomask)
  728. va.va_mode |= gap->ae_perm << 3;
  729. return bhv_vop_setattr(vp, &va, 0, sys_cred);
  730. }
  731. /*
  732. * The permissions for the special ACL entries (u::, g::[m::], o::) are
  733. * actually stored in the file mode (if there is both a group and a mask,
  734. * the group is stored in the ACL entry and the mask is stored on the file).
  735. * This allows the mode to remain automatically in sync with the ACL without
  736. * the need for a call-back to the ACL system at every point where the mode
  737. * could change. This function takes the permissions from the specified mode
  738. * and places it in the supplied ACL.
  739. *
  740. * This implementation draws its validity from the fact that, when the ACL
  741. * was assigned, the mode was copied from the ACL.
  742. * If the mode did not change, therefore, the mode remains exactly what was
  743. * taken from the special ACL entries at assignment.
  744. * If a subsequent chmod() was done, the POSIX spec says that the change in
  745. * mode must cause an update to the ACL seen at user level and used for
  746. * access checks. Before and after a mode change, therefore, the file mode
  747. * most accurately reflects what the special ACL entries should permit/deny.
  748. *
  749. * CAVEAT: If someone sets the SGI_ACL_FILE attribute directly,
  750. * the existing mode bits will override whatever is in the
  751. * ACL. Similarly, if there is a pre-existing ACL that was
  752. * never in sync with its mode (owing to a bug in 6.5 and
  753. * before), it will now magically (or mystically) be
  754. * synchronized. This could cause slight astonishment, but
  755. * it is better than inconsistent permissions.
  756. *
  757. * The supplied ACL is a template that may contain any combination
  758. * of special entries. These are treated as place holders when we fill
  759. * out the ACL. This routine does not add or remove special entries, it
  760. * simply unites each special entry with its associated set of permissions.
  761. */
  762. STATIC void
  763. xfs_acl_sync_mode(
  764. mode_t mode,
  765. xfs_acl_t *acl)
  766. {
  767. int i, nomask = 1;
  768. xfs_acl_entry_t *ap;
  769. xfs_acl_entry_t *gap = NULL;
  770. /*
  771. * Set ACL entries. POSIX1003.1eD16 requires that the MASK
  772. * be set instead of the GROUP entry, if there is a MASK.
  773. */
  774. for (ap = acl->acl_entry, i = 0; i < acl->acl_cnt; ap++, i++) {
  775. switch (ap->ae_tag) {
  776. case ACL_USER_OBJ:
  777. ap->ae_perm = (mode >> 6) & 0x7;
  778. break;
  779. case ACL_GROUP_OBJ:
  780. gap = ap;
  781. break;
  782. case ACL_MASK:
  783. nomask = 0;
  784. ap->ae_perm = (mode >> 3) & 0x7;
  785. break;
  786. case ACL_OTHER:
  787. ap->ae_perm = mode & 0x7;
  788. break;
  789. default:
  790. break;
  791. }
  792. }
  793. /* Set the ACL_GROUP_OBJ if there's no ACL_MASK */
  794. if (gap && nomask)
  795. gap->ae_perm = (mode >> 3) & 0x7;
  796. }
  797. /*
  798. * When inheriting an Access ACL from a directory Default ACL,
  799. * the ACL bits are set to the intersection of the ACL default
  800. * permission bits and the file permission bits in mode. If there
  801. * are no permission bits on the file then we must not give them
  802. * the ACL. This is what what makes umask() work with ACLs.
  803. */
  804. STATIC void
  805. xfs_acl_filter_mode(
  806. mode_t mode,
  807. xfs_acl_t *acl)
  808. {
  809. int i, nomask = 1;
  810. xfs_acl_entry_t *ap;
  811. xfs_acl_entry_t *gap = NULL;
  812. /*
  813. * Set ACL entries. POSIX1003.1eD16 requires that the MASK
  814. * be merged with GROUP entry, if there is a MASK.
  815. */
  816. for (ap = acl->acl_entry, i = 0; i < acl->acl_cnt; ap++, i++) {
  817. switch (ap->ae_tag) {
  818. case ACL_USER_OBJ:
  819. ap->ae_perm &= (mode >> 6) & 0x7;
  820. break;
  821. case ACL_GROUP_OBJ:
  822. gap = ap;
  823. break;
  824. case ACL_MASK:
  825. nomask = 0;
  826. ap->ae_perm &= (mode >> 3) & 0x7;
  827. break;
  828. case ACL_OTHER:
  829. ap->ae_perm &= mode & 0x7;
  830. break;
  831. default:
  832. break;
  833. }
  834. }
  835. /* Set the ACL_GROUP_OBJ if there's no ACL_MASK */
  836. if (gap && nomask)
  837. gap->ae_perm &= (mode >> 3) & 0x7;
  838. }