Revert "FROMLIST: overlayfs: override_creds=off option bypass creator_cred"
This reverts commit 6120a4d780 as it did
not make it into 5.11-rc1 and causes massive merge issues. If needed,
please forward-port and add it back.
Cc: Mark Salyzyn <salyzyn@android.com>
Bug: 133515582
Bug: 136124883
Bug: 129319403
Change-Id: Ib896e744640d570918af498e1f2bd42d66c33471
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
@@ -137,29 +137,6 @@ Only the lists of names from directories are merged. Other content
|
||||
such as metadata and extended attributes are reported for the upper
|
||||
directory only. These attributes of the lower directory are hidden.
|
||||
|
||||
credentials
|
||||
-----------
|
||||
|
||||
By default, all access to the upper, lower and work directories is the
|
||||
recorded mounter's MAC and DAC credentials. The incoming accesses are
|
||||
checked against the caller's credentials.
|
||||
|
||||
In the case where caller MAC or DAC credentials do not overlap, a
|
||||
use case available in older versions of the driver, the
|
||||
override_creds mount flag can be turned off and help when the use
|
||||
pattern has caller with legitimate credentials where the mounter
|
||||
does not. Several unintended side effects will occur though. The
|
||||
caller without certain key capabilities or lower privilege will not
|
||||
always be able to delete files or directories, create nodes, or
|
||||
search some restricted directories. The ability to search and read
|
||||
a directory entry is spotty as a result of the cache mechanism not
|
||||
retesting the credentials because of the assumption, a privileged
|
||||
caller can fill cache, then a lower privilege can read the directory
|
||||
cache. The uneven security model where cache, upperdir and workdir
|
||||
are opened at privilege, but accessed without creating a form of
|
||||
privilege escalation, should only be used with strict understanding
|
||||
of the side effects and of the security policies.
|
||||
|
||||
whiteouts and opaque directories
|
||||
--------------------------------
|
||||
|
||||
|
||||
@@ -962,7 +962,7 @@ static int ovl_copy_up_flags(struct dentry *dentry, int flags)
|
||||
dput(parent);
|
||||
dput(next);
|
||||
}
|
||||
ovl_revert_creds(dentry->d_sb, old_cred);
|
||||
revert_creds(old_cred);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -565,7 +565,7 @@ static int ovl_create_or_link(struct dentry *dentry, struct inode *inode,
|
||||
struct ovl_cattr *attr, bool origin)
|
||||
{
|
||||
int err;
|
||||
const struct cred *old_cred, *hold_cred = NULL;
|
||||
const struct cred *old_cred;
|
||||
struct cred *override_cred;
|
||||
struct dentry *parent = dentry->d_parent;
|
||||
|
||||
@@ -592,15 +592,14 @@ static int ovl_create_or_link(struct dentry *dentry, struct inode *inode,
|
||||
override_cred->fsgid = inode->i_gid;
|
||||
if (!attr->hardlink) {
|
||||
err = security_dentry_create_files_as(dentry,
|
||||
attr->mode, &dentry->d_name,
|
||||
old_cred ? old_cred : current_cred(),
|
||||
attr->mode, &dentry->d_name, old_cred,
|
||||
override_cred);
|
||||
if (err) {
|
||||
put_cred(override_cred);
|
||||
goto out_revert_creds;
|
||||
}
|
||||
}
|
||||
hold_cred = override_creds(override_cred);
|
||||
put_cred(override_creds(override_cred));
|
||||
put_cred(override_cred);
|
||||
|
||||
if (!ovl_dentry_is_whiteout(dentry))
|
||||
@@ -609,9 +608,7 @@ static int ovl_create_or_link(struct dentry *dentry, struct inode *inode,
|
||||
err = ovl_create_over_whiteout(dentry, inode, attr);
|
||||
}
|
||||
out_revert_creds:
|
||||
ovl_revert_creds(dentry->d_sb, old_cred ?: hold_cred);
|
||||
if (old_cred && hold_cred)
|
||||
put_cred(hold_cred);
|
||||
revert_creds(old_cred);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -687,7 +684,7 @@ static int ovl_set_link_redirect(struct dentry *dentry)
|
||||
|
||||
old_cred = ovl_override_creds(dentry->d_sb);
|
||||
err = ovl_set_redirect(dentry, false);
|
||||
ovl_revert_creds(dentry->d_sb, old_cred);
|
||||
revert_creds(old_cred);
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -906,7 +903,7 @@ static int ovl_do_remove(struct dentry *dentry, bool is_dir)
|
||||
err = ovl_remove_upper(dentry, is_dir, &list);
|
||||
else
|
||||
err = ovl_remove_and_whiteout(dentry, &list);
|
||||
ovl_revert_creds(dentry->d_sb, old_cred);
|
||||
revert_creds(old_cred);
|
||||
if (!err) {
|
||||
if (is_dir)
|
||||
clear_nlink(dentry->d_inode);
|
||||
@@ -1276,7 +1273,7 @@ static int ovl_rename(struct inode *olddir, struct dentry *old,
|
||||
out_unlock:
|
||||
unlock_rename(new_upperdir, old_upperdir);
|
||||
out_revert_creds:
|
||||
ovl_revert_creds(old->d_sb, old_cred);
|
||||
revert_creds(old_cred);
|
||||
if (update_nlink)
|
||||
ovl_nlink_end(new);
|
||||
out_drop_write:
|
||||
|
||||
@@ -59,7 +59,7 @@ static struct file *ovl_open_realfile(const struct file *file,
|
||||
realfile = open_with_fake_path(&file->f_path, flags, realinode,
|
||||
current_cred());
|
||||
}
|
||||
ovl_revert_creds(inode->i_sb, old_cred);
|
||||
revert_creds(old_cred);
|
||||
|
||||
pr_debug("open(%p[%pD2/%c], 0%o) -> (%p, 0%o)\n",
|
||||
file, file, ovl_whatisit(inode, realinode), file->f_flags,
|
||||
@@ -209,7 +209,7 @@ static loff_t ovl_llseek(struct file *file, loff_t offset, int whence)
|
||||
|
||||
old_cred = ovl_override_creds(inode->i_sb);
|
||||
ret = vfs_llseek(real.file, offset, whence);
|
||||
ovl_revert_creds(inode->i_sb, old_cred);
|
||||
revert_creds(old_cred);
|
||||
|
||||
file->f_pos = real.file->f_pos;
|
||||
ovl_inode_unlock(inode);
|
||||
@@ -323,8 +323,7 @@ static ssize_t ovl_read_iter(struct kiocb *iocb, struct iov_iter *iter)
|
||||
ovl_aio_cleanup_handler(aio_req);
|
||||
}
|
||||
out:
|
||||
ovl_revert_creds(file_inode(file)->i_sb, old_cred);
|
||||
|
||||
revert_creds(old_cred);
|
||||
ovl_file_accessed(file);
|
||||
|
||||
fdput(real);
|
||||
@@ -389,7 +388,7 @@ static ssize_t ovl_write_iter(struct kiocb *iocb, struct iov_iter *iter)
|
||||
ovl_aio_cleanup_handler(aio_req);
|
||||
}
|
||||
out:
|
||||
ovl_revert_creds(file_inode(file)->i_sb, old_cred);
|
||||
revert_creds(old_cred);
|
||||
fdput(real);
|
||||
|
||||
out_unlock:
|
||||
@@ -412,7 +411,7 @@ static ssize_t ovl_splice_read(struct file *in, loff_t *ppos,
|
||||
|
||||
old_cred = ovl_override_creds(file_inode(in)->i_sb);
|
||||
ret = generic_file_splice_read(real.file, ppos, pipe, len, flags);
|
||||
ovl_revert_creds(file_inode(in)->i_sb, old_cred);
|
||||
revert_creds(old_cred);
|
||||
|
||||
ovl_file_accessed(in);
|
||||
fdput(real);
|
||||
@@ -433,7 +432,7 @@ ovl_splice_write(struct pipe_inode_info *pipe, struct file *out,
|
||||
|
||||
old_cred = ovl_override_creds(file_inode(out)->i_sb);
|
||||
ret = iter_file_splice_write(pipe, real.file, ppos, len, flags);
|
||||
ovl_revert_creds(file_inode(out)->i_sb, old_cred);
|
||||
revert_creds(old_cred);
|
||||
|
||||
ovl_file_accessed(out);
|
||||
fdput(real);
|
||||
@@ -457,7 +456,7 @@ static int ovl_fsync(struct file *file, loff_t start, loff_t end, int datasync)
|
||||
if (file_inode(real.file) == ovl_inode_upper(file_inode(file))) {
|
||||
old_cred = ovl_override_creds(file_inode(file)->i_sb);
|
||||
ret = vfs_fsync_range(real.file, start, end, datasync);
|
||||
ovl_revert_creds(file_inode(file)->i_sb, old_cred);
|
||||
revert_creds(old_cred);
|
||||
}
|
||||
|
||||
fdput(real);
|
||||
@@ -481,7 +480,7 @@ static int ovl_mmap(struct file *file, struct vm_area_struct *vma)
|
||||
|
||||
old_cred = ovl_override_creds(file_inode(file)->i_sb);
|
||||
ret = call_mmap(vma->vm_file, vma);
|
||||
ovl_revert_creds(file_inode(file)->i_sb, old_cred);
|
||||
revert_creds(old_cred);
|
||||
|
||||
if (ret) {
|
||||
/* Drop reference count from new vm_file value */
|
||||
@@ -509,7 +508,7 @@ static long ovl_fallocate(struct file *file, int mode, loff_t offset, loff_t len
|
||||
|
||||
old_cred = ovl_override_creds(file_inode(file)->i_sb);
|
||||
ret = vfs_fallocate(real.file, mode, offset, len);
|
||||
ovl_revert_creds(file_inode(file)->i_sb, old_cred);
|
||||
revert_creds(old_cred);
|
||||
|
||||
/* Update size */
|
||||
ovl_copyattr(ovl_inode_real(inode), inode);
|
||||
@@ -531,7 +530,7 @@ static int ovl_fadvise(struct file *file, loff_t offset, loff_t len, int advice)
|
||||
|
||||
old_cred = ovl_override_creds(file_inode(file)->i_sb);
|
||||
ret = vfs_fadvise(real.file, offset, len, advice);
|
||||
ovl_revert_creds(file_inode(file)->i_sb, old_cred);
|
||||
revert_creds(old_cred);
|
||||
|
||||
fdput(real);
|
||||
|
||||
@@ -553,7 +552,7 @@ static long ovl_real_ioctl(struct file *file, unsigned int cmd,
|
||||
ret = security_file_ioctl(real.file, cmd, arg);
|
||||
if (!ret)
|
||||
ret = vfs_ioctl(real.file, cmd, arg);
|
||||
ovl_revert_creds(file_inode(file)->i_sb, old_cred);
|
||||
revert_creds(old_cred);
|
||||
|
||||
fdput(real);
|
||||
|
||||
@@ -742,7 +741,7 @@ static loff_t ovl_copyfile(struct file *file_in, loff_t pos_in,
|
||||
flags);
|
||||
break;
|
||||
}
|
||||
ovl_revert_creds(file_inode(file_out)->i_sb, old_cred);
|
||||
revert_creds(old_cred);
|
||||
|
||||
/* Update size */
|
||||
ovl_copyattr(ovl_inode_real(inode_out), inode_out);
|
||||
|
||||
@@ -80,7 +80,7 @@ int ovl_setattr(struct dentry *dentry, struct iattr *attr)
|
||||
inode_lock(upperdentry->d_inode);
|
||||
old_cred = ovl_override_creds(dentry->d_sb);
|
||||
err = notify_change(upperdentry, attr, NULL);
|
||||
ovl_revert_creds(dentry->d_sb, old_cred);
|
||||
revert_creds(old_cred);
|
||||
if (!err)
|
||||
ovl_copyattr(upperdentry->d_inode, dentry->d_inode);
|
||||
inode_unlock(upperdentry->d_inode);
|
||||
@@ -272,7 +272,7 @@ int ovl_getattr(const struct path *path, struct kstat *stat,
|
||||
stat->nlink = dentry->d_inode->i_nlink;
|
||||
|
||||
out:
|
||||
ovl_revert_creds(dentry->d_sb, old_cred);
|
||||
revert_creds(old_cred);
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -306,7 +306,7 @@ int ovl_permission(struct inode *inode, int mask)
|
||||
mask |= MAY_READ;
|
||||
}
|
||||
err = inode_permission(realinode, mask);
|
||||
ovl_revert_creds(inode->i_sb, old_cred);
|
||||
revert_creds(old_cred);
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -323,7 +323,7 @@ static const char *ovl_get_link(struct dentry *dentry,
|
||||
|
||||
old_cred = ovl_override_creds(dentry->d_sb);
|
||||
p = vfs_get_link(ovl_dentry_real(dentry), done);
|
||||
ovl_revert_creds(dentry->d_sb, old_cred);
|
||||
revert_creds(old_cred);
|
||||
return p;
|
||||
}
|
||||
|
||||
@@ -366,7 +366,7 @@ int ovl_xattr_set(struct dentry *dentry, struct inode *inode, const char *name,
|
||||
WARN_ON(flags != XATTR_REPLACE);
|
||||
err = vfs_removexattr(realdentry, name);
|
||||
}
|
||||
ovl_revert_creds(dentry->d_sb, old_cred);
|
||||
revert_creds(old_cred);
|
||||
|
||||
/* copy c/mtime */
|
||||
ovl_copyattr(d_inode(realdentry), inode);
|
||||
@@ -388,7 +388,7 @@ int ovl_xattr_get(struct dentry *dentry, struct inode *inode, const char *name,
|
||||
old_cred = ovl_override_creds(dentry->d_sb);
|
||||
res = __vfs_getxattr(realdentry, d_inode(realdentry), name,
|
||||
value, size, flags);
|
||||
ovl_revert_creds(dentry->d_sb, old_cred);
|
||||
revert_creds(old_cred);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -416,7 +416,7 @@ ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size)
|
||||
|
||||
old_cred = ovl_override_creds(dentry->d_sb);
|
||||
res = vfs_listxattr(realdentry, list, size);
|
||||
ovl_revert_creds(dentry->d_sb, old_cred);
|
||||
revert_creds(old_cred);
|
||||
if (res <= 0 || size == 0)
|
||||
return res;
|
||||
|
||||
@@ -451,7 +451,7 @@ struct posix_acl *ovl_get_acl(struct inode *inode, int type)
|
||||
|
||||
old_cred = ovl_override_creds(inode->i_sb);
|
||||
acl = get_acl(realinode, type);
|
||||
ovl_revert_creds(inode->i_sb, old_cred);
|
||||
revert_creds(old_cred);
|
||||
|
||||
return acl;
|
||||
}
|
||||
@@ -485,7 +485,7 @@ static int ovl_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
|
||||
|
||||
old_cred = ovl_override_creds(inode->i_sb);
|
||||
err = realinode->i_op->fiemap(realinode, fieinfo, start, len);
|
||||
ovl_revert_creds(inode->i_sb, old_cred);
|
||||
revert_creds(old_cred);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -1098,7 +1098,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
|
||||
ovl_dentry_update_reval(dentry, upperdentry,
|
||||
DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE);
|
||||
|
||||
ovl_revert_creds(dentry->d_sb, old_cred);
|
||||
revert_creds(old_cred);
|
||||
if (origin_path) {
|
||||
dput(origin_path->dentry);
|
||||
kfree(origin_path);
|
||||
@@ -1125,7 +1125,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
|
||||
kfree(upperredirect);
|
||||
out:
|
||||
kfree(d.redirect);
|
||||
ovl_revert_creds(dentry->d_sb, old_cred);
|
||||
revert_creds(old_cred);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
@@ -1177,7 +1177,7 @@ bool ovl_lower_positive(struct dentry *dentry)
|
||||
dput(this);
|
||||
}
|
||||
}
|
||||
ovl_revert_creds(dentry->d_sb, old_cred);
|
||||
revert_creds(old_cred);
|
||||
|
||||
return positive;
|
||||
}
|
||||
|
||||
@@ -253,7 +253,6 @@ int ovl_want_write(struct dentry *dentry);
|
||||
void ovl_drop_write(struct dentry *dentry);
|
||||
struct dentry *ovl_workdir(struct dentry *dentry);
|
||||
const struct cred *ovl_override_creds(struct super_block *sb);
|
||||
void ovl_revert_creds(struct super_block *sb, const struct cred *oldcred);
|
||||
int ovl_can_decode_fh(struct super_block *sb);
|
||||
struct dentry *ovl_indexdir(struct super_block *sb);
|
||||
bool ovl_index_all(struct super_block *sb);
|
||||
|
||||
@@ -18,7 +18,6 @@ struct ovl_config {
|
||||
int xino;
|
||||
bool metacopy;
|
||||
bool ovl_volatile;
|
||||
bool override_creds;
|
||||
};
|
||||
|
||||
struct ovl_sb {
|
||||
|
||||
@@ -286,7 +286,7 @@ static int ovl_check_whiteouts(struct dentry *dir, struct ovl_readdir_data *rdd)
|
||||
}
|
||||
inode_unlock(dir->d_inode);
|
||||
}
|
||||
ovl_revert_creds(rdd->dentry->d_sb, old_cred);
|
||||
revert_creds(old_cred);
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -796,7 +796,7 @@ static int ovl_iterate(struct file *file, struct dir_context *ctx)
|
||||
}
|
||||
err = 0;
|
||||
out:
|
||||
ovl_revert_creds(dentry->d_sb, old_cred);
|
||||
revert_creds(old_cred);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -848,7 +848,7 @@ static struct file *ovl_dir_open_realfile(const struct file *file,
|
||||
|
||||
old_cred = ovl_override_creds(file_inode(file)->i_sb);
|
||||
res = ovl_path_open(realpath, O_RDONLY | (file->f_flags & O_LARGEFILE));
|
||||
ovl_revert_creds(file_inode(file)->i_sb, old_cred);
|
||||
revert_creds(old_cred);
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -986,7 +986,7 @@ int ovl_check_empty_dir(struct dentry *dentry, struct list_head *list)
|
||||
|
||||
old_cred = ovl_override_creds(dentry->d_sb);
|
||||
err = ovl_dir_read_merged(dentry, list, &root);
|
||||
ovl_revert_creds(dentry->d_sb, old_cred);
|
||||
revert_creds(old_cred);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
||||
@@ -53,11 +53,6 @@ module_param_named(xino_auto, ovl_xino_auto_def, bool, 0644);
|
||||
MODULE_PARM_DESC(xino_auto,
|
||||
"Auto enable xino feature");
|
||||
|
||||
static bool __read_mostly ovl_override_creds_def = true;
|
||||
module_param_named(override_creds, ovl_override_creds_def, bool, 0644);
|
||||
MODULE_PARM_DESC(ovl_override_creds_def,
|
||||
"Use mounter's credentials for accesses");
|
||||
|
||||
static void ovl_entry_stack_free(struct ovl_entry *oe)
|
||||
{
|
||||
unsigned int i;
|
||||
@@ -371,9 +366,6 @@ static int ovl_show_options(struct seq_file *m, struct dentry *dentry)
|
||||
ofs->config.metacopy ? "on" : "off");
|
||||
if (ofs->config.ovl_volatile)
|
||||
seq_puts(m, ",volatile");
|
||||
if (ofs->config.override_creds != ovl_override_creds_def)
|
||||
seq_show_option(m, "override_creds",
|
||||
ofs->config.override_creds ? "on" : "off");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -426,8 +418,6 @@ enum {
|
||||
OPT_METACOPY_ON,
|
||||
OPT_METACOPY_OFF,
|
||||
OPT_VOLATILE,
|
||||
OPT_OVERRIDE_CREDS_ON,
|
||||
OPT_OVERRIDE_CREDS_OFF,
|
||||
OPT_ERR,
|
||||
};
|
||||
|
||||
@@ -447,8 +437,6 @@ static const match_table_t ovl_tokens = {
|
||||
{OPT_METACOPY_ON, "metacopy=on"},
|
||||
{OPT_METACOPY_OFF, "metacopy=off"},
|
||||
{OPT_VOLATILE, "volatile"},
|
||||
{OPT_OVERRIDE_CREDS_ON, "override_creds=on"},
|
||||
{OPT_OVERRIDE_CREDS_OFF, "override_creds=off"},
|
||||
{OPT_ERR, NULL}
|
||||
};
|
||||
|
||||
@@ -508,7 +496,6 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config)
|
||||
config->redirect_mode = kstrdup(ovl_redirect_mode_def(), GFP_KERNEL);
|
||||
if (!config->redirect_mode)
|
||||
return -ENOMEM;
|
||||
config->override_creds = ovl_override_creds_def;
|
||||
|
||||
while ((p = ovl_next_opt(&opt)) != NULL) {
|
||||
int token;
|
||||
@@ -598,14 +585,6 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config)
|
||||
config->ovl_volatile = true;
|
||||
break;
|
||||
|
||||
case OPT_OVERRIDE_CREDS_ON:
|
||||
config->override_creds = true;
|
||||
break;
|
||||
|
||||
case OPT_OVERRIDE_CREDS_OFF:
|
||||
config->override_creds = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
pr_err("unrecognized mount option \"%s\" or missing value\n",
|
||||
p);
|
||||
@@ -2028,6 +2007,7 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
|
||||
kfree(splitlower);
|
||||
|
||||
sb->s_root = root_dentry;
|
||||
|
||||
return 0;
|
||||
|
||||
out_free_oe:
|
||||
|
||||
@@ -37,17 +37,9 @@ const struct cred *ovl_override_creds(struct super_block *sb)
|
||||
{
|
||||
struct ovl_fs *ofs = sb->s_fs_info;
|
||||
|
||||
if (!ofs->config.override_creds)
|
||||
return NULL;
|
||||
return override_creds(ofs->creator_cred);
|
||||
}
|
||||
|
||||
void ovl_revert_creds(struct super_block *sb, const struct cred *old_cred)
|
||||
{
|
||||
if (old_cred)
|
||||
revert_creds(old_cred);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if underlying fs supports file handles and try to determine encoding
|
||||
* type, in order to deduce maximum inode number used by fs.
|
||||
@@ -831,7 +823,7 @@ int ovl_nlink_start(struct dentry *dentry)
|
||||
* value relative to the upper inode nlink in an upper inode xattr.
|
||||
*/
|
||||
err = ovl_set_nlink_upper(dentry);
|
||||
ovl_revert_creds(dentry->d_sb, old_cred);
|
||||
revert_creds(old_cred);
|
||||
|
||||
out:
|
||||
if (err)
|
||||
@@ -849,7 +841,7 @@ void ovl_nlink_end(struct dentry *dentry)
|
||||
|
||||
old_cred = ovl_override_creds(dentry->d_sb);
|
||||
ovl_cleanup_index(dentry);
|
||||
ovl_revert_creds(dentry->d_sb, old_cred);
|
||||
revert_creds(old_cred);
|
||||
}
|
||||
|
||||
ovl_inode_unlock(inode);
|
||||
|
||||
Reference in New Issue
Block a user