diff options
author | Christoph Hellwig <hch@infradead.org> | 2008-02-04 20:13:24 -0500 |
---|---|---|
committer | Lachlan McIlroy <lachlan@redback.melbourne.sgi.com> | 2008-02-07 02:22:38 -0500 |
commit | 4576758db5817a91b8974c696247d459dc653db2 (patch) | |
tree | 43b5b471510f0981ea2dc668ca7591a75831f111 /fs/xfs | |
parent | f6aa7f2184330262e1cb5f7802536e5346bd46a3 (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>
Diffstat (limited to 'fs/xfs')
-rw-r--r-- | fs/xfs/linux-2.6/xfs_iops.c | 27 | ||||
-rw-r--r-- | fs/xfs/xfs_acl.c | 30 | ||||
-rw-r--r-- | fs/xfs/xfs_acl.h | 2 | ||||
-rw-r--r-- | fs/xfs/xfs_inode.c | 63 | ||||
-rw-r--r-- | fs/xfs/xfs_inode.h | 1 | ||||
-rw-r--r-- | fs/xfs/xfs_vnodeops.c | 21 | ||||
-rw-r--r-- | fs/xfs/xfs_vnodeops.h | 1 |
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 |
561 | STATIC int | 561 | STATIC int |
562 | xfs_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 | |||
580 | STATIC int | ||
562 | xfs_vn_permission( | 581 | xfs_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 | */ | ||
405 | STATIC int | ||
406 | xfs_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 | */ | ||
3589 | int | ||
3590 | xfs_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 |
3650 | ktrace_t *xfs_ilock_trace_buf; | 3587 | ktrace_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 *); | |||
550 | int xfs_iextents_copy(xfs_inode_t *, xfs_bmbt_rec_t *, int); | 550 | int xfs_iextents_copy(xfs_inode_t *, xfs_bmbt_rec_t *, int); |
551 | int xfs_iflush(xfs_inode_t *, uint); | 551 | int xfs_iflush(xfs_inode_t *, uint); |
552 | void xfs_iflush_all(struct xfs_mount *); | 552 | void xfs_iflush_all(struct xfs_mount *); |
553 | int xfs_iaccess(xfs_inode_t *, mode_t, cred_t *); | ||
554 | void xfs_ichgtime(xfs_inode_t *, int); | 553 | void xfs_ichgtime(xfs_inode_t *, int); |
555 | xfs_fsize_t xfs_file_last_byte(xfs_inode_t *); | 554 | xfs_fsize_t xfs_file_last_byte(xfs_inode_t *); |
556 | void xfs_lock_inodes(xfs_inode_t **, int, int, uint); | 555 | void 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 | */ | ||
906 | int | ||
907 | xfs_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); | |||
18 | int xfs_getattr(struct xfs_inode *ip, struct bhv_vattr *vap, int flags); | 18 | int xfs_getattr(struct xfs_inode *ip, struct bhv_vattr *vap, int flags); |
19 | int xfs_setattr(struct xfs_inode *ip, struct bhv_vattr *vap, int flags, | 19 | int xfs_setattr(struct xfs_inode *ip, struct bhv_vattr *vap, int flags, |
20 | struct cred *credp); | 20 | struct cred *credp); |
21 | int xfs_access(struct xfs_inode *ip, int mode, struct cred *credp); | ||
22 | int xfs_readlink(struct xfs_inode *ip, char *link); | 21 | int xfs_readlink(struct xfs_inode *ip, char *link); |
23 | int xfs_fsync(struct xfs_inode *ip, int flag, xfs_off_t start, | 22 | int xfs_fsync(struct xfs_inode *ip, int flag, xfs_off_t start, |
24 | xfs_off_t stop); | 23 | xfs_off_t stop); |