diff options
| author | Matthias Goergens <matthias.goergens@gmail.com> | 2026-09-26 12:29:13 +0800 |
|---|---|---|
| committer | Jan Kara <jack@suse.cz> | 2026-10-02 12:54:48 +0200 |
| commit | b8253bcf92d6365b20eea6465f5a93c9fc4aa029 (patch) | |
| tree | c9bfec012fbf93cb027d8fdcbb56874850f1b1ed /tools/perf/scripts/python/stackcollapse.py | |
| parent | 595373206d0c0cfc4e65f233e36d7b3e110b0709 (diff) | |
| download | linux-b8253bcf92d6365b20eea6465f5a93c9fc4aa029.tar.gz linux-b8253bcf92d6365b20eea6465f5a93c9fc4aa029.zip | |
isofs: return long Joliet names whole
get_joliet_filename() writes into a buffer allocated by its caller but
is not told how big that buffer is. It hardcodes PAGE_SIZE as the
output limit for utf16s_to_utf8s() and gives uni16_to_x8() no limit at
all. PAGE_SIZE was never the right bound. Before commit b2eb2e288604
("isofs: Drop support of directory entries straddling blocks") both
callers allocated a page, but only its first 1024 bytes were for the
name, the rest holding a copy of a directory record that straddled a
block. It could not overflow only because a directory record holds at
most 222 bytes of name (255 bytes, 33 of them fixed), which no converter
expands beyond 1024 bytes.
It also keeps the converted length in an unsigned char. 222 bytes of
name are 111 UTF-16 units, and the UTF-8 converter, used for
iocharset=utf8 and when CONFIG_NLS_DEFAULT is "utf8", needs three bytes
for each CJK, Thai or Devanagari character, so such a name can take up
to 333 bytes. Past 255 the length wraps. readdir then reports a short
name that usually ends in the middle of a UTF-8 sequence, and lookup
finds the file only under that name, never under its real one; a name
that wraps to exactly 0 bytes is not listed at all.
Such names are out of spec, since Joliet allows 64 units, but common
tools write them: PowerISO 9.5 and UltraISO 9.76 both keep up to 110
units by default. Windows, for which Joliet was made, returns them
whole, including 111-unit names in records that leave out the padding
byte.
Return them whole here too. Pass the buffer size down and have both
converters respect it. utf16s_to_utf8s() stops before a character that
does not fit, and uni16_to_x8() now hands uni2char() the space that
actually remains and stops on -ENAMETOOLONG, as fs/hfsplus/unicode.c
does. Both callers pass JOLIET_NAME_MAX + 1, room for 111 units at
three bytes each plus the terminator; no character set needs more than
three bytes for a UTF-16 unit, and isofs_dir_record_valid() already
rejects a record whose name_len claims more than the record holds, so no
name is cut. Make the length an int, which is what both converters
return.
These names are longer than NAME_MAX. POSIX lets the limit vary by
filesystem, reported by pathconf(_PC_NAME_MAX), and the VFS limits a
name only by PATH_MAX (verify_dirent_name() in fs/readdir.c).
vfat, exfat, hfsplus and ntfs3 already return names of up to 255 UTF-16
units, 765 bytes of UTF-8, and such names break the same things there:
copying the file to a filesystem with a 255-byte limit, such as ext4 or
tmpfs, fails with ENAMETOOLONG, and cp, tar, rsync and Python's shutil
report that file and carry on with the rest, so the copy is incomplete
but says so. glibc's readdir() returns the names, but the deprecated
readdir_r() skips them and fails with ENAMETOOLONG, and an inotify
reader with the buffer size inotify(7) suggests gets EINVAL. In the
kernel, fanotify reports events on such a file without its name and
warns once in fanotify_info_copy_name(), and a directory with such a
name cannot be reconnected from a file handle, because the generic
get_name() in fs/exportfs, which isofs uses, skips names longer than
NAME_MAX. Cutting at NAME_MAX would avoid these, but would list names
that Windows does not show and that can coincide within a directory.
Every name of at most 255 bytes is returned exactly as before.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Matthias Goergens <matthias.goergens@gmail.com>
Link: https://patch.msgid.link/20260926042916.3277409-2-matthias.goergens@gmail.com
Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'tools/perf/scripts/python/stackcollapse.py')
0 files changed, 0 insertions, 0 deletions
