Exemplo n.º 1
0
/* This is used to cache the default acl before a new object is created.
 * The biggest reason for this is to get an idea of how many blocks will
 * actually be required for the create operation if we must inherit an ACL.
 * An ACL write can add up to 3 object creations and an additional file write
 * so we'd prefer not to reserve that many blocks in the journal if we can.
 * It also has the advantage of not loading the ACL with a transaction open,
 * this may seem silly, but if the owner of the directory is doing the
 * creation, the ACL may not be loaded since the permissions wouldn't require
 * it.
 * We return the number of blocks required for the transaction.
 */
int reiserfs_cache_default_acl(struct inode *inode)
{
	struct posix_acl *acl;
	int nblocks = 0;

	if (IS_PRIVATE(inode))
		return 0;

	acl = reiserfs_get_acl(inode, ACL_TYPE_DEFAULT);

	if (acl && !IS_ERR(acl)) {
		int size = reiserfs_acl_size(acl->a_count);

		/* Other xattrs can be created during inode creation. We don't
		 * want to claim too many blocks, so we check to see if we
		 * we need to create the tree to the xattrs, and then we
		 * just want two files. */
		nblocks = reiserfs_xattr_jcreate_nblocks(inode);
		nblocks += JOURNAL_BLOCKS_PER_OBJECT(inode->i_sb);

		REISERFS_I(inode)->i_flags |= i_has_xattr_dir;

		/* We need to account for writes + bitmaps for two files */
		nblocks += reiserfs_xattr_nblocks(inode, size) * 4;
		posix_acl_release(acl);
	}

	return nblocks;
}
Exemplo n.º 2
0
/* dir->i_mutex: locked,
 * inode is new and not released into the wild yet */
int
reiserfs_inherit_default_acl(struct reiserfs_transaction_handle *th,
			     struct inode *dir, struct dentry *dentry,
			     struct inode *inode)
{
	struct posix_acl *acl;
	int err = 0;

	/* ACLs only get applied to files and directories */
	if (S_ISLNK(inode->i_mode))
		return 0;

	/* ACLs can only be used on "new" objects, so if it's an old object
	 * there is nothing to inherit from */
	if (get_inode_sd_version(dir) == STAT_DATA_V1)
		goto apply_umask;

	/* Don't apply ACLs to objects in the .reiserfs_priv tree.. This
	 * would be useless since permissions are ignored, and a pain because
	 * it introduces locking cycles */
	if (IS_PRIVATE(dir)) {
		inode->i_flags |= S_PRIVATE;
		goto apply_umask;
	}

	acl = reiserfs_get_acl(dir, ACL_TYPE_DEFAULT);
	if (IS_ERR(acl))
		return PTR_ERR(acl);

	if (acl) {
		/* Copy the default ACL to the default ACL of a new directory */
		if (S_ISDIR(inode->i_mode)) {
			err = reiserfs_set_acl(th, inode, ACL_TYPE_DEFAULT,
					       acl);
			if (err)
				goto cleanup;
		}

		/* Now we reconcile the new ACL and the mode,
		   potentially modifying both */
		err = posix_acl_create(&acl, GFP_NOFS, &inode->i_mode);
		if (err < 0)
			return err;

		/* If we need an ACL.. */
		if (err > 0)
			err = reiserfs_set_acl(th, inode, ACL_TYPE_ACCESS, acl);
	      cleanup:
		posix_acl_release(acl);
	} else {
	      apply_umask:
		/* no ACL, apply umask */
		inode->i_mode &= ~current_umask();
	}

	return err;
}
Exemplo n.º 3
0
/* Looks up and caches the result of the default ACL.
 * We do this so that we don't need to carry the xattr_sem into
 * reiserfs_new_inode if we don't need to */
