aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2008-02-04 20:13:24 -0500
committerLachlan McIlroy <lachlan@redback.melbourne.sgi.com>2008-02-07 02:22:38 -0500
commit4576758db5817a91b8974c696247d459dc653db2 (patch)
tree43b5b471510f0981ea2dc668ca7591a75831f111
parentf6aa7f2184330262e1cb5f7802536e5346bd46a3 (diff)
[XFS] use generic_permission
Now that all direct caller of xfs_iaccess are gone we can kill xfs_iaccess and xfs_access and just use generic_permission with a check_acl callback. This is required for the per-mount read-only patchset in -mm to work properly with XFS. SGI-PV: 971186 SGI-Modid: xfs-linux-melb:xfs-kern:30370a Signed-off-by: Christoph Hellwig <hch@infradead.org> Signed-off-by: Lachlan McIlroy <lachlan@sgi.com>
-rw-r--r--fs/xfs/linux-2.6/xfs_iops.c27
-rw-r--r--fs/xfs/xfs_acl.c30
-rw-r--r--fs/xfs/xfs_acl.h2
-rw-r--r--fs/xfs/xfs_inode.c63
-rw-r--r--fs/xfs/xfs_inode.h1
-rw-r--r--fs/xfs/xfs_vnodeops.c21
-rw-r--r--fs/xfs/xfs_vnodeops.h1
7 files changed, 25 insertions, 120 deletions
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c
index 1ecd86a8c6e6..c3231a519361 100644
--- a/fs/xfs/linux-2.6/xfs_iops.c
+++ b/fs/xfs/linux-2.6/xfs_iops.c
@@ -559,12 +559,31 @@ xfs_vn_put_link(
559 559
560#ifdef CONFIG_XFS_POSIX_ACL 560#ifdef CONFIG_XFS_POSIX_ACL
561STATIC int 561STATIC int
562xfs_check_acl(
563 struct inode *inode,
564 int mask)
565{
566 struct xfs_inode *ip = XFS_I(inode);
567 int error;
568
569 xfs_itrace_entry(ip);
570
571 if (XFS_IFORK_Q(ip)) {
572 error = xfs_acl_iaccess(ip, mask, NULL);
573 if (error != -1)
574 return -error;
575 }
576
577 return -EAGAIN;
578}
579
580STATIC int
562xfs_vn_permission( 581xfs_vn_permission(
563 struct inode *inode, 582 struct inode *inode,
564 int mode, 583 int mask,
565 struct nameidata *nd) 584 struct nameidata *nd)
566{ 585{
567 return -xfs_access(XFS_I(inode), mode << 6, NULL); 586 return generic_permission(inode, mask, xfs_check_acl);
568} 587}
569#else 588#else
570#define xfs_vn_permission NULL 589#define xfs_vn_permission NULL
diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c
index 5bfb66f33caf..7272fe39a92d 100644
--- a/fs/xfs/xfs_acl.c
+++ b/fs/xfs/xfs_acl.c
@@ -392,32 +392,6 @@ xfs_acl_allow_set(
392} 392}
393 393
394/* 394/*
395 * The access control process to determine the access permission:
396 * if uid == file owner id, use the file owner bits.
397 * if gid == file owner group id, use the file group bits.
398 * scan ACL for a matching user or group, and use matched entry
399 * permission. Use total permissions of all matching group entries,
400 * until all acl entries are exhausted. The final permission produced
401 * by matching acl entry or entries needs to be & with group permission.
402 * if not owner, owning group, or matching entry in ACL, use file
403 * other bits.
404 */
405STATIC int
406xfs_acl_capability_check(
407 mode_t mode,
408 cred_t *cr)
409{
410 if ((mode & ACL_READ) && !capable_cred(cr, CAP_DAC_READ_SEARCH))
411 return EACCES;
412 if ((mode & ACL_WRITE) && !capable_cred(cr, CAP_DAC_OVERRIDE))
413 return EACCES;
414 if ((mode & ACL_EXECUTE) && !capable_cred(cr, CAP_DAC_OVERRIDE))
415 return EACCES;
416
417 return 0;
418}
419
420/*
421 * Note: cr is only used here for the capability check if the ACL test fails. 395 * Note: cr is only used here for the capability check if the ACL test fails.
422 * It is not used to find out the credentials uid or groups etc, as was 396 * It is not used to find out the credentials uid or groups etc, as was
423 * done in IRIX. It is assumed that the uid and groups for the current 397 * done in IRIX. It is assumed that the uid and groups for the current
@@ -438,7 +412,6 @@ xfs_acl_access(
438 412
439 matched.ae_tag = 0; /* Invalid type */ 413 matched.ae_tag = 0; /* Invalid type */
440 matched.ae_perm = 0; 414 matched.ae_perm = 0;
441 md >>= 6; /* Normalize the bits for comparison */
442 415
443 for (i = 0; i < fap->acl_cnt; i++) { 416 for (i = 0; i < fap->acl_cnt; i++) {
444 /* 417 /*
@@ -520,7 +493,8 @@ xfs_acl_access(
520 break; 493 break;
521 } 494 }
522 495
523 return xfs_acl_capability_check(md, cr); 496 /* EACCES tells generic_permission to check for capability overrides */
497 return EACCES;
524} 498}
525 499
526/* 500/*
diff --git a/fs/xfs/xfs_acl.h b/fs/xfs/xfs_acl.h
index 34b7d3391299..332a772461c4 100644
--- a/fs/xfs/xfs_acl.h
+++ b/fs/xfs/xfs_acl.h
@@ -75,7 +75,6 @@ extern int xfs_acl_vremove(bhv_vnode_t *, int);
75#define _ACL_GET_DEFAULT(pv,pd) (xfs_acl_vtoacl(pv,NULL,pd) == 0) 75#define _ACL_GET_DEFAULT(pv,pd) (xfs_acl_vtoacl(pv,NULL,pd) == 0)
76#define _ACL_ACCESS_EXISTS xfs_acl_vhasacl_access 76#define _ACL_ACCESS_EXISTS xfs_acl_vhasacl_access
77#define _ACL_DEFAULT_EXISTS xfs_acl_vhasacl_default 77#define _ACL_DEFAULT_EXISTS xfs_acl_vhasacl_default
78#define _ACL_XFS_IACCESS(i,m,c) (XFS_IFORK_Q(i) ? xfs_acl_iaccess(i,m,c) : -1)
79 78
80#define _ACL_ALLOC(a) ((a) = kmem_zone_alloc(xfs_acl_zone, KM_SLEEP)) 79#define _ACL_ALLOC(a) ((a) = kmem_zone_alloc(xfs_acl_zone, KM_SLEEP))
81#define _ACL_FREE(a) ((a)? kmem_zone_free(xfs_acl_zone, (a)):(void)0) 80#define _ACL_FREE(a) ((a)? kmem_zone_free(xfs_acl_zone, (a)):(void)0)
@@ -95,7 +94,6 @@ extern int xfs_acl_vremove(bhv_vnode_t *, int);
95#define _ACL_GET_DEFAULT(pv,pd) (0) 94#define _ACL_GET_DEFAULT(pv,pd) (0)
96#define _ACL_ACCESS_EXISTS (NULL) 95#define _ACL_ACCESS_EXISTS (NULL)
97#define _ACL_DEFAULT_EXISTS (NULL) 96#define _ACL_DEFAULT_EXISTS (NULL)
98#define _ACL_XFS_IACCESS(i,m,c) (-1)
99#endif 97#endif
100 98
101#endif /* __XFS_ACL_H__ */ 99#endif /* __XFS_ACL_H__ */
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 75b636c14876..a550546a7083 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -3583,69 +3583,6 @@ xfs_iflush_all(
3583 XFS_MOUNT_IUNLOCK(mp); 3583 XFS_MOUNT_IUNLOCK(mp);
3584} 3584}
3585 3585
3586/*
3587 * xfs_iaccess: check accessibility of inode for mode.
3588 */
3589int
3590xfs_iaccess(
3591 xfs_inode_t *ip,
3592 mode_t mode,
3593 cred_t *cr)
3594{
3595 int error;
3596 mode_t orgmode = mode;
3597 struct inode *inode = vn_to_inode(XFS_ITOV(ip));
3598
3599 if (mode & S_IWUSR) {
3600 umode_t imode = inode->i_mode;
3601
3602 if (IS_RDONLY(inode) &&
3603 (S_ISREG(imode) || S_ISDIR(imode) || S_ISLNK(imode)))
3604 return XFS_ERROR(EROFS);
3605
3606 if (IS_IMMUTABLE(inode))
3607 return XFS_ERROR(EACCES);
3608 }
3609
3610 /*
3611 * If there's an Access Control List it's used instead of
3612 * the mode bits.
3613 */
3614 if ((error = _ACL_XFS_IACCESS(ip, mode, cr)) != -1)
3615 return error ? XFS_ERROR(error) : 0;
3616
3617 if (current_fsuid(cr) != ip->i_d.di_uid) {
3618 mode >>= 3;
3619 if (!in_group_p((gid_t)ip->i_d.di_gid))
3620 mode >>= 3;
3621 }
3622
3623 /*
3624 * If the DACs are ok we don't need any capability check.
3625 */
3626 if ((ip->i_d.di_mode & mode) == mode)
3627 return 0;
3628 /*
3629 * Read/write DACs are always overridable.
3630 * Executable DACs are overridable if at least one exec bit is set.
3631 */
3632 if (!(orgmode & S_IXUSR) ||
3633 (inode->i_mode & S_IXUGO) || S_ISDIR(inode->i_mode))
3634 if (capable_cred(cr, CAP_DAC_OVERRIDE))
3635 return 0;
3636
3637 if ((orgmode == S_IRUSR) ||
3638 (S_ISDIR(inode->i_mode) && (!(orgmode & S_IWUSR)))) {
3639 if (capable_cred(cr, CAP_DAC_READ_SEARCH))
3640 return 0;
3641#ifdef NOISE
3642 cmn_err(CE_NOTE, "Ick: mode=%o, orgmode=%o", mode, orgmode);
3643#endif /* NOISE */
3644 return XFS_ERROR(EACCES);
3645 }
3646 return XFS_ERROR(EACCES);
3647}
3648
3649#ifdef XFS_ILOCK_TRACE 3586#ifdef XFS_ILOCK_TRACE
3650ktrace_t *xfs_ilock_trace_buf; 3587ktrace_t *xfs_ilock_trace_buf;
3651 3588
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index a8d6f5e251aa..bfcd72cbaeea 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -550,7 +550,6 @@ void xfs_iunpin(xfs_inode_t *);
550int xfs_iextents_copy(xfs_inode_t *, xfs_bmbt_rec_t *, int); 550int xfs_iextents_copy(xfs_inode_t *, xfs_bmbt_rec_t *, int);
551int xfs_iflush(xfs_inode_t *, uint); 551int xfs_iflush(xfs_inode_t *, uint);
552void xfs_iflush_all(struct xfs_mount *); 552void xfs_iflush_all(struct xfs_mount *);
553int xfs_iaccess(xfs_inode_t *, mode_t, cred_t *);
554void xfs_ichgtime(xfs_inode_t *, int); 553void xfs_ichgtime(xfs_inode_t *, int);
555xfs_fsize_t xfs_file_last_byte(xfs_inode_t *); 554xfs_fsize_t xfs_file_last_byte(xfs_inode_t *);
556void xfs_lock_inodes(xfs_inode_t **, int, int, uint); 555void xfs_lock_inodes(xfs_inode_t **, int, int, uint);
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index 076555e8763f..27e1bea8169f 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -898,27 +898,6 @@ xfs_setattr(
898 return code; 898 return code;
899} 899}
900 900
901
902/*
903 * xfs_access
904 * Null conversion from vnode mode bits to inode mode bits, as in efs.
905 */
906int
907xfs_access(
908 xfs_inode_t *ip,
909 int mode,
910 cred_t *credp)
911{
912 int error;
913
914 xfs_itrace_entry(ip);
915 xfs_ilock(ip, XFS_ILOCK_SHARED);
916 error = xfs_iaccess(ip, mode, credp);
917 xfs_iunlock(ip, XFS_ILOCK_SHARED);
918 return error;
919}
920
921
922/* 901/*
923 * The maximum pathlen is 1024 bytes. Since the minimum file system 902 * The maximum pathlen is 1024 bytes. Since the minimum file system
924 * blocksize is 512 bytes, we can get a max of 2 extents back from 903 * blocksize is 512 bytes, we can get a max of 2 extents back from
diff --git a/fs/xfs/xfs_vnodeops.h b/fs/xfs/xfs_vnodeops.h
index a501aeffb808..4e3970f0e5e3 100644
--- a/fs/xfs/xfs_vnodeops.h
+++ b/fs/xfs/xfs_vnodeops.h
@@ -18,7 +18,6 @@ int xfs_open(struct xfs_inode *ip);
18int xfs_getattr(struct xfs_inode *ip, struct bhv_vattr *vap, int flags); 18int xfs_getattr(struct xfs_inode *ip, struct bhv_vattr *vap, int flags);
19int xfs_setattr(struct xfs_inode *ip, struct bhv_vattr *vap, int flags, 19int xfs_setattr(struct xfs_inode *ip, struct bhv_vattr *vap, int flags,
20 struct cred *credp); 20 struct cred *credp);
21int xfs_access(struct xfs_inode *ip, int mode, struct cred *credp);
22int xfs_readlink(struct xfs_inode *ip, char *link); 21int xfs_readlink(struct xfs_inode *ip, char *link);
23int xfs_fsync(struct xfs_inode *ip, int flag, xfs_off_t start, 22int xfs_fsync(struct xfs_inode *ip, int flag, xfs_off_t start,
24 xfs_off_t stop); 23 xfs_off_t stop);