xfs_acl.c 21 KB

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