Exemple #1
0
int jffs2_acl_chmod(struct inode *inode)
{
	struct posix_acl *acl, *clone;
	int rc;

	if (S_ISLNK(inode->i_mode))
		return -EOPNOTSUPP;
	acl = jffs2_get_acl(inode, ACL_TYPE_ACCESS);
	if (IS_ERR(acl) || !acl)
		return PTR_ERR(acl);
	clone = posix_acl_clone(acl, GFP_KERNEL);
	posix_acl_release(acl);
	if (!clone)
		return -ENOMEM;
	rc = posix_acl_chmod_masq(clone, inode->i_mode);
	if (!rc)
		rc = jffs2_set_acl(inode, ACL_TYPE_ACCESS, clone);
	posix_acl_release(clone);
	return rc;
}
/*
 * No need for i_mutex because the inode is not yet exposed to the VFS.
 */
int
xfs_inherit_acl(struct inode *inode, struct posix_acl *default_acl)
{
	struct posix_acl *clone;
	mode_t mode;
	int error = 0, inherit = 0;

	if (S_ISDIR(inode->i_mode)) {
		error = xfs_set_acl(inode, ACL_TYPE_DEFAULT, default_acl);
		if (error)
			return error;
	}

	clone = posix_acl_clone(default_acl, GFP_KERNEL);
	if (!clone)
		return -ENOMEM;

	mode = inode->i_mode;
	error = posix_acl_create_masq(clone, &mode);
	if (error < 0)
		goto out_release_clone;

	/*
	 * If posix_acl_create_masq returns a positive value we need to
	 * inherit a permission that can't be represented using the Unix
	 * mode bits and we actually need to set an ACL.
	 */
	if (error > 0)
		inherit = 1;

	error = xfs_set_mode(inode, mode);
	if (error)
		goto out_release_clone;

	if (inherit)
		error = xfs_set_acl(inode, ACL_TYPE_ACCESS, clone);

 out_release_clone:
	posix_acl_release(clone);
	return error;
}
Exemple #3
0
int f2fs_init_acl(struct inode *inode, struct inode *dir)
{
	struct posix_acl *acl = NULL;
	mode_t mode;
	struct posix_acl *clone;
	struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb);
	int error = 0;

	if (!S_ISLNK(inode->i_mode)) {
		if (test_opt(sbi, POSIX_ACL)) {
			acl = f2fs_get_acl(dir, ACL_TYPE_DEFAULT);
			if (IS_ERR(acl))
				return PTR_ERR(acl);
		}
		if (!acl)
			inode->i_mode &= ~current_umask();
	}

	if (test_opt(sbi, POSIX_ACL) && acl) {

		if (S_ISDIR(inode->i_mode)) {
			error = f2fs_set_acl(inode, ACL_TYPE_DEFAULT, acl);
			if (error)
				goto cleanup;
		}
		//error = posix_acl_create(&acl, GFP_KERNEL, &inode->i_mode);
		clone = posix_acl_clone(acl, GFP_KERNEL);
		error = -ENOMEM;
		if (!clone)
			goto cleanup;
		mode = inode->i_mode;
		error = posix_acl_create_masq(clone, &mode);
		if (error < 0)
			return error;
		if (error > 0)
			error = f2fs_set_acl(inode, ACL_TYPE_ACCESS, acl);
	}
cleanup:
	posix_acl_release(acl);
	return error;
}
Exemple #4
0
int jfs_init_acl(tid_t tid, struct inode *inode, struct inode *dir)
{
	struct posix_acl *acl = NULL;
	struct posix_acl *clone;
	mode_t mode;
	int rc = 0;

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

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

	if (acl) {
		if (S_ISDIR(inode->i_mode)) {
			rc = jfs_set_acl(tid, inode, ACL_TYPE_DEFAULT, acl);
			if (rc)
				goto cleanup;
		}
		clone = posix_acl_clone(acl, GFP_KERNEL);
		if (!clone) {
			rc = -ENOMEM;
			goto cleanup;
		}
		mode = inode->i_mode;
		rc = posix_acl_create_masq(clone, &mode);
		if (rc >= 0) {
			inode->i_mode = mode;
			if (rc > 0)
				rc = jfs_set_acl(tid, inode, ACL_TYPE_ACCESS,
						 clone);
		}
		posix_acl_release(clone);
cleanup:
		posix_acl_release(acl);
	} else
		inode->i_mode &= ~current->fs->umask;

	return rc;
}
Exemple #5
0
/**
 * generic_acl_chmod  -  change the access acl of @inode upon chmod()
 * @ops:    FIlesystem specific getacl and setacl callbacks
 *
 * A chmod also changes the permissions of the owner, group/mask, and
 * other ACL entries.
 */
