Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+8 −8
Original line number Diff line number Diff line
@@ -20,7 +20,8 @@ static struct dentry *ovl_lookup_real(struct dentry *dir,

	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);
@@ -74,6 +75,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *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;
@@ -86,6 +88,9 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
	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) {
@@ -127,14 +132,9 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,

		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)) {
+1 −1
Original line number Diff line number Diff line
@@ -21,7 +21,7 @@ struct ovl_fs {
	unsigned numlower;
	struct vfsmount **lower_mnt;
	struct dentry *workdir;
	long lower_namelen;
	long namelen;
	/* pathnames of lower and upper dirs, for show_options */
	struct ovl_config config;
	/* creds of process who forced instantiation of super block */
+26 −12
Original line number Diff line number Diff line
@@ -174,7 +174,7 @@ static int ovl_statfs(struct dentry *dentry, struct kstatfs *buf)

	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;
	}

@@ -461,22 +461,33 @@ static int ovl_mount_dir(const char *name, struct path *path)
	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))
@@ -708,6 +719,10 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
			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;
@@ -745,9 +760,8 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)

	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;