ovl: check namelen
We already calculate f_namelen in statfs as the maximum of the name lengths provided by the filesystems taking part in the overlay. Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
This commit is contained in:
parent
bbb1e54dd5
commit
6b2d5fe46f
|
@ -20,7 +20,8 @@ static struct dentry *ovl_lookup_real(struct dentry *dir,
|
||||||
|
|
||||||
dentry = lookup_one_len_unlocked(name->name, dir, name->len);
|
dentry = lookup_one_len_unlocked(name->name, dir, name->len);
|
||||||
if (IS_ERR(dentry)) {
|
if (IS_ERR(dentry)) {
|
||||||
if (PTR_ERR(dentry) == -ENOENT)
|
if (PTR_ERR(dentry) == -ENOENT ||
|
||||||
|
PTR_ERR(dentry) == -ENAMETOOLONG)
|
||||||
dentry = NULL;
|
dentry = NULL;
|
||||||
} else if (!dentry->d_inode) {
|
} else if (!dentry->d_inode) {
|
||||||
dput(dentry);
|
dput(dentry);
|
||||||
|
@ -74,6 +75,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
|
||||||
{
|
{
|
||||||
struct ovl_entry *oe;
|
struct ovl_entry *oe;
|
||||||
const struct cred *old_cred;
|
const struct cred *old_cred;
|
||||||
|
struct ovl_fs *ofs = dentry->d_sb->s_fs_info;
|
||||||
struct ovl_entry *poe = dentry->d_parent->d_fsdata;
|
struct ovl_entry *poe = dentry->d_parent->d_fsdata;
|
||||||
struct path *stack = NULL;
|
struct path *stack = NULL;
|
||||||
struct dentry *upperdir, *upperdentry = NULL;
|
struct dentry *upperdir, *upperdentry = NULL;
|
||||||
|
@ -86,6 +88,9 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
if (dentry->d_name.len > ofs->namelen)
|
||||||
|
return ERR_PTR(-ENAMETOOLONG);
|
||||||
|
|
||||||
old_cred = ovl_override_creds(dentry->d_sb);
|
old_cred = ovl_override_creds(dentry->d_sb);
|
||||||
upperdir = ovl_upperdentry_dereference(poe);
|
upperdir = ovl_upperdentry_dereference(poe);
|
||||||
if (upperdir) {
|
if (upperdir) {
|
||||||
|
@ -127,14 +132,9 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
|
||||||
|
|
||||||
this = ovl_lookup_real(lowerpath.dentry, &dentry->d_name);
|
this = ovl_lookup_real(lowerpath.dentry, &dentry->d_name);
|
||||||
err = PTR_ERR(this);
|
err = PTR_ERR(this);
|
||||||
if (IS_ERR(this)) {
|
if (IS_ERR(this))
|
||||||
/*
|
|
||||||
* If it's positive, then treat ENAMETOOLONG as ENOENT.
|
|
||||||
*/
|
|
||||||
if (err == -ENAMETOOLONG && (upperdentry || ctr))
|
|
||||||
continue;
|
|
||||||
goto out_put;
|
goto out_put;
|
||||||
}
|
|
||||||
if (!this)
|
if (!this)
|
||||||
continue;
|
continue;
|
||||||
if (ovl_is_whiteout(this)) {
|
if (ovl_is_whiteout(this)) {
|
||||||
|
|
|
@ -21,7 +21,7 @@ struct ovl_fs {
|
||||||
unsigned numlower;
|
unsigned numlower;
|
||||||
struct vfsmount **lower_mnt;
|
struct vfsmount **lower_mnt;
|
||||||
struct dentry *workdir;
|
struct dentry *workdir;
|
||||||
long lower_namelen;
|
long namelen;
|
||||||
/* pathnames of lower and upper dirs, for show_options */
|
/* pathnames of lower and upper dirs, for show_options */
|
||||||
struct ovl_config config;
|
struct ovl_config config;
|
||||||
/* creds of process who forced instantiation of super block */
|
/* creds of process who forced instantiation of super block */
|
||||||
|
|
|
@ -174,7 +174,7 @@ static int ovl_statfs(struct dentry *dentry, struct kstatfs *buf)
|
||||||
|
|
||||||
err = vfs_statfs(&path, buf);
|
err = vfs_statfs(&path, buf);
|
||||||
if (!err) {
|
if (!err) {
|
||||||
buf->f_namelen = max(buf->f_namelen, ofs->lower_namelen);
|
buf->f_namelen = ofs->namelen;
|
||||||
buf->f_type = OVERLAYFS_SUPER_MAGIC;
|
buf->f_type = OVERLAYFS_SUPER_MAGIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -461,22 +461,33 @@ static int ovl_mount_dir(const char *name, struct path *path)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ovl_lower_dir(const char *name, struct path *path, long *namelen,
|
static int ovl_check_namelen(struct path *path, struct ovl_fs *ofs,
|
||||||
int *stack_depth, bool *remote)
|
const char *name)
|
||||||
|
{
|
||||||
|
struct kstatfs statfs;
|
||||||
|
int err = vfs_statfs(path, &statfs);
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
pr_err("overlayfs: statfs failed on '%s'\n", name);
|
||||||
|
else
|
||||||
|
ofs->namelen = max(ofs->namelen, statfs.f_namelen);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ovl_lower_dir(const char *name, struct path *path,
|
||||||
|
struct ovl_fs *ofs, int *stack_depth, bool *remote)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
struct kstatfs statfs;
|
|
||||||
|
|
||||||
err = ovl_mount_dir_noesc(name, path);
|
err = ovl_mount_dir_noesc(name, path);
|
||||||
if (err)
|
if (err)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
err = vfs_statfs(path, &statfs);
|
err = ovl_check_namelen(path, ofs, name);
|
||||||
if (err) {
|
if (err)
|
||||||
pr_err("overlayfs: statfs failed on '%s'\n", name);
|
|
||||||
goto out_put;
|
goto out_put;
|
||||||
}
|
|
||||||
*namelen = max(*namelen, statfs.f_namelen);
|
|
||||||
*stack_depth = max(*stack_depth, path->mnt->mnt_sb->s_stack_depth);
|
*stack_depth = max(*stack_depth, path->mnt->mnt_sb->s_stack_depth);
|
||||||
|
|
||||||
if (ovl_dentry_remote(path->dentry))
|
if (ovl_dentry_remote(path->dentry))
|
||||||
|
@ -708,6 +719,10 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
|
||||||
goto out_put_upperpath;
|
goto out_put_upperpath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = ovl_check_namelen(&upperpath, ufs, ufs->config.upperdir);
|
||||||
|
if (err)
|
||||||
|
goto out_put_upperpath;
|
||||||
|
|
||||||
err = ovl_mount_dir(ufs->config.workdir, &workpath);
|
err = ovl_mount_dir(ufs->config.workdir, &workpath);
|
||||||
if (err)
|
if (err)
|
||||||
goto out_put_upperpath;
|
goto out_put_upperpath;
|
||||||
|
@ -745,9 +760,8 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
|
||||||
|
|
||||||
lower = lowertmp;
|
lower = lowertmp;
|
||||||
for (numlower = 0; numlower < stacklen; numlower++) {
|
for (numlower = 0; numlower < stacklen; numlower++) {
|
||||||
err = ovl_lower_dir(lower, &stack[numlower],
|
err = ovl_lower_dir(lower, &stack[numlower], ufs,
|
||||||
&ufs->lower_namelen, &sb->s_stack_depth,
|
&sb->s_stack_depth, &remote);
|
||||||
&remote);
|
|
||||||
if (err)
|
if (err)
|
||||||
goto out_put_lowerpath;
|
goto out_put_lowerpath;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue