Commit 7b871c77 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'work.gfs2' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

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
...@@ -249,6 +249,34 @@ void setattr_copy(struct user_namespace *mnt_userns, struct inode *inode, ...@@ -249,6 +249,34 @@ void setattr_copy(struct user_namespace *mnt_userns, struct inode *inode,
} }
EXPORT_SYMBOL(setattr_copy); 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 * notify_change - modify attributes of a filesytem object
* @mnt_userns: user namespace of the mount the inode was found from * @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, ...@@ -290,25 +318,9 @@ int notify_change(struct user_namespace *mnt_userns, struct dentry *dentry,
WARN_ON_ONCE(!inode_is_locked(inode)); WARN_ON_ONCE(!inode_is_locked(inode));
if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_TIMES_SET)) { error = may_setattr(mnt_userns, inode, ia_valid);
if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) if (error)
return -EPERM; return error;
}
/*
* 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;
}
}
if ((ia_valid & ATTR_MODE)) { if ((ia_valid & ATTR_MODE)) {
umode_t amode = attr->ia_mode; umode_t amode = attr->ia_mode;
......
...@@ -1985,8 +1985,8 @@ static int gfs2_setattr(struct user_namespace *mnt_userns, ...@@ -1985,8 +1985,8 @@ static int gfs2_setattr(struct user_namespace *mnt_userns,
if (error) if (error)
goto out; goto out;
error = -EPERM; error = may_setattr(&init_user_ns, inode, attr->ia_valid);
if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) if (error)
goto error; goto error;
error = setattr_prepare(&init_user_ns, dentry, attr); error = setattr_prepare(&init_user_ns, dentry, attr);
......
...@@ -3439,6 +3439,8 @@ extern int buffer_migrate_page_norefs(struct address_space *, ...@@ -3439,6 +3439,8 @@ extern int buffer_migrate_page_norefs(struct address_space *,
#define buffer_migrate_page_norefs NULL #define buffer_migrate_page_norefs NULL
#endif #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 *); int setattr_prepare(struct user_namespace *, struct dentry *, struct iattr *);
extern int inode_newsize_ok(const struct inode *, loff_t offset); extern int inode_newsize_ok(const struct inode *, loff_t offset);
void setattr_copy(struct user_namespace *, struct inode *inode, void setattr_copy(struct user_namespace *, struct inode *inode,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment