xfs_acl.c 22 KB

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