Пример #1
0
static int can_set_system_xattr(struct inode *inode, const char *name,
				const void *value, size_t size)
{
#ifdef CONFIG_HFSPLUS_FS_POSIX_ACL
	struct posix_acl *acl;
	int err;

	if (!inode_owner_or_capable(inode))
		return -EPERM;

	/*
	 * POSIX_ACL_XATTR_ACCESS is tied to i_mode
	 */
	if (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0) {
		acl = posix_acl_from_xattr(&init_user_ns, value, size);
		if (IS_ERR(acl))
			return PTR_ERR(acl);
		if (acl) {
			err = posix_acl_equiv_mode(acl, &inode->i_mode);
			posix_acl_release(acl);
			if (err < 0)
				return err;
			mark_inode_dirty(inode);
		}
		/*
		 * We're changing the ACL.  Get rid of the cached one
		 */
		forget_cached_acl(inode, ACL_TYPE_ACCESS);

		return 0;
	} else if (strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0) {
		acl = posix_acl_from_xattr(&init_user_ns, value, size);
		if (IS_ERR(acl))
			return PTR_ERR(acl);
		posix_acl_release(acl);

		/*
		 * We're changing the default ACL.  Get rid of the cached one
		 */
		forget_cached_acl(inode, ACL_TYPE_DEFAULT);

		return 0;
	}
#endif /* CONFIG_HFSPLUS_FS_POSIX_ACL */
	return -EOPNOTSUPP;
}
Пример #2
0
static inline void ceph_set_cached_acl(struct inode *inode,
                                       int type, struct posix_acl *acl)
{
    struct ceph_inode_info *ci = ceph_inode(inode);

    spin_lock(&ci->i_ceph_lock);
    if (__ceph_caps_issued_mask(ci, CEPH_CAP_XATTR_SHARED, 0))
        set_cached_acl(inode, type, acl);
    else
        forget_cached_acl(inode, type);
    spin_unlock(&ci->i_ceph_lock);
}
Пример #3
0
void
xfs_forget_acl(
	struct inode		*inode,
	const char		*name,
	int			xflags)
{
	/*
	 * Invalidate any cached ACLs if the user has bypassed the ACL
	 * interface. We don't validate the content whatsoever so it is caller
	 * responsibility to provide data in valid format and ensure i_mode is
	 * consistent.
	 */
	if (xflags & ATTR_ROOT) {
#ifdef CONFIG_XFS_POSIX_ACL
		if (!strcmp(name, SGI_ACL_FILE))
			forget_cached_acl(inode, ACL_TYPE_ACCESS);
		else if (!strcmp(name, SGI_ACL_DEFAULT))
			forget_cached_acl(inode, ACL_TYPE_DEFAULT);
#endif
	}
}
Пример #4
0
static int gfs2_xattr_system_set(struct dentry *dentry, const char *name,
				 const void *value, size_t size, int flags,
				 int xtype)
{
	struct inode *inode = dentry->d_inode;
	struct gfs2_sbd *sdp = GFS2_SB(inode);
	struct posix_acl *acl = NULL;
	int error = 0, type;

	if (!sdp->sd_args.ar_posix_acl)
		return -EOPNOTSUPP;

	type = gfs2_acl_type(name);
	if (type < 0)
		return type;
	if (flags & XATTR_CREATE)
		return -EINVAL;
	if (type == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode))
		return value ? -EACCES : 0;
	if ((current_fsuid() != inode->i_uid) && !capable(CAP_FOWNER))
		return -EPERM;
	if (S_ISLNK(inode->i_mode))
		return -EOPNOTSUPP;

	if (!value)
		goto set_acl;

	acl = posix_acl_from_xattr(value, size);
	if (!acl) {
		/*
		 * acl_set_file(3) may request that we set default ACLs with
		 * zero length -- defend (gracefully) against that here.
		 */
		goto out;
	}
	if (IS_ERR(acl)) {
		error = PTR_ERR(acl);
		goto out;
	}

	error = posix_acl_valid(acl);
	if (error)
		goto out_release;

	error = -EINVAL;
	if (acl->a_count > GFS2_ACL_MAX_ENTRIES)
		goto out_release;

	if (type == ACL_TYPE_ACCESS) {
		umode_t mode = inode->i_mode;
		error = posix_acl_equiv_mode(acl, &mode);

		if (error <= 0) {
			posix_acl_release(acl);
			acl = NULL;

			if (error < 0)
				return error;
		}

		error = gfs2_set_mode(inode, mode);
		if (error)
			goto out_release;
	}

