diff options
Diffstat (limited to 'fs/overlayfs/copy_up.c')
-rw-r--r-- | fs/overlayfs/copy_up.c | 90 |
1 files changed, 49 insertions, 41 deletions
diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c index e040970408d4..714ec569d25b 100644 --- a/fs/overlayfs/copy_up.c +++ b/fs/overlayfs/copy_up.c @@ -44,9 +44,9 @@ static bool ovl_must_copy_xattr(const char *name) !strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN); } -int ovl_copy_xattr(struct super_block *sb, struct dentry *old, - struct dentry *new) +int ovl_copy_xattr(struct super_block *sb, struct path *oldpath, struct dentry *new) { + struct dentry *old = oldpath->dentry; ssize_t list_size, size, value_size = 0; char *buf, *name, *value = NULL; int error = 0; @@ -94,9 +94,9 @@ int ovl_copy_xattr(struct super_block *sb, struct dentry *old, continue; /* Discard */ } retry: - size = vfs_getxattr(&init_user_ns, old, name, value, value_size); + size = ovl_do_getxattr(oldpath, name, value, value_size); if (size == -ERANGE) - size = vfs_getxattr(&init_user_ns, old, name, NULL, 0); + size = ovl_do_getxattr(oldpath, name, NULL, 0); if (size < 0) { error = size; @@ -117,7 +117,7 @@ retry: goto retry; } - error = vfs_setxattr(&init_user_ns, new, name, value, size, 0); + error = ovl_do_setxattr(OVL_FS(sb), new, name, value, size, 0); if (error) { if (error != -EOPNOTSUPP || ovl_must_copy_xattr(name)) break; @@ -292,17 +292,19 @@ out_fput: return error; } -static int ovl_set_size(struct dentry *upperdentry, struct kstat *stat) +static int ovl_set_size(struct ovl_fs *ofs, + struct dentry *upperdentry, struct kstat *stat) { struct iattr attr = { .ia_valid = ATTR_SIZE, .ia_size = stat->size, }; - return notify_change(&init_user_ns, upperdentry, &attr, NULL); + return ovl_do_notify_change(ofs, upperdentry, &attr); } -static int ovl_set_timestamps(struct dentry *upperdentry, struct kstat *stat) +static int ovl_set_timestamps(struct ovl_fs *ofs, struct dentry *upperdentry, + struct kstat *stat) { struct iattr attr = { .ia_valid = @@ -311,10 +313,11 @@ static int ovl_set_timestamps(struct dentry *upperdentry, struct kstat *stat) .ia_mtime = stat->mtime, }; - return notify_change(&init_user_ns, upperdentry, &attr, NULL); + return ovl_do_notify_change(ofs, upperdentry, &attr); } -int ovl_set_attr(struct dentry *upperdentry, struct kstat *stat) +int ovl_set_attr(struct ovl_fs *ofs, struct dentry *upperdentry, + struct kstat *stat) { int err = 0; @@ -323,7 +326,7 @@ int ovl_set_attr(struct dentry *upperdentry, struct kstat *stat) .ia_valid = ATTR_MODE, .ia_mode = stat->mode, }; - err = notify_change(&init_user_ns, upperdentry, &attr, NULL); + err = ovl_do_notify_change(ofs, upperdentry, &attr); } if (!err) { struct iattr attr = { @@ -331,10 +334,10 @@ int ovl_set_attr(struct dentry *upperdentry, struct kstat *stat) .ia_uid = stat->uid, .ia_gid = stat->gid, }; - err = notify_change(&init_user_ns, upperdentry, &attr, NULL); + err = ovl_do_notify_change(ofs, upperdentry, &attr); } if (!err) - ovl_set_timestamps(upperdentry, stat); + ovl_set_timestamps(ofs, upperdentry, stat); return err; } @@ -433,7 +436,7 @@ static int ovl_set_upper_fh(struct ovl_fs *ofs, struct dentry *upper, if (IS_ERR(fh)) return PTR_ERR(fh); - err = ovl_do_setxattr(ofs, index, OVL_XATTR_UPPER, fh->buf, fh->fb.len); + err = ovl_setxattr(ofs, index, OVL_XATTR_UPPER, fh->buf, fh->fb.len); kfree(fh); return err; @@ -474,7 +477,7 @@ static int ovl_create_index(struct dentry *dentry, struct dentry *origin, if (err) return err; - temp = ovl_create_temp(indexdir, OVL_CATTR(S_IFDIR | 0)); + temp = ovl_create_temp(ofs, indexdir, OVL_CATTR(S_IFDIR | 0)); err = PTR_ERR(temp); if (IS_ERR(temp)) goto free_name; @@ -483,16 +486,16 @@ static int ovl_create_index(struct dentry *dentry, struct dentry *origin, if (err) goto out; - index = lookup_one_len(name.name, indexdir, name.len); + index = ovl_lookup_upper(ofs, name.name, indexdir, name.len); if (IS_ERR(index)) { err = PTR_ERR(index); } else { - err = ovl_do_rename(dir, temp, dir, index, 0); + err = ovl_do_rename(ofs, dir, temp, dir, index, 0); dput(index); } out: if (err) - ovl_cleanup(dir, temp); + ovl_cleanup(ofs, dir, temp); dput(temp); free_name: kfree(name.name); @@ -519,6 +522,7 @@ static int ovl_link_up(struct ovl_copy_up_ctx *c) int err; struct dentry *upper; struct dentry *upperdir = ovl_dentry_upper(c->parent); + struct ovl_fs *ofs = OVL_FS(c->dentry->d_sb); struct inode *udir = d_inode(upperdir); /* Mark parent "impure" because it may now contain non-pure upper */ @@ -531,16 +535,16 @@ static int ovl_link_up(struct ovl_copy_up_ctx *c) return err; inode_lock_nested(udir, I_MUTEX_PARENT); - upper = lookup_one_len(c->dentry->d_name.name, upperdir, - c->dentry->d_name.len); + upper = ovl_lookup_upper(ofs, c->dentry->d_name.name, upperdir, + c->dentry->d_name.len); err = PTR_ERR(upper); if (!IS_ERR(upper)) { - err = ovl_do_link(ovl_dentry_upper(c->dentry), udir, upper); + err = ovl_do_link(ofs, ovl_dentry_upper(c->dentry), udir, upper); dput(upper); if (!err) { /* Restore timestamps on parent (best effort) */ - ovl_set_timestamps(upperdir, &c->pstat); + ovl_set_timestamps(ofs, upperdir, &c->pstat); ovl_dentry_set_upper_alias(c->dentry); } } @@ -578,7 +582,7 @@ static int ovl_copy_up_inode(struct ovl_copy_up_ctx *c, struct dentry *temp) return err; } - err = ovl_copy_xattr(c->dentry->d_sb, c->lowerpath.dentry, temp); + err = ovl_copy_xattr(c->dentry->d_sb, &c->lowerpath, temp); if (err) return err; @@ -614,9 +618,9 @@ static int ovl_copy_up_inode(struct ovl_copy_up_ctx *c, struct dentry *temp) inode_lock(temp->d_inode); if (S_ISREG(c->stat.mode)) - err = ovl_set_size(temp, &c->stat); + err = ovl_set_size(ofs, temp, &c->stat); if (!err) - err = ovl_set_attr(temp, &c->stat); + err = ovl_set_attr(ofs, temp, &c->stat); inode_unlock(temp->d_inode); return err; @@ -656,6 +660,7 @@ static void ovl_revert_cu_creds(struct ovl_cu_creds *cc) */ static int ovl_copy_up_workdir(struct ovl_copy_up_ctx *c) { + struct ovl_fs *ofs = OVL_FS(c->dentry->d_sb); struct inode *inode; struct inode *udir = d_inode(c->destdir), *wdir = d_inode(c->workdir); struct dentry *temp, *upper; @@ -677,7 +682,7 @@ static int ovl_copy_up_workdir(struct ovl_copy_up_ctx *c) if (err) goto unlock; - temp = ovl_create_temp(c->workdir, &cattr); + temp = ovl_create_temp(ofs, c->workdir, &cattr); ovl_revert_cu_creds(&cc); err = PTR_ERR(temp); @@ -694,12 +699,13 @@ static int ovl_copy_up_workdir(struct ovl_copy_up_ctx *c) goto cleanup; } - upper = lookup_one_len(c->destname.name, c->destdir, c->destname.len); + upper = ovl_lookup_upper(ofs, c->destname.name, c->destdir, + c->destname.len); err = PTR_ERR(upper); if (IS_ERR(upper)) goto cleanup; - err = ovl_do_rename(wdir, temp, udir, upper, 0); + err = ovl_do_rename(ofs, wdir, temp, udir, upper, 0); dput(upper); if (err) goto cleanup; @@ -716,7 +722,7 @@ unlock: return err; cleanup: - ovl_cleanup(wdir, temp); + ovl_cleanup(ofs, wdir, temp); dput(temp); goto unlock; } @@ -724,6 +730,7 @@ cleanup: /* Copyup using O_TMPFILE which does not require cross dir locking */ static int ovl_copy_up_tmpfile(struct ovl_copy_up_ctx *c) { + struct ovl_fs *ofs = OVL_FS(c->dentry->d_sb); struct inode *udir = d_inode(c->destdir); struct dentry *temp, *upper; struct ovl_cu_creds cc; @@ -733,7 +740,7 @@ static int ovl_copy_up_tmpfile(struct ovl_copy_up_ctx *c) if (err) return err; - temp = ovl_do_tmpfile(c->workdir, c->stat.mode); + temp = ovl_do_tmpfile(ofs, c->workdir, c->stat.mode); ovl_revert_cu_creds(&cc); if (IS_ERR(temp)) @@ -745,10 +752,11 @@ static int ovl_copy_up_tmpfile(struct ovl_copy_up_ctx *c) inode_lock_nested(udir, I_MUTEX_PARENT); - upper = lookup_one_len(c->destname.name, c->destdir, c->destname.len); + upper = ovl_lookup_upper(ofs, c->destname.name, c->destdir, + c->destname.len); err = PTR_ERR(upper); if (!IS_ERR(upper)) { - err = ovl_do_link(temp, udir, upper); + err = ovl_do_link(ofs, temp, udir, upper); dput(upper); } inode_unlock(udir); @@ -836,7 +844,7 @@ static int ovl_do_copy_up(struct ovl_copy_up_ctx *c) /* Restore timestamps on parent (best effort) */ inode_lock(udir); - ovl_set_timestamps(c->destdir, &c->pstat); + ovl_set_timestamps(ofs, c->destdir, &c->pstat); inode_unlock(udir); ovl_dentry_set_upper_alias(c->dentry); @@ -865,12 +873,12 @@ static bool ovl_need_meta_copy_up(struct dentry *dentry, umode_t mode, return true; } -static ssize_t ovl_getxattr(struct dentry *dentry, char *name, char **value) +static ssize_t ovl_getxattr_value(struct path *path, char *name, char **value) { ssize_t res; char *buf; - res = vfs_getxattr(&init_user_ns, dentry, name, NULL, 0); + res = ovl_do_getxattr(path, name, NULL, 0); if (res == -ENODATA || res == -EOPNOTSUPP) res = 0; @@ -879,7 +887,7 @@ static ssize_t ovl_getxattr(struct dentry *dentry, char *name, char **value) if (!buf) return -ENOMEM; - res = vfs_getxattr(&init_user_ns, dentry, name, buf, res); + res = ovl_do_getxattr(path, name, buf, res); if (res < 0) kfree(buf); else @@ -906,8 +914,8 @@ static int ovl_copy_up_meta_inode_data(struct ovl_copy_up_ctx *c) return -EIO; if (c->stat.size) { - err = cap_size = ovl_getxattr(upperpath.dentry, XATTR_NAME_CAPS, - &capability); + err = cap_size = ovl_getxattr_value(&upperpath, XATTR_NAME_CAPS, + &capability); if (cap_size < 0) goto out; } @@ -921,14 +929,14 @@ static int ovl_copy_up_meta_inode_data(struct ovl_copy_up_ctx *c) * don't want that to happen for normal copy-up operation. */ if (capability) { - err = vfs_setxattr(&init_user_ns, upperpath.dentry, - XATTR_NAME_CAPS, capability, cap_size, 0); + err = ovl_do_setxattr(ofs, upperpath.dentry, XATTR_NAME_CAPS, + capability, cap_size, 0); if (err) goto out_free; } - err = ovl_do_removexattr(ofs, upperpath.dentry, OVL_XATTR_METACOPY); + err = ovl_removexattr(ofs, upperpath.dentry, OVL_XATTR_METACOPY); if (err) goto out_free; |