Commit 7b871c77 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull gfs2 setattr updates from Al Viro:
 "Make it possible for filesystems to use a generic 'may_setattr()' and
  switch gfs2 to using it"

* 'work.gfs2' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
  gfs2: Switch to may_setattr in gfs2_setattr
  fs: Move notify_change permission checks into may_setattr
parents e2e694b9 d75b9fa0
Loading
Loading
Loading
Loading
+31 −19
Original line number Diff line number Diff line
@@ -249,6 +249,34 @@ void setattr_copy(struct user_namespace *mnt_userns, struct inode *inode,
}
EXPORT_SYMBOL(setattr_copy);

int may_setattr(struct user_namespace *mnt_userns, struct inode *inode,
		unsigned int ia_valid)
{
	int error;

	if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_TIMES_SET)) {
		if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
			return -EPERM;
	}

	/*
	 * If utimes(2) and friends are called with times == NULL (or both
	 * times are UTIME_NOW), then we need to check for write permission
	 */
	if (ia_valid & ATTR_TOUCH) {
		if (IS_IMMUTABLE(inode))
			return -EPERM;

		if (!inode_owner_or_capable(mnt_userns, inode)) {
			error = inode_permission(mnt_userns, inode, MAY_WRITE);
			if (error)
				return error;
		}
	}
	return 0;
}
EXPORT_SYMBOL(may_setattr);

/**
 * notify_change - modify attributes of a filesytem object
 * @mnt_userns:	user namespace of the mount the inode was found from
@@ -290,25 +318,9 @@ int notify_change(struct user_namespace *mnt_userns, struct dentry *dentry,

	WARN_ON_ONCE(!inode_is_locked(inode));

	if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_TIMES_SET)) {
		if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
			return -EPERM;
	}

	/*
	 * If utimes(2) and friends are called with times == NULL (or both
	 * times are UTIME_NOW), then we need to check for write permission
	 */
	if (ia_valid & ATTR_TOUCH) {
		if (IS_IMMUTABLE(inode))
			return -EPERM;

		if (!inode_owner_or_capable(mnt_userns, inode)) {
			error = inode_permission(mnt_userns, inode, MAY_WRITE);
	error = may_setattr(mnt_userns, inode, ia_valid);
	if (error)
		return error;
		}
	}

	if ((ia_valid & ATTR_MODE)) {
		umode_t amode = attr->ia_mode;
+2 −2
Original line number Diff line number Diff line
@@ -1985,8 +1985,8 @@ static int gfs2_setattr(struct user_namespace *mnt_userns,
	if (error)
		goto out;

	error = -EPERM;
	if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
	error = may_setattr(&init_user_ns, inode, attr->ia_valid);
	if (error)
		goto error;

	error = setattr_prepare(&init_user_ns, dentry, attr);
+2 −0
Original line number Diff line number Diff line
@@ -3439,6 +3439,8 @@ extern int buffer_migrate_page_norefs(struct address_space *,
#define buffer_migrate_page_norefs NULL
#endif

int may_setattr(struct user_namespace *mnt_userns, struct inode *inode,
		unsigned int ia_valid);
int setattr_prepare(struct user_namespace *, struct dentry *, struct iattr *);
extern int inode_newsize_ok(const struct inode *, loff_t offset);
void setattr_copy(struct user_namespace *, struct inode *inode,