set_acl:
	error = __gfs2_xattr_set(inode, name, value, size, 0, GFS2_EATYPE_SYS);
	if (!error) {
		if (acl)
			set_cached_acl(inode, type, acl);
		else
			forget_cached_acl(inode, type);
	}
out_release:
	posix_acl_release(acl);
out:
	return error;
}
Пример #5
0
struct posix_acl *nfs3_get_acl(struct inode *inode, int type)
{
	struct nfs_server *server = NFS_SERVER(inode);
	struct page *pages[NFSACL_MAXPAGES] = { };
	struct nfs3_getaclargs args = {
		.fh = NFS_FH(inode),
		/* The xdr layer may allocate pages here. */
		.pages = pages,
	};
	struct nfs3_getaclres res = {
		NULL,
	};
	struct rpc_message msg = {
		.rpc_argp	= &args,
		.rpc_resp	= &res,
	};
	int status, count;

	if (!nfs_server_capable(inode, NFS_CAP_ACLS))
		return ERR_PTR(-EOPNOTSUPP);

	status = nfs_revalidate_inode(server, inode);
	if (status < 0)
		return ERR_PTR(status);

	/*
	 * Only get the access acl when explicitly requested: We don't
	 * need it for access decisions, and only some applications use
	 * it. Applications which request the access acl first are not
	 * penalized from this optimization.
	 */
	if (type == ACL_TYPE_ACCESS)
		args.mask |= NFS_ACLCNT|NFS_ACL;
	if (S_ISDIR(inode->i_mode))
		args.mask |= NFS_DFACLCNT|NFS_DFACL;
	if (args.mask == 0)
		return NULL;

	dprintk("NFS call getacl\n");
	msg.rpc_proc = &server->client_acl->cl_procinfo[ACLPROC3_GETACL];
	res.fattr = nfs_alloc_fattr();
	if (res.fattr == NULL)
		return ERR_PTR(-ENOMEM);

	status = rpc_call_sync(server->client_acl, &msg, 0);
	dprintk("NFS reply getacl: %d\n", status);

	/* pages may have been allocated at the xdr layer. */
	for (count = 0; count < NFSACL_MAXPAGES && args.pages[count]; count++)
		__free_page(args.pages[count]);

	switch (status) {
		case 0:
			status = nfs_refresh_inode(inode, res.fattr);
			break;
		case -EPFNOSUPPORT:
		case -EPROTONOSUPPORT:
			dprintk("NFS_V3_ACL extension not supported; disabling\n");
			server->caps &= ~NFS_CAP_ACLS;
		case -ENOTSUPP:
			status = -EOPNOTSUPP;
		default:
			goto getout;
	}
	if ((args.mask & res.mask) != args.mask) {
		status = -EIO;
		goto getout;
	}

	if (res.acl_access != NULL) {
		if ((posix_acl_equiv_mode(res.acl_access, NULL) == 0) ||
		    res.acl_access->a_count == 0) {
			posix_acl_release(res.acl_access);
			res.acl_access = NULL;
		}
	}

	if (res.mask & NFS_ACL)
		set_cached_acl(inode, ACL_TYPE_ACCESS, res.acl_access);
	else
		forget_cached_acl(inode, ACL_TYPE_ACCESS);

	if (res.mask & NFS_DFACL)
		set_cached_acl(inode, ACL_TYPE_DEFAULT, res.acl_default);
	else
		forget_cached_acl(inode, ACL_TYPE_DEFAULT);

	nfs_free_fattr(res.fattr);
	if (type == ACL_TYPE_ACCESS) {
		posix_acl_release(res.acl_default);
		return res.acl_access;
	} else {
		posix_acl_release(res.acl_access);
		return res.acl_default;
	}

getout:
	posix_acl_release(res.acl_access);
	posix_acl_release(res.acl_default);
	nfs_free_fattr(res.fattr);
	return ERR_PTR(status);
}