xfs_acl.c 22 KB

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