}
#ifdef CONFIG_XFS_POSIX_ACL
+STATIC int
+xfs_check_acl(
+ struct inode *inode,
+ int mask)
+{
+ 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 mode,
- struct nameidata *nd)
+ struct inode *inode,
+ int mask,
+ struct nameidata *nd)
{
- return -xfs_access(XFS_I(inode), mode << 6, NULL);
+ return generic_permission(inode, mask, xfs_check_acl);
}
#else
#define xfs_vn_permission NULL
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.
* It is not used to find out the credentials uid or groups etc, as was
matched.ae_tag = 0; /* Invalid type */
matched.ae_perm = 0;
- md >>= 6; /* Normalize the bits for comparison */
for (i = 0; i < fap->acl_cnt; i++) {
/*
break;
}
- return xfs_acl_capability_check(md, cr);
+ /* EACCES tells generic_permission to check for capability overrides */
+ return EACCES;
}
/*
#define _ACL_GET_DEFAULT(pv,pd) (xfs_acl_vtoacl(pv,NULL,pd) == 0)
#define _ACL_ACCESS_EXISTS xfs_acl_vhasacl_access
#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_FREE(a) ((a)? kmem_zone_free(xfs_acl_zone, (a)):(void)0)
#define _ACL_GET_DEFAULT(pv,pd) (0)
#define _ACL_ACCESS_EXISTS (NULL)
#define _ACL_DEFAULT_EXISTS (NULL)
-#define _ACL_XFS_IACCESS(i,m,c) (-1)
#endif
#endif /* __XFS_ACL_H__ */
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
ktrace_t *xfs_ilock_trace_buf;
int xfs_iextents_copy(xfs_inode_t *, xfs_bmbt_rec_t *, int);
int xfs_iflush(xfs_inode_t *, uint);
void xfs_iflush_all(struct xfs_mount *);
-int xfs_iaccess(xfs_inode_t *, mode_t, cred_t *);
void xfs_ichgtime(xfs_inode_t *, int);
xfs_fsize_t xfs_file_last_byte(xfs_inode_t *);
void xfs_lock_inodes(xfs_inode_t **, int, int, uint);
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
* blocksize is 512 bytes, we can get a max of 2 extents back from
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,
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_fsync(struct xfs_inode *ip, int flag, xfs_off_t start,
xfs_off_t stop);