Replace the override_creds_light()/revert_creds_light() pairs of operations with cred_guard()/cred_scoped_guard(). In ovl_setattr(), ovl_set_or_remove_acl() and ovl_fileattr_set() use cred_scoped_guard(), because of 'goto', which can cause the cleanup flow to run on garbage memory. Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@xxxxxxxxx> --- fs/overlayfs/inode.c | 73 +++++++++++++++++--------------------------- 1 file changed, 28 insertions(+), 45 deletions(-) diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index 30460d718605..a597e748397f 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c @@ -25,7 +25,6 @@ int ovl_setattr(struct mnt_idmap *idmap, struct dentry *dentry, struct ovl_fs *ofs = OVL_FS(dentry->d_sb); bool full_copy_up = false; struct dentry *upperdentry; - const struct cred *old_cred; err = setattr_prepare(&nop_mnt_idmap, dentry, attr); if (err) @@ -78,9 +77,8 @@ int ovl_setattr(struct mnt_idmap *idmap, struct dentry *dentry, goto out_put_write; inode_lock(upperdentry->d_inode); - old_cred = ovl_override_creds_light(dentry->d_sb); - err = ovl_do_notify_change(ofs, upperdentry, attr); - revert_creds_light(old_cred); + cred_scoped_guard(ovl_creds(dentry->d_sb)) + err = ovl_do_notify_change(ofs, upperdentry, attr); if (!err) ovl_copyattr(dentry->d_inode); inode_unlock(upperdentry->d_inode); @@ -159,7 +157,6 @@ int ovl_getattr(struct mnt_idmap *idmap, const struct path *path, struct dentry *dentry = path->dentry; enum ovl_path_type type; struct path realpath; - const struct cred *old_cred; struct inode *inode = d_inode(dentry); bool is_dir = S_ISDIR(inode->i_mode); int fsid = 0; @@ -169,7 +166,7 @@ int ovl_getattr(struct mnt_idmap *idmap, const struct path *path, metacopy_blocks = ovl_is_metacopy_dentry(dentry); type = ovl_path_real(dentry, &realpath); - old_cred = ovl_override_creds_light(dentry->d_sb); + cred_guard(ovl_creds(dentry->d_sb)); err = ovl_do_getattr(&realpath, stat, request_mask, flags); if (err) goto out; @@ -280,7 +277,6 @@ int ovl_getattr(struct mnt_idmap *idmap, const struct path *path, stat->nlink = dentry->d_inode->i_nlink; out: - revert_creds_light(old_cred); return err; } @@ -291,7 +287,6 @@ int ovl_permission(struct mnt_idmap *idmap, struct inode *upperinode = ovl_inode_upper(inode); struct inode *realinode; struct path realpath; - const struct cred *old_cred; int err; /* Careful in RCU walk mode */ @@ -309,7 +304,7 @@ int ovl_permission(struct mnt_idmap *idmap, if (err) return err; - old_cred = ovl_override_creds_light(inode->i_sb); + cred_guard(ovl_creds(inode->i_sb)); if (!upperinode && !special_file(realinode->i_mode) && mask & MAY_WRITE) { mask &= ~(MAY_WRITE | MAY_APPEND); @@ -317,7 +312,6 @@ int ovl_permission(struct mnt_idmap *idmap, mask |= MAY_READ; } err = inode_permission(mnt_idmap(realpath.mnt), realinode, mask); - revert_creds_light(old_cred); return err; } @@ -326,15 +320,13 @@ static const char *ovl_get_link(struct dentry *dentry, struct inode *inode, struct delayed_call *done) { - const struct cred *old_cred; const char *p; if (!dentry) return ERR_PTR(-ECHILD); - old_cred = ovl_override_creds_light(dentry->d_sb); + cred_guard(ovl_creds(dentry->d_sb)); p = vfs_get_link(ovl_dentry_real(dentry), done); - revert_creds_light(old_cred); return p; } @@ -465,11 +457,9 @@ struct posix_acl *do_ovl_get_acl(struct mnt_idmap *idmap, acl = get_cached_acl_rcu(realinode, type); } else { - const struct cred *old_cred; - old_cred = ovl_override_creds_light(inode->i_sb); + cred_guard(ovl_creds(inode->i_sb)); acl = ovl_get_acl_path(&realpath, posix_acl_xattr_name(type), noperm); - revert_creds_light(old_cred); } return acl; @@ -481,7 +471,6 @@ static int ovl_set_or_remove_acl(struct dentry *dentry, struct inode *inode, int err; struct path realpath; const char *acl_name; - const struct cred *old_cred; struct ovl_fs *ofs = OVL_FS(dentry->d_sb); struct dentry *upperdentry = ovl_dentry_upper(dentry); struct dentry *realdentry = upperdentry ?: ovl_dentry_lower(dentry); @@ -495,10 +484,9 @@ static int ovl_set_or_remove_acl(struct dentry *dentry, struct inode *inode, struct posix_acl *real_acl; ovl_path_lower(dentry, &realpath); - old_cred = ovl_override_creds_light(dentry->d_sb); + cred_guard(ovl_creds(dentry->d_sb)); real_acl = vfs_get_acl(mnt_idmap(realpath.mnt), realdentry, acl_name); - revert_creds_light(old_cred); if (IS_ERR(real_acl)) { err = PTR_ERR(real_acl); goto out; @@ -518,12 +506,12 @@ static int ovl_set_or_remove_acl(struct dentry *dentry, struct inode *inode, if (err) goto out; - old_cred = ovl_override_creds_light(dentry->d_sb); - if (acl) - err = ovl_do_set_acl(ofs, realdentry, acl_name, acl); - else - err = ovl_do_remove_acl(ofs, realdentry, acl_name); - revert_creds_light(old_cred); + cred_scoped_guard(ovl_creds(dentry->d_sb)) { + if (acl) + err = ovl_do_set_acl(ofs, realdentry, acl_name, acl); + else + err = ovl_do_remove_acl(ofs, realdentry, acl_name); + } ovl_drop_write(dentry); /* copy c/mtime */ @@ -590,7 +578,6 @@ static int ovl_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, { int err; struct inode *realinode = ovl_inode_realdata(inode); - const struct cred *old_cred; if (!realinode) return -EIO; @@ -598,9 +585,8 @@ static int ovl_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, if (!realinode->i_op->fiemap) return -EOPNOTSUPP; - old_cred = ovl_override_creds_light(inode->i_sb); + cred_guard(ovl_creds(inode->i_sb)); err = realinode->i_op->fiemap(realinode, fieinfo, start, len); - revert_creds_light(old_cred); return err; } @@ -648,7 +634,6 @@ int ovl_fileattr_set(struct mnt_idmap *idmap, { struct inode *inode = d_inode(dentry); struct path upperpath; - const struct cred *old_cred; unsigned int flags; int err; @@ -660,19 +645,19 @@ int ovl_fileattr_set(struct mnt_idmap *idmap, if (err) goto out; - old_cred = ovl_override_creds_light(inode->i_sb); - /* - * Store immutable/append-only flags in xattr and clear them - * in upper fileattr (in case they were set by older kernel) - * so children of "ovl-immutable" directories lower aliases of - * "ovl-immutable" hardlinks could be copied up. - * Clear xattr when flags are cleared. - */ - err = ovl_set_protattr(inode, upperpath.dentry, fa); - if (!err) - err = ovl_real_fileattr_set(&upperpath, fa); - revert_creds_light(old_cred); - ovl_drop_write(dentry); + cred_scoped_guard(ovl_creds(inode->i_sb)) { + /* + * Store immutable/append-only flags in xattr and clear them + * in upper fileattr (in case they were set by older kernel) + * so children of "ovl-immutable" directories lower aliases of + * "ovl-immutable" hardlinks could be copied up. + * Clear xattr when flags are cleared. + */ + err = ovl_set_protattr(inode, upperpath.dentry, fa); + if (!err) + err = ovl_real_fileattr_set(&upperpath, fa); + ovl_drop_write(dentry); + } /* * Merge real inode flags with inode flags read from @@ -725,15 +710,13 @@ int ovl_fileattr_get(struct dentry *dentry, struct fileattr *fa) { struct inode *inode = d_inode(dentry); struct path realpath; - const struct cred *old_cred; int err; ovl_path_real(dentry, &realpath); - old_cred = ovl_override_creds_light(inode->i_sb); + cred_guard(ovl_creds(inode->i_sb)); err = ovl_real_fileattr_get(&realpath, fa); ovl_fileattr_prot_flags(inode, fa); - revert_creds_light(old_cred); return err; } -- 2.46.0