mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
ovl: check the casefold flag of directories only
On an overlay over casefolded (case-insensitive) directories, every
lookup of a file that is not a directory fails with EREMOTE, and the
first file create triggers a kernel warning. No privilege is needed: an
unprivileged user can cause both in a user namespace, with the layers on
a tmpfs that they have mounted with the casefold option.
Some filesystems support casefolding, which is case-insensitive name
lookup. It is enabled per directory, and the inode of a casefolded
directory has the S_CASEFOLD flag.
overlayfs accepts layers on a filesystem that supports casefolding as
long as casefolding is enabled on every directory of the layers, or on
none. The mount records which of the two applies in ofs->casefold.
ovl_lookup_single() compares the S_CASEFOLD flag of each file that it
finds against ofs->casefold and returns -EREMOTE on a mismatch.
Filesystems only set S_CASEFOLD on directories, so with casefolded
layers a regular file, a symlink or a special file never matches and its
lookup fails.
ovl_get_inode() does the same comparison in a WARN_ON_ONCE() for each
new overlay inode. A failed lookup never gets that far, so it is the
first file create that trips the warning.
Reproduced on an overlay over casefolded tmpfs or ext4 directories, with
stat() of a regular file, a symlink and a FIFO, and with a file create:
each stat() failed with EREMOTE. For an unprivileged user in a user
namespace, on tmpfs, stat() of a regular file failed in the same way,
and the file create triggered the warning.
Fix this by limiting both checks to directories.
Fixes: 16754d61dc ("ovl: Support mounting case-insensitive enabled layers")
Cc: stable@vger.kernel.org
Signed-off-by: Chris Mason <mason@kernel.org>
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
This commit is contained in:
parent
a65eb18081
commit
1d27da7de3
|
|
@ -1287,7 +1287,7 @@ struct inode *ovl_get_inode(struct super_block *sb,
|
|||
}
|
||||
ovl_fill_inode(inode, realinode->i_mode, realinode->i_rdev);
|
||||
ovl_inode_init(inode, oip, ino, fsid);
|
||||
WARN_ON_ONCE(!!IS_CASEFOLDED(inode) != ofs->casefold);
|
||||
WARN_ON_ONCE(is_dir && !!IS_CASEFOLDED(inode) != ofs->casefold);
|
||||
|
||||
if (upperdentry && ovl_is_impuredir(sb, upperdentry))
|
||||
ovl_set_flag(OVL_IMPURE, inode);
|
||||
|
|
|
|||
|
|
@ -266,7 +266,8 @@ static int ovl_lookup_single(struct dentry *base, struct ovl_lookup_data *d,
|
|||
goto out_err;
|
||||
}
|
||||
|
||||
if (ofs->casefold != ovl_dentry_casefolded(this)) {
|
||||
/* Filesystems set the casefold flag only on directories */
|
||||
if (d_is_dir(this) && ofs->casefold != ovl_dentry_casefolded(this)) {
|
||||
warn = "child wrong casefold";
|
||||
err = -EREMOTE;
|
||||
goto out_warn;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user