mirror of
https://github.com/torvalds/linux.git
synced 2026-10-24 16:55:02 +02:00
generic_ci_d_hash() and generic_ci_d_compare() read sb->s_encoding and
dereference the unicode map while a pathwalk in rcu mode holds nothing
but rcu_read_lock(). The filesystems that use them, ext4, f2fs and
tmpfs, drop the map with utf8_unload() from ->put_super(), which runs
when the last reference to the mount goes away. A lookup that is still
inside such a filesystem at that point reads a freed map.
With a pathwalk held up in utf8_casefold_hash() while the last reference
to a casefolded tmpfs goes away:
BUG: KASAN: slab-use-after-free in utf8nlookup+0x74c/0x950
Read of size 8 at addr ff110001030fe658 by task walker/98
Call Trace:
<TASK>
utf8nlookup+0x74c/0x950
utf8byte+0x160/0x1560
utf8_casefold_hash+0x167/0x230
generic_ci_d_hash+0xdd/0x1c0
link_path_walk+0x11ad/0x1d30
path_lookupat+0x63/0xb00
filename_lookup+0x1f1/0x5b0
vfs_statx+0xd7/0x3b0
[...]
Allocated by task 94:
__kmalloc_cache_noprof+0x249/0x560
utf8_load+0x4e/0x570
shmem_parse_opt_casefold.isra.0+0x92/0x270
[...]
Freed by task 97:
kfree+0x1db/0x5b0
shmem_put_super+0x72/0x170
generic_shutdown_super+0x14c/0x530
kill_anon_super+0x3a/0x60
deactivate_locked_super+0x9c/0xf0
cleanup_mnt+0x9f/0x130
So far that has been hard to hit. umount(2) waits for a grace period
in namespace_unlock() before it drops the mount, so only a mount whose
last reference goes away elsewhere, like the close of a file or a chdir
out of a lazily unmounted directory, can race a walker. So it is
reachable.
Delay the free until a grace period has passed. The map and the data
table it holds a reference to then outlive any pathwalk that found the
superblock before the mount went away. The reference on the data table
module is dropped from the rcu callback as well. utf8-core is built in
whenever CONFIG_UNICODE is set, so there is no module exit that would
have to wait for the callbacks.
Overlayfs points the s_encoding of an overlay at the map of its first
layer without taking a reference of its own. That stays correct. The
layer is held by the overlay, so its map is dropped only after the
overlay is gone.
Fixes:
|
||
|---|---|---|
| .. | ||
| tests | ||
| .gitignore | ||
| Kconfig | ||
| Makefile | ||
| mkutf8data.c | ||
| README.utf8data | ||
| utf8-core.c | ||
| utf8-norm.c | ||
| utf8data.c_shipped | ||
| utf8n.h | ||
The utf8data.c file in this directory is generated from the Unicode Character Database for version 12.1.0 of the Unicode standard. The full set of files can be found here: http://www.unicode.org/Public/12.1.0/ucd/ Individual source links: https://www.unicode.org/Public/12.1.0/ucd/CaseFolding.txt https://www.unicode.org/Public/12.1.0/ucd/DerivedAge.txt https://www.unicode.org/Public/12.1.0/ucd/extracted/DerivedCombiningClass.txt https://www.unicode.org/Public/12.1.0/ucd/DerivedCoreProperties.txt https://www.unicode.org/Public/12.1.0/ucd/NormalizationCorrections.txt https://www.unicode.org/Public/12.1.0/ucd/NormalizationTest.txt https://www.unicode.org/Public/12.1.0/ucd/UnicodeData.txt md5sums (verify by running "md5sum -c README.utf8data"): 900e76da1d822a160fd6b8c0b1d70094 CaseFolding.txt 131256380bff4fea8ad4a851616f2f10 DerivedAge.txt e731a4089b30002144e107e3d6f8d1fa DerivedCombiningClass.txt a47c9fbd7ff92a9b261ba9831e68778a DerivedCoreProperties.txt fcab6dad15e440879d92f315978f93d3 NormalizationCorrections.txt f9ff1c55a60decf436100f791b44aa98 NormalizationTest.txt 755f6af699f8c8d2d958da411f78f6c6 UnicodeData.txt sha1sums (verify by running "sha1sum -c README.utf8data"): dc9245f6803c4ac99555c361f5052e0b13eb779b CaseFolding.txt 3281104f237184cdb5d869e86eb8573678ada7da DerivedAge.txt 2f5f995ccb96e0fa84b15151b35d5e2681535175 DerivedCombiningClass.txt 5b8698a3fcd5018e1987f296b02e2c17e696415e DerivedCoreProperties.txt cd83935fbc012345d8792d2c704f69497e753835 NormalizationCorrections.txt ea419aae505b337b0d99a83fa83fe58ddff7c19f NormalizationTest.txt dc973c0fc93d6f09d9ab9f70d1c9f89c447f0526 UnicodeData.txt To update to the newer version of the Unicode standard, the latest released version of the UCD can be found here: http://www.unicode.org/Public/UCD/latest/ Then, build under fs/unicode/ with REGENERATE_UTF8DATA=1: make REGENERATE_UTF8DATA=1 fs/unicode/ After sanity checking the newly generated utf8data.c file (the version generated from the 12.1.0 UCD should be 4,109 lines long, and have a total size of 324k) and/or comparing it with the older version of utf8data.c_shipped, rename it to utf8data.c_shipped. If you are a kernel developer updating to a newer version of the Unicode Character Database, please update this README.utf8data file with the version of the UCD that was used, the md5sum and sha1sums of the *.txt files, before checking in the new versions of the utf8data.c and README.utf8data files.