int
generic_acl_chmod(struct inode *inode, struct generic_acl_operations *ops)
{
    struct posix_acl *acl, *clone;
    int error = 0;

    if (S_ISLNK(inode->i_mode))
        return -EOPNOTSUPP;
    acl = ops->getacl(inode, ACL_TYPE_ACCESS);
    if (acl) {
        clone = posix_acl_clone(acl, GFP_KERNEL);
        posix_acl_release(acl);
        if (!clone)
            return -ENOMEM;
        error = posix_acl_chmod_masq(clone, inode->i_mode);
        if (!error)
            ops->setacl(inode, ACL_TYPE_ACCESS, clone);
        posix_acl_release(clone);
    }
    return error;
}
Exemple #6
0
/*
 * Does chmod for an inode that may have an Access Control List. The
 * inode->i_mode field must be updated to the desired value by the caller
 * before calling this function.
 * Returns 0 on success, or a negative error number.
 *
 * We change the ACL rather than storing some ACL entries in the file
 * mode permission bits (which would be more efficient), because that
 * would break once additional permissions (like  ACL_APPEND, ACL_DELETE
 * for directories) are added. There are no more bits available in the
 * file mode.
 *
 * inode->i_mutex: down
 */
int
ext3_acl_chmod(struct inode *inode)
{
	struct posix_acl *acl, *clone;
        int error;

	if (S_ISLNK(inode->i_mode))
		return -EOPNOTSUPP;
	if (!test_opt(inode->i_sb, POSIX_ACL))
		return 0;
	acl = ext3_get_acl(inode, ACL_TYPE_ACCESS);
	if (IS_ERR(acl) || !acl)
		return PTR_ERR(acl);
	clone = posix_acl_clone(acl, GFP_KERNEL);
	posix_acl_release(acl);
	if (!clone)
		return -ENOMEM;
	error = posix_acl_chmod_masq(clone, inode->i_mode);
	if (!error) {
		handle_t *handle;
		int retries = 0;

	retry:
		handle = ext3_journal_start(inode,
				EXT3_DATA_TRANS_BLOCKS(inode->i_sb));
		if (IS_ERR(handle)) {
			error = PTR_ERR(handle);
			ext3_std_error(inode->i_sb, error);
			goto out;
		}
		error = ext3_set_acl(handle, inode, ACL_TYPE_ACCESS, clone);
		ext3_journal_stop(handle);
		if (error == -ENOSPC &&
		    ext3_should_retry_alloc(inode->i_sb, &retries))
			goto retry;
	}
out:
	posix_acl_release(clone);
	return error;
}
Exemple #7
0
int v9fs_acl_mode(struct inode *dir, mode_t *modep,
		  struct posix_acl **dpacl, struct posix_acl **pacl)
{
	int retval = 0;
	mode_t mode = *modep;
	struct posix_acl *acl = NULL;

	if (!S_ISLNK(mode)) {
		acl = v9fs_get_cached_acl(dir, ACL_TYPE_DEFAULT);
		if (IS_ERR(acl))
			return PTR_ERR(acl);
		if (!acl)
			mode &= ~current_umask();
	}
	if (acl) {
		struct posix_acl *clone;

		if (S_ISDIR(mode))
			*dpacl = posix_acl_dup(acl);
		clone = posix_acl_clone(acl, GFP_NOFS);
		posix_acl_release(acl);
		if (!clone)
			return -ENOMEM;

		retval = posix_acl_create_masq(clone, &mode);
		if (retval < 0) {
			posix_acl_release(clone);
			goto cleanup;
		}
		if (retval > 0)
			*pacl = clone;
		else
			posix_acl_release(clone);
	}
	*modep  = mode;
	return 0;
cleanup:
	return retval;

}
Exemple #8
0
int jffs2_init_acl(struct inode *inode, struct inode *dir)
{
	struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
	struct posix_acl *acl = NULL, *clone;
	mode_t mode;
	int rc = 0;

	f->i_acl_access = JFFS2_ACL_NOT_CACHED;
	f->i_acl_default = JFFS2_ACL_NOT_CACHED;
	if (!S_ISLNK(inode->i_mode)) {
		acl = jffs2_get_acl(dir, ACL_TYPE_DEFAULT);
		if (IS_ERR(acl))
			return PTR_ERR(acl);
		if (!acl)
			inode->i_mode &= ~current->fs->umask;
	}
	if (acl) {
		if (S_ISDIR(inode->i_mode)) {
			rc = jffs2_set_acl(inode, ACL_TYPE_DEFAULT, acl);
			if (rc)
				goto cleanup;
		}
		clone = posix_acl_clone(acl, GFP_KERNEL);
		rc = -ENOMEM;
		if (!clone)
			goto cleanup;
		mode = inode->i_mode;
		rc = posix_acl_create_masq(clone, &mode);
		if (rc >= 0) {
			inode->i_mode = mode;
			if (rc > 0)
				rc = jffs2_set_acl(inode, ACL_TYPE_ACCESS, clone);
		}
		posix_acl_release(clone);
	}
 cleanup:
	posix_acl_release(acl);
	return rc;
}
/*
 * Does chmod for an inode that may have an Access Control List. The
 * inode->i_mode field must be updated to the desired value by the caller
 * before calling this function.
 * Returns 0 on success, or a negative error number.
 *
 * We change the ACL rather than storing some ACL entries in the file
 * mode permission bits (which would be more efficient), because that
 * would break once additional permissions (like  ACL_APPEND, ACL_DELETE
 * for directories) are added. There are no more bits available in the
 * file mode.
 *
 * inode->i_mutex: down
 */
int
ext2_acl_chmod(struct inode *inode)
{
	struct posix_acl *acl, *clone;
        int error;

	if (!test_opt(inode->i_sb, POSIX_ACL))
		return 0;
	if (S_ISLNK(inode->i_mode))
		return -EOPNOTSUPP;
	acl = ext2_get_acl(inode, ACL_TYPE_ACCESS);
	if (IS_ERR(acl) || !acl)
		return PTR_ERR(acl);
	clone = posix_acl_clone(acl, GFP_KERNEL);
	posix_acl_release(acl);
	if (!clone)
		return -ENOMEM;
	error = posix_acl_chmod_masq(clone, inode->i_mode);
	if (!error)
		error = ext2_set_acl(inode, ACL_TYPE_ACCESS, clone);
	posix_acl_release(clone);
	return error;
}
Exemple #10
0
int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr)
{
	struct posix_acl *acl, *clone;
	char *data;
	unsigned int len;
	int error;

	acl = gfs2_acl_get(ip, ACL_TYPE_ACCESS);
	if (IS_ERR(acl))
		return PTR_ERR(acl);
	if (!acl)
		return gfs2_setattr_simple(ip, attr);

	clone = posix_acl_clone(acl, GFP_NOFS);
	error = -ENOMEM;
	if (!clone)
		goto out;
	posix_acl_release(acl);
	acl = clone;

	error = posix_acl_chmod_masq(acl, attr->ia_mode);
	if (!error) {
		len = posix_acl_to_xattr(acl, NULL, 0);
		data = kmalloc(len, GFP_NOFS);
		error = -ENOMEM;
		if (data == NULL)
			goto out;
		posix_acl_to_xattr(acl, data, len);
		error = gfs2_xattr_acl_chmod(ip, attr, data);
		kfree(data);
		set_cached_acl(&ip->i_inode, ACL_TYPE_ACCESS, acl);
	}

out:
	posix_acl_release(acl);
	return error;
}
int jffs2_init_acl_pre(struct inode *dir_i, struct inode *inode, int *i_mode)
{
	struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
	struct posix_acl *acl, *clone;
	int rc;

	f->i_acl_default = NULL;
	f->i_acl_access = NULL;

	if (S_ISLNK(*i_mode))
		return 0;	/* Symlink always has no-ACL */

	acl = jffs2_get_acl(dir_i, ACL_TYPE_DEFAULT);
	if (IS_ERR(acl))
		return PTR_ERR(acl);

	if (!acl) {
		*i_mode &= ~current->fs->umask;
	} else {
		if (S_ISDIR(*i_mode))
			jffs2_iset_acl(inode, &f->i_acl_default, acl);

		clone = posix_acl_clone(acl, GFP_KERNEL);
		if (!clone)
			return -ENOMEM;
		rc = posix_acl_create_masq(clone, (mode_t *)i_mode);
		if (rc < 0) {
			posix_acl_release(clone);
			return rc;
		}
		if (rc > 0)
			jffs2_iset_acl(inode, &f->i_acl_access, clone);

		posix_acl_release(clone);
	}
	return 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;
}
Exemple #13
0
/*
 * initialize the ACLs of a new inode.
 * This needs to be called from pvfs2_get_custom_inode.
 * Note that for the root of the PVFS2 file system,
 * dir will be NULL! For all others dir will be non-NULL
 * However, inode cannot be NULL!
 * Returns 0 on success and -ve number on failure.
 */
int pvfs2_init_acl(struct inode *inode, struct inode *dir)
{
    struct posix_acl *acl = NULL;
    int error = 0;
    pvfs2_inode_t *pvfs2_inode = PVFS2_I(inode);

    if (dir == NULL)
        dir = inode;
    ClearModeFlag(pvfs2_inode);
    if (!S_ISLNK(inode->i_mode))
    {
        if (get_acl_flag(inode) == 1)
        {
            acl = pvfs2_get_acl(dir, ACL_TYPE_DEFAULT);
            if (IS_ERR(acl)) {
                error = PTR_ERR(acl);
                gossip_err("pvfs2_get_acl (default) failed with error %d\n", error);
                return error;
            }
        }
        if (!acl && dir != inode)
        {
            int old_mode = inode->i_mode;
            inode->i_mode &= ~current->fs->umask;
            gossip_debug(GOSSIP_ACL_DEBUG, "inode->i_mode before %o and "
                    "after %o\n", old_mode, inode->i_mode);
            if (old_mode != inode->i_mode)
                SetModeFlag(pvfs2_inode);
        }
    }
    if (get_acl_flag(inode) == 1 && acl)
    {
        struct posix_acl *clone;
        mode_t mode;

        if (S_ISDIR(inode->i_mode)) 
        {
            error = pvfs2_set_acl(inode, ACL_TYPE_DEFAULT, acl);
            if (error) {
                gossip_err("pvfs2_set_acl (default) directory failed with "
                        "error %d\n", error);
                ClearModeFlag(pvfs2_inode);
                goto cleanup;
            }
        }
        clone = posix_acl_clone(acl, GFP_KERNEL);
        error = -ENOMEM;
        if (!clone) {
            gossip_err("posix_acl_clone failed with ENOMEM\n");
            ClearModeFlag(pvfs2_inode);
            goto cleanup;
        }
        mode = inode->i_mode;
        error = posix_acl_create_masq(clone, &mode);
        if (error >= 0)
        {
            gossip_debug(GOSSIP_ACL_DEBUG, "posix_acl_create_masq changed mode "
                    "from %o to %o\n", inode->i_mode, mode);
            /*
             * Dont do a needless ->setattr() if mode has not changed 
             */
            if (inode->i_mode != mode)
                SetModeFlag(pvfs2_inode);
            inode->i_mode = mode;
            /* 
             * if this is an ACL that cannot be captured by
             * the mode bits, go for the server! 
             */
            if (error > 0)
            {
                error = pvfs2_set_acl(inode, ACL_TYPE_ACCESS, clone);
                gossip_debug(GOSSIP_ACL_DEBUG, "pvfs2_set_acl (access) returned %d\n", error);
            }
        }
        posix_acl_release(clone);
    }
    /* If mode of the inode was changed, then do a forcible ->setattr */
    if (ModeFlag(pvfs2_inode))
        pvfs2_flush_inode(inode);
cleanup:
    posix_acl_release(acl);
    return error;
}
Exemple #14
0
/*
 * Initialize the ACLs of a new inode. If parent directory has default ACL,
 * then clone to new inode. Called from ocfs2_mknod.
 */
int ocfs2_init_acl(handle_t *handle,
		   struct inode *inode,
		   struct inode *dir,
		   struct buffer_head *di_bh,
		   struct buffer_head *dir_bh,
		   struct ocfs2_alloc_context *meta_ac,
		   struct ocfs2_alloc_context *data_ac)
{
	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
	struct posix_acl *acl = NULL;
	int ret = 0, ret2;
	mode_t mode;

	if (!S_ISLNK(inode->i_mode)) {
		if (osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) {
			acl = ocfs2_get_acl_nolock(dir, ACL_TYPE_DEFAULT,
						   dir_bh);
			if (IS_ERR(acl))
				return PTR_ERR(acl);
		}
		if (!acl) {
			mode = inode->i_mode & ~current_umask();
			ret = ocfs2_acl_set_mode(inode, di_bh, handle, mode);
			if (ret) {
				mlog_errno(ret);
				goto cleanup;
			}
		}
	}
	if ((osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) && acl) {
		struct posix_acl *clone;

		if (S_ISDIR(inode->i_mode)) {
			ret = ocfs2_set_acl(handle, inode, di_bh,
					    ACL_TYPE_DEFAULT, acl,
					    meta_ac, data_ac);
			if (ret)
				goto cleanup;
		}
		clone = posix_acl_clone(acl, GFP_NOFS);
		ret = -ENOMEM;
		if (!clone)
			goto cleanup;

		mode = inode->i_mode;
		ret = posix_acl_create_masq(clone, &mode);
		if (ret >= 0) {
			ret2 = ocfs2_acl_set_mode(inode, di_bh, handle, mode);
			if (ret2) {
				mlog_errno(ret2);
				ret = ret2;
				goto cleanup;
			}
			if (ret > 0) {
				ret = ocfs2_set_acl(handle, inode,
						    di_bh, ACL_TYPE_ACCESS,
						    clone, meta_ac, data_ac);
			}
		}
		posix_acl_release(clone);
	}
cleanup:
	posix_acl_release(acl);
	return ret;
}