int reiserfs_cache_default_acl(struct inode *inode)
{
    int ret = 0;
    if (reiserfs_posixacl(inode->i_sb) && !is_reiserfs_priv_object(inode)) {
        struct posix_acl *acl;
        reiserfs_read_lock_xattr_i(inode);
        reiserfs_read_lock_xattrs(inode->i_sb);
        acl = reiserfs_get_acl(inode, ACL_TYPE_DEFAULT);
        reiserfs_read_unlock_xattrs(inode->i_sb);
        reiserfs_read_unlock_xattr_i(inode);
        ret = (acl && !IS_ERR(acl));
        if (ret)
            posix_acl_release(acl);
    }

    return ret;
}
Exemplo n.º 4
0
int reiserfs_acl_chmod(struct inode *inode)
{
	struct posix_acl *acl, *clone;
	int error;

	if (S_ISLNK(inode->i_mode))
		return -EOPNOTSUPP;

	if (get_inode_sd_version(inode) == STAT_DATA_V1 ||
	    !reiserfs_posixacl(inode->i_sb)) {
		return 0;
	}

	reiserfs_write_unlock(inode->i_sb);
	acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS);
	reiserfs_write_lock(inode->i_sb);
	if (!acl)
		return 0;
	if (IS_ERR(acl))
		return PTR_ERR(acl);
	clone = posix_acl_clone(acl, GFP_NOFS);
	posix_acl_release(acl);
	if (!clone)
		return -ENOMEM;
	error = posix_acl_chmod_masq(clone, inode->i_mode);
	if (!error) {
		struct reiserfs_transaction_handle th;
		size_t size = reiserfs_xattr_nblocks(inode,
					     reiserfs_acl_size(clone->a_count));
		int depth;

		depth = reiserfs_write_lock_once(inode->i_sb);
		error = journal_begin(&th, inode->i_sb, size * 2);
		if (!error) {
			int error2;
			error = reiserfs_set_acl(&th, inode, ACL_TYPE_ACCESS,
						 clone);
			error2 = journal_end(&th, inode->i_sb, size * 2);
			if (error2)
				error = error2;
		}
		reiserfs_write_unlock_once(inode->i_sb, depth);
	}
	posix_acl_release(clone);
	return error;
}
Exemplo n.º 5
0
int
reiserfs_acl_chmod (struct inode *inode)
{
        struct posix_acl *acl, *clone;
        int error;

        if (S_ISLNK(inode->i_mode))
                return -EOPNOTSUPP;

	if (get_inode_sd_version (inode) == STAT_DATA_V1 ||
	    !reiserfs_posixacl(inode->i_sb))
        {
	    return 0;
	}

        reiserfs_read_lock_xattrs (inode->i_sb);
        acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS);
        reiserfs_read_unlock_xattrs (inode->i_sb);
        if (!acl)
                return 0;
        if (IS_ERR(acl))
                return PTR_ERR(acl);
        clone = posix_acl_clone(acl, GFP_NOFS);
        posix_acl_release(acl);
        if (!clone)
                return -ENOMEM;
        error = posix_acl_chmod_masq(clone, inode->i_mode);
        if (!error) {
                int lock = !has_xattr_dir (inode);
                reiserfs_write_lock_xattr_i (inode);
                if (lock)
                    reiserfs_write_lock_xattrs (inode->i_sb);
                else
                    reiserfs_read_lock_xattrs (inode->i_sb);
                error = reiserfs_set_acl(inode, ACL_TYPE_ACCESS, clone);
                if (lock)
                    reiserfs_write_unlock_xattrs (inode->i_sb);
                else
                    reiserfs_read_unlock_xattrs (inode->i_sb);
                reiserfs_write_unlock_xattr_i (inode);
        }
        posix_acl_release(clone);
        return error;
}
Exemplo n.º 6
0
static int
xattr_get_acl(struct inode *inode, int type, void *buffer, size_t size)
{
	struct posix_acl *acl;
	int error;

	if (!reiserfs_posixacl(inode->i_sb))
		return -EOPNOTSUPP;

	acl = reiserfs_get_acl (inode, type);
	if (IS_ERR(acl))
		return PTR_ERR(acl);
	if (acl == NULL)
		return -ENODATA;
	error = posix_acl_to_xattr(acl, buffer, size);
	posix_acl_release(acl);

	return error;
}
Exemplo n.º 7
0
static int
posix_acl_get(struct dentry *dentry, const char *name, void *buffer,
		size_t size, int type)
{
	struct posix_acl *acl;
	int error;

	if (!reiserfs_posixacl(dentry->d_sb))
		return -EOPNOTSUPP;

	acl = reiserfs_get_acl(dentry->d_inode, type);
	if (IS_ERR(acl))
		return PTR_ERR(acl);
	if (acl == NULL)
		return -ENODATA;
	error = posix_acl_to_xattr(&init_user_ns, acl, buffer, size);
	posix_acl_release(acl);

	return error;
}
Exemplo n.º 8
0
/* dir->i_sem: down,
 * inode is new and not released into the wild yet */
int
reiserfs_inherit_default_acl (struct inode *dir, struct dentry *dentry, struct inode *inode)
{
    struct posix_acl *acl;
    int err = 0;

    /* ACLs only get applied to files and directories */
    if (S_ISLNK (inode->i_mode))
        return 0;

    /* ACLs can only be used on "new" objects, so if it's an old object
     * there is nothing to inherit from */
    if (get_inode_sd_version (dir) == STAT_DATA_V1)
        goto apply_umask;

    /* Don't apply ACLs to objects in the .reiserfs_priv tree.. This
     * would be useless since permissions are ignored, and a pain because
     * it introduces locking cycles */
    if (is_reiserfs_priv_object (dir)) {
        reiserfs_mark_inode_private (inode);
        goto apply_umask;
    }

    acl = reiserfs_get_acl (dir, ACL_TYPE_DEFAULT);
    if (IS_ERR (acl)) {
        if (PTR_ERR (acl) == -ENODATA)
            goto apply_umask;
        return PTR_ERR (acl);
    }

    if (acl) {
        struct posix_acl *acl_copy;
        mode_t mode = inode->i_mode;
        int need_acl;

        /* Copy the default ACL to the default ACL of a new directory */
        if (S_ISDIR (inode->i_mode)) {
            err = reiserfs_set_acl (inode, ACL_TYPE_DEFAULT, acl);
            if (err)
                goto cleanup;
        }

        /* Now we reconcile the new ACL and the mode,
           potentially modifying both */
        acl_copy = posix_acl_clone (acl, GFP_NOFS);
        if (!acl_copy) {
            err = -ENOMEM;
            goto cleanup;
        }


        need_acl = posix_acl_create_masq (acl_copy, &mode);
        if (need_acl >= 0) {
            if (mode != inode->i_mode) {
                inode->i_mode = mode;
            }

            /* If we need an ACL.. */
            if (need_acl > 0) {
                err = reiserfs_set_acl (inode, ACL_TYPE_ACCESS, acl_copy);
                if (err)
                    goto cleanup_copy;
            }
        }
cleanup_copy:
        posix_acl_release (acl_copy);
cleanup:
        posix_acl_release (acl);
    } else {
apply_umask:
        /* no ACL, apply umask */
        inode->i_mode &= ~current->fs->umask;
    }

    return err;
}
Exemplo n.º 9
0
/*
 * Inode operation listxattr()
 *
 * We totally ignore the generic listxattr here because it would be stupid
 * not to. Since the xattrs are organized in a directory, we can just
 * readdir to find them.
 */
ssize_t reiserfs_listxattr(struct dentry * dentry, char *buffer, size_t size)
{
	struct dentry *dir;
	int err = 0;
	loff_t pos = 0;
	struct listxattr_buf buf = {
		.dentry = dentry,
		.buf = buffer,
		.size = buffer ? size : 0,
	};

	if (!dentry->d_inode)
		return -EINVAL;

	if (!dentry->d_sb->s_xattr ||
	    get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1)
		return -EOPNOTSUPP;

	dir = open_xa_dir(dentry->d_inode, XATTR_REPLACE);
	if (IS_ERR(dir)) {
		err = PTR_ERR(dir);
		if (err == -ENODATA)
			err = 0;  /* Not an error if there aren't any xattrs */
		goto out;
	}

	mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_XATTR);
	err = reiserfs_readdir_dentry(dir, &buf, listxattr_filler, &pos);
	mutex_unlock(&dir->d_inode->i_mutex);

	if (!err)
		err = buf.pos;

	dput(dir);
out:
	return err;
}

static int reiserfs_check_acl(struct inode *inode, int mask, unsigned int flags)
{
	struct posix_acl *acl;
	int error = -EAGAIN; /* do regular unix permission checks by default */

	if (flags & IPERM_FLAG_RCU)
		return -ECHILD;

	acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS);

	if (acl) {
		if (!IS_ERR(acl)) {
			error = posix_acl_permission(inode, acl, mask);
			posix_acl_release(acl);
		} else if (PTR_ERR(acl) != -ENODATA)
			error = PTR_ERR(acl);
	}

	return error;
}

static int create_privroot(struct dentry *dentry)
{
	int err;
	struct inode *inode = dentry->d_parent->d_inode;
	WARN_ON_ONCE(!mutex_is_locked(&inode->i_mutex));

	err = xattr_mkdir(inode, dentry, 0700);
	if (err || !dentry->d_inode) {
		reiserfs_warning(dentry->d_sb, "jdm-20006",
				 "xattrs/ACLs enabled and couldn't "
				 "find/create .reiserfs_priv. "
				 "Failing mount.");
		return -EOPNOTSUPP;
	}

	dentry->d_inode->i_flags |= S_PRIVATE;
	reiserfs_info(dentry->d_sb, "Created %s - reserved for xattr "
		      "storage.\n", PRIVROOT_NAME);

	return 0;
}