[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>
This commit is contained in:
parent
f6aa7f2184
commit
4576758db5
@ -559,12 +559,31 @@ xfs_vn_put_link(
|
|||||||
|
|
||||||
#ifdef CONFIG_XFS_POSIX_ACL
|
#ifdef CONFIG_XFS_POSIX_ACL
|
||||||
STATIC int
|
STATIC int
|
||||||
xfs_vn_permission(
|
xfs_check_acl(
|
||||||
struct inode *inode,
|
struct inode *inode,
|
||||||
int mode,
|
int mask)
|
||||||
struct nameidata *nd)
|
|
||||||
{
|
{
|
||||||
return -xfs_access(XFS_I(inode), mode << 6, NULL);
|
struct xfs_inode *ip = XFS_I(inode);
|
||||||
|
int error;
|
||||||
|
|
||||||
|
xfs_itrace_entry(ip);
|
||||||
|
|
||||||
|
if (XFS_IFORK_Q(ip)) {
|
||||||
|
error = xfs_acl_iaccess(ip, mask, NULL);
|
||||||
|
if (error != -1)
|
||||||
|
return -error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC int
|
||||||
|
xfs_vn_permission(
|
||||||
|
struct inode *inode,
|
||||||
|
int mask,
|
||||||
|
struct nameidata *nd)
|
||||||
|
{
|
||||||
|
return generic_permission(inode, mask, xfs_check_acl);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#define xfs_vn_permission NULL
|
#define xfs_vn_permission NULL
|
||||||
|
@ -391,32 +391,6 @@ xfs_acl_allow_set(
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* The access control process to determine the access permission:
|
|
||||||
* if uid == file owner id, use the file owner bits.
|
|
||||||
* if gid == file owner group id, use the file group bits.
|
|
||||||
* scan ACL for a matching user or group, and use matched entry
|
|
||||||
* permission. Use total permissions of all matching group entries,
|
|
||||||
* until all acl entries are exhausted. The final permission produced
|
|
||||||
* by matching acl entry or entries needs to be & with group permission.
|
|
||||||
* if not owner, owning group, or matching entry in ACL, use file
|
|
||||||
* other bits.
|
|
||||||
*/
|
|
||||||
STATIC int
|
|
||||||
xfs_acl_capability_check(
|
|
||||||
mode_t mode,
|
|
||||||
cred_t *cr)
|
|
||||||
{
|
|
||||||
if ((mode & ACL_READ) && !capable_cred(cr, CAP_DAC_READ_SEARCH))
|
|
||||||
return EACCES;
|
|
||||||
if ((mode & ACL_WRITE) && !capable_cred(cr, CAP_DAC_OVERRIDE))
|
|
||||||
return EACCES;
|
|
||||||
if ((mode & ACL_EXECUTE) && !capable_cred(cr, CAP_DAC_OVERRIDE))
|
|
||||||
return EACCES;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note: cr is only used here for the capability check if the ACL test fails.
|
* Note: cr is only used here for the capability check if the ACL test fails.
|
||||||
* It is not used to find out the credentials uid or groups etc, as was
|
* It is not used to find out the credentials uid or groups etc, as was
|
||||||
@ -438,7 +412,6 @@ xfs_acl_access(
|
|||||||
|
|
||||||
matched.ae_tag = 0; /* Invalid type */
|
matched.ae_tag = 0; /* Invalid type */
|
||||||
matched.ae_perm = 0;
|
matched.ae_perm = 0;
|
||||||
md >>= 6; /* Normalize the bits for comparison */
|
|
||||||
|
|
||||||
for (i = 0; i < fap->acl_cnt; i++) {
|
for (i = 0; i < fap->acl_cnt; i++) {
|
||||||
/*
|
/*
|
||||||
@ -520,7 +493,8 @@ xfs_acl_access(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return xfs_acl_capability_check(md, cr);
|
/* EACCES tells generic_permission to check for capability overrides */
|
||||||
|
return EACCES;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -75,7 +75,6 @@ extern int xfs_acl_vremove(bhv_vnode_t *, int);
|
|||||||
#define _ACL_GET_DEFAULT(pv,pd) (xfs_acl_vtoacl(pv,NULL,pd) == 0)
|
#define _ACL_GET_DEFAULT(pv,pd) (xfs_acl_vtoacl(pv,NULL,pd) == 0)
|
||||||
#define _ACL_ACCESS_EXISTS xfs_acl_vhasacl_access
|
#define _ACL_ACCESS_EXISTS xfs_acl_vhasacl_access
|
||||||
#define _ACL_DEFAULT_EXISTS xfs_acl_vhasacl_default
|
#define _ACL_DEFAULT_EXISTS xfs_acl_vhasacl_default
|
||||||
#define _ACL_XFS_IACCESS(i,m,c) (XFS_IFORK_Q(i) ? xfs_acl_iaccess(i,m,c) : -1)
|
|
||||||
|
|
||||||
#define _ACL_ALLOC(a) ((a) = kmem_zone_alloc(xfs_acl_zone, KM_SLEEP))
|
#define _ACL_ALLOC(a) ((a) = kmem_zone_alloc(xfs_acl_zone, KM_SLEEP))
|
||||||
#define _ACL_FREE(a) ((a)? kmem_zone_free(xfs_acl_zone, (a)):(void)0)
|
#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);
|
|||||||
#define _ACL_GET_DEFAULT(pv,pd) (0)
|
#define _ACL_GET_DEFAULT(pv,pd) (0)
|
||||||
#define _ACL_ACCESS_EXISTS (NULL)
|
#define _ACL_ACCESS_EXISTS (NULL)
|
||||||
#define _ACL_DEFAULT_EXISTS (NULL)
|
#define _ACL_DEFAULT_EXISTS (NULL)
|
||||||
#define _ACL_XFS_IACCESS(i,m,c) (-1)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* __XFS_ACL_H__ */
|
#endif /* __XFS_ACL_H__ */
|
||||||
|
@ -3583,69 +3583,6 @@ xfs_iflush_all(
|
|||||||
XFS_MOUNT_IUNLOCK(mp);
|
XFS_MOUNT_IUNLOCK(mp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* xfs_iaccess: check accessibility of inode for mode.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
xfs_iaccess(
|
|
||||||
xfs_inode_t *ip,
|
|
||||||
mode_t mode,
|
|
||||||
cred_t *cr)
|
|
||||||
{
|
|
||||||
int error;
|
|
||||||
mode_t orgmode = mode;
|
|
||||||
struct inode *inode = vn_to_inode(XFS_ITOV(ip));
|
|
||||||
|
|
||||||
if (mode & S_IWUSR) {
|
|
||||||
umode_t imode = inode->i_mode;
|
|
||||||
|
|
||||||
if (IS_RDONLY(inode) &&
|
|
||||||
(S_ISREG(imode) || S_ISDIR(imode) || S_ISLNK(imode)))
|
|
||||||
return XFS_ERROR(EROFS);
|
|
||||||
|
|
||||||
if (IS_IMMUTABLE(inode))
|
|
||||||
return XFS_ERROR(EACCES);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If there's an Access Control List it's used instead of
|
|
||||||
* the mode bits.
|
|
||||||
*/
|
|
||||||
if ((error = _ACL_XFS_IACCESS(ip, mode, cr)) != -1)
|
|
||||||
return error ? XFS_ERROR(error) : 0;
|
|
||||||
|
|
||||||
if (current_fsuid(cr) != ip->i_d.di_uid) {
|
|
||||||
mode >>= 3;
|
|
||||||
if (!in_group_p((gid_t)ip->i_d.di_gid))
|
|
||||||
mode >>= 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the DACs are ok we don't need any capability check.
|
|
||||||
*/
|
|
||||||
if ((ip->i_d.di_mode & mode) == mode)
|
|
||||||
return 0;
|
|
||||||
/*
|
|
||||||
* Read/write DACs are always overridable.
|
|
||||||
* Executable DACs are overridable if at least one exec bit is set.
|
|
||||||
*/
|
|
||||||
if (!(orgmode & S_IXUSR) ||
|
|
||||||
(inode->i_mode & S_IXUGO) || S_ISDIR(inode->i_mode))
|
|
||||||
if (capable_cred(cr, CAP_DAC_OVERRIDE))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if ((orgmode == S_IRUSR) ||
|
|
||||||
(S_ISDIR(inode->i_mode) && (!(orgmode & S_IWUSR)))) {
|
|
||||||
if (capable_cred(cr, CAP_DAC_READ_SEARCH))
|
|
||||||
return 0;
|
|
||||||
#ifdef NOISE
|
|
||||||
cmn_err(CE_NOTE, "Ick: mode=%o, orgmode=%o", mode, orgmode);
|
|
||||||
#endif /* NOISE */
|
|
||||||
return XFS_ERROR(EACCES);
|
|
||||||
}
|
|
||||||
return XFS_ERROR(EACCES);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef XFS_ILOCK_TRACE
|
#ifdef XFS_ILOCK_TRACE
|
||||||
ktrace_t *xfs_ilock_trace_buf;
|
ktrace_t *xfs_ilock_trace_buf;
|
||||||
|
|
||||||
|
@ -550,7 +550,6 @@ void xfs_iunpin(xfs_inode_t *);
|
|||||||
int xfs_iextents_copy(xfs_inode_t *, xfs_bmbt_rec_t *, int);
|
int xfs_iextents_copy(xfs_inode_t *, xfs_bmbt_rec_t *, int);
|
||||||
int xfs_iflush(xfs_inode_t *, uint);
|
int xfs_iflush(xfs_inode_t *, uint);
|
||||||
void xfs_iflush_all(struct xfs_mount *);
|
void xfs_iflush_all(struct xfs_mount *);
|
||||||
int xfs_iaccess(xfs_inode_t *, mode_t, cred_t *);
|
|
||||||
void xfs_ichgtime(xfs_inode_t *, int);
|
void xfs_ichgtime(xfs_inode_t *, int);
|
||||||
xfs_fsize_t xfs_file_last_byte(xfs_inode_t *);
|
xfs_fsize_t xfs_file_last_byte(xfs_inode_t *);
|
||||||
void xfs_lock_inodes(xfs_inode_t **, int, int, uint);
|
void xfs_lock_inodes(xfs_inode_t **, int, int, uint);
|
||||||
|
@ -898,27 +898,6 @@ xfs_setattr(
|
|||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* xfs_access
|
|
||||||
* Null conversion from vnode mode bits to inode mode bits, as in efs.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
xfs_access(
|
|
||||||
xfs_inode_t *ip,
|
|
||||||
int mode,
|
|
||||||
cred_t *credp)
|
|
||||||
{
|
|
||||||
int error;
|
|
||||||
|
|
||||||
xfs_itrace_entry(ip);
|
|
||||||
xfs_ilock(ip, XFS_ILOCK_SHARED);
|
|
||||||
error = xfs_iaccess(ip, mode, credp);
|
|
||||||
xfs_iunlock(ip, XFS_ILOCK_SHARED);
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The maximum pathlen is 1024 bytes. Since the minimum file system
|
* The maximum pathlen is 1024 bytes. Since the minimum file system
|
||||||
* blocksize is 512 bytes, we can get a max of 2 extents back from
|
* blocksize is 512 bytes, we can get a max of 2 extents back from
|
||||||
|
@ -18,7 +18,6 @@ int xfs_open(struct xfs_inode *ip);
|
|||||||
int xfs_getattr(struct xfs_inode *ip, struct bhv_vattr *vap, int flags);
|
int xfs_getattr(struct xfs_inode *ip, struct bhv_vattr *vap, int flags);
|
||||||
int xfs_setattr(struct xfs_inode *ip, struct bhv_vattr *vap, int flags,
|
int xfs_setattr(struct xfs_inode *ip, struct bhv_vattr *vap, int flags,
|
||||||
struct cred *credp);
|
struct cred *credp);
|
||||||
int xfs_access(struct xfs_inode *ip, int mode, struct cred *credp);
|
|
||||||
int xfs_readlink(struct xfs_inode *ip, char *link);
|
int xfs_readlink(struct xfs_inode *ip, char *link);
|
||||||
int xfs_fsync(struct xfs_inode *ip, int flag, xfs_off_t start,
|
int xfs_fsync(struct xfs_inode *ip, int flag, xfs_off_t start,
|
||||||
xfs_off_t stop);
|
xfs_off_t stop);
|
||||||
|
Loading…
Reference in New Issue
Block a user