dentry = lookup_one_len_unlocked(name->name, dir, name->len);
if (IS_ERR(dentry)) {
- if (PTR_ERR(dentry) == -ENOENT)
+ if (PTR_ERR(dentry) == -ENOENT ||
+ PTR_ERR(dentry) == -ENAMETOOLONG)
dentry = NULL;
} else if (!dentry->d_inode) {
dput(dentry);
{
struct ovl_entry *oe;
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 path *stack = NULL;
struct dentry *upperdir, *upperdentry = NULL;
unsigned int i;
int err;
+ if (dentry->d_name.len > ofs->namelen)
+ return ERR_PTR(-ENAMETOOLONG);
+
old_cred = ovl_override_creds(dentry->d_sb);
upperdir = ovl_upperdentry_dereference(poe);
if (upperdir) {
this = ovl_lookup_real(lowerpath.dentry, &dentry->d_name);
err = PTR_ERR(this);
- if (IS_ERR(this)) {
- /*
- * If it's positive, then treat ENAMETOOLONG as ENOENT.
- */
- if (err == -ENAMETOOLONG && (upperdentry || ctr))
- continue;
+ if (IS_ERR(this))
goto out_put;
- }
+
if (!this)
continue;
if (ovl_is_whiteout(this)) {
err = vfs_statfs(&path, buf);
if (!err) {
- buf->f_namelen = max(buf->f_namelen, ofs->lower_namelen);
+ buf->f_namelen = ofs->namelen;
buf->f_type = OVERLAYFS_SUPER_MAGIC;
}
return err;
}
-static int ovl_lower_dir(const char *name, struct path *path, long *namelen,
- int *stack_depth, bool *remote)
+static int ovl_check_namelen(struct path *path, struct ovl_fs *ofs,
+ const char *name)
{
- int err;
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);
if (err)
goto out;
- err = vfs_statfs(path, &statfs);
- if (err) {
- pr_err("overlayfs: statfs failed on '%s'\n", name);
+ err = ovl_check_namelen(path, ofs, name);
+ if (err)
goto out_put;
- }
- *namelen = max(*namelen, statfs.f_namelen);
+
*stack_depth = max(*stack_depth, path->mnt->mnt_sb->s_stack_depth);
if (ovl_dentry_remote(path->dentry))
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);
if (err)
goto out_put_upperpath;
lower = lowertmp;
for (numlower = 0; numlower < stacklen; numlower++) {
- err = ovl_lower_dir(lower, &stack[numlower],
- &ufs->lower_namelen, &sb->s_stack_depth,
- &remote);
+ err = ovl_lower_dir(lower, &stack[numlower], ufs,
+ &sb->s_stack_depth, &remote);
if (err)
goto out_put_lowerpath;