Commit 6b2d5fe4 authored by Miklos Szeredi's avatar Miklos Szeredi

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: default avatarMiklos Szeredi <mszeredi@redhat.com>
parent bbb1e54d
...@@ -20,7 +20,8 @@ static struct dentry *ovl_lookup_real(struct dentry *dir, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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 { ...@@ -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) ...@@ -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) ...@@ -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)
{ {
int err;
struct kstatfs statfs; 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;
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) ...@@ -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) ...@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment