summaryrefslogtreecommitdiffstats
path: root/fs/overlayfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/overlayfs')
-rw-r--r--fs/overlayfs/copy_up.c26
-rw-r--r--fs/overlayfs/dir.c13
-rw-r--r--fs/overlayfs/inode.c8
-rw-r--r--fs/overlayfs/super.c6
4 files changed, 38 insertions, 15 deletions
diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
index 43fdc2765aea..3f803b3a1f82 100644
--- a/fs/overlayfs/copy_up.c
+++ b/fs/overlayfs/copy_up.c
@@ -58,8 +58,8 @@ int ovl_copy_xattr(struct dentry *old, struct dentry *new)
char *buf, *name, *value = NULL;
int uninitialized_var(error);
- if (!old->d_inode->i_op->getxattr ||
- !new->d_inode->i_op->getxattr)
+ if (!(old->d_inode->i_opflags & IOP_XATTR) ||
+ !(new->d_inode->i_opflags & IOP_XATTR))
return 0;
list_size = vfs_listxattr(old, NULL, 0);
@@ -105,6 +105,13 @@ retry:
goto retry;
}
+ error = security_inode_copy_up_xattr(name);
+ if (error < 0 && error != -EOPNOTSUPP)
+ break;
+ if (error == 1) {
+ error = 0;
+ continue; /* Discard */
+ }
error = vfs_setxattr(new, name, value, size, 0);
if (error)
break;
@@ -248,6 +255,8 @@ static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir,
struct dentry *upper = NULL;
umode_t mode = stat->mode;
int err;
+ const struct cred *old_creds = NULL;
+ struct cred *new_creds = NULL;
newdentry = ovl_lookup_temp(workdir, dentry);
err = PTR_ERR(newdentry);
@@ -260,10 +269,23 @@ static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir,
if (IS_ERR(upper))
goto out1;
+ err = security_inode_copy_up(dentry, &new_creds);
+ if (err < 0)
+ goto out2;
+
+ if (new_creds)
+ old_creds = override_creds(new_creds);
+
/* Can't properly set mode on creation because of the umask */
stat->mode &= S_IFMT;
err = ovl_create_real(wdir, newdentry, stat, link, NULL, true);
stat->mode = mode;
+
+ if (new_creds) {
+ revert_creds(old_creds);
+ put_cred(new_creds);
+ }
+
if (err)
goto out2;
diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
index 480fc7868a2f..5f90ddf778ba 100644
--- a/fs/overlayfs/dir.c
+++ b/fs/overlayfs/dir.c
@@ -489,6 +489,15 @@ static int ovl_create_or_link(struct dentry *dentry, struct inode *inode,
if (override_cred) {
override_cred->fsuid = inode->i_uid;
override_cred->fsgid = inode->i_gid;
+ if (!hardlink) {
+ err = security_dentry_create_files_as(dentry,
+ stat->mode, &dentry->d_name, old_cred,
+ override_cred);
+ if (err) {
+ put_cred(override_cred);
+ goto out_revert_creds;
+ }
+ }
put_cred(override_creds(override_cred));
put_cred(override_cred);
@@ -499,6 +508,7 @@ static int ovl_create_or_link(struct dentry *dentry, struct inode *inode,
err = ovl_create_over_whiteout(dentry, inode, stat,
link, hardlink);
}
+out_revert_creds:
revert_creds(old_cred);
if (!err) {
struct inode *realinode = d_inode(ovl_dentry_upper(dentry));
@@ -1003,10 +1013,7 @@ const struct inode_operations ovl_dir_inode_operations = {
.mknod = ovl_mknod,
.permission = ovl_permission,
.getattr = ovl_dir_getattr,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = ovl_listxattr,
- .removexattr = generic_removexattr,
.get_acl = ovl_get_acl,
.update_time = ovl_update_time,
};
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
index c75625c1efa3..c18d6a4ff456 100644
--- a/fs/overlayfs/inode.c
+++ b/fs/overlayfs/inode.c
@@ -53,7 +53,7 @@ int ovl_setattr(struct dentry *dentry, struct iattr *attr)
* inode_newsize_ok() will always check against MAX_LFS_FILESIZE and not
* check for a swapfile (which this won't be anyway).
*/
- err = inode_change_ok(dentry->d_inode, attr);
+ err = setattr_prepare(dentry, attr);
if (err)
return err;
@@ -367,10 +367,7 @@ static const struct inode_operations ovl_file_inode_operations = {
.setattr = ovl_setattr,
.permission = ovl_permission,
.getattr = ovl_getattr,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = ovl_listxattr,
- .removexattr = generic_removexattr,
.get_acl = ovl_get_acl,
.update_time = ovl_update_time,
};
@@ -380,10 +377,7 @@ static const struct inode_operations ovl_symlink_inode_operations = {
.get_link = ovl_get_link,
.readlink = ovl_readlink,
.getattr = ovl_getattr,
- .setxattr = generic_setxattr,
- .getxattr = generic_getxattr,
.listxattr = ovl_listxattr,
- .removexattr = generic_removexattr,
.update_time = ovl_update_time,
};
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index e2a94a26767b..7e3f0127fc1a 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -275,10 +275,10 @@ static bool ovl_is_opaquedir(struct dentry *dentry)
char val;
struct inode *inode = dentry->d_inode;
- if (!S_ISDIR(inode->i_mode) || !inode->i_op->getxattr)
+ if (!S_ISDIR(inode->i_mode) || !(inode->i_opflags & IOP_XATTR))
return false;
- res = inode->i_op->getxattr(dentry, inode, OVL_XATTR_OPAQUE, &val, 1);
+ res = __vfs_getxattr(dentry, inode, OVL_XATTR_OPAQUE, &val, 1);
if (res == 1 && val == 'y')
return true;
@@ -1320,7 +1320,7 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
sb->s_xattr = ovl_xattr_handlers;
sb->s_root = root_dentry;
sb->s_fs_info = ufs;
- sb->s_flags |= MS_POSIXACL;
+ sb->s_flags |= MS_POSIXACL | MS_NOREMOTELOCK;
return 0;