Skip to content

mount -o remount always appends options to /etc/mtab even if they already exist #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
martinpitt opened this issue Nov 30, 2011 · 2 comments

Comments

@martinpitt
Copy link

If you use mount -o remount,, these extra options always get appended to the existing ones in /etc/mtab. This has the effect that on suspend/resume, mounted USB drives keep growing options like

/dev/sdc1 on /media/LaCie type ext4 (rw,nosuid,nodev,commit=600,commit=600,commit=0,commit=600,commit=0,commit=600,commit=0,commit=0,commit=0,commit=600,commit=0,commit=0,commit=600,commit=0,commit=600,commit=600,commit=0,uhelper=udisks)

because of a pm-utils hook (/usr/lib/pm-utils/power.d/journal-commit).

Reproducer:

$ sudo modprobe scsi_debug

ATTENTION! MAKE TRIPLE-SURE ABOUT THE DEVICE NAME HERE! it's the fake one from scsi_debug

$ sudo mkfs.ext4 /dev/sdb
$ sudo mount /dev/sdb /mnt
$ grep sdb /etc/mtab
/dev/sdb /mnt ext4 rw 0 0

$ sudo mount -o remount,commit=600 /dev/sdb
$ grep sdb /etc/mtab
/dev/sdb /mnt ext4 rw,commit=600 0 0

$ sudo mount -o remount,commit=600 /dev/sdb
$ grep sdb /etc/mtab
/dev/sdb /mnt ext4 rw,commit=600,commit=600 0 0

@ronin13
Copy link
Contributor

ronin13 commented Feb 26, 2012

Not the same reason, but remount should only pass new options (ie. after remount option), otherwise non-clean workarounds like http://lxr.linux.no/#linux+v3.2.7/fs/xfs/xfs_super.c#L1141 will need to be used; which also has the side-effect that in case of invalid remount mount(2) won't return EINVAL.

@karelzak
Copy link
Collaborator

karelzak commented Jun 6, 2012

This is standard and documented behaviour (see man mount, remount description).

@karelzak karelzak closed this as completed Jun 6, 2012
karelzak added a commit that referenced this issue Sep 9, 2013
 #0 recount_geometry at libfdisk/src/alignment.c:143
 #1 fdisk_discover_geometry at libfdisk/src/alignment.c:205
 #2 fdisk_context_assign_device at libfdisk/src/context.c:173
 #3 print_partition_table_from_option at fdisks/fdisk.c:924

References: https://bugzilla.redhat.com/show_bug.cgi?id=1005566
Signed-off-by: Karel Zak <kzak@redhat.com>
@karelzak karelzak mentioned this issue Sep 15, 2014
karelzak pushed a commit that referenced this issue Nov 18, 2014
The tests failed with following message in config.log

ERROR: LeakSanitizer: detected memory leaks

Direct leak of 2 byte(s) in 1 object(s) allocated from:
    #0 0x49a40e in realloc (/home/src/util-linux/conftest+0x49a40e)
    #1 0x7fbe48633e69 in __GI__IO_vfscanf (/usr/lib/libc.so.6+0x56e69)
    #2 0x7fbe48649786 in _IO_vsscanf (/usr/lib/libc.so.6+0x6c786)

which knocked out libmount from build, and commands depending on it.

The reason this change makes sense is that AddressSanitizer seems like a
good addition to set of tools that util-linux package can use, when and
if needed.

Reference: https://code.google.com/p/address-sanitizer/wiki/AddressSanitizer
Reviewed-by: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
karelzak pushed a commit that referenced this issue Nov 18, 2014
==10918==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fffd795b680 at pc 0x0000004447c6 bp 0x7fffd795b3e0 sp 0x7fffd795ab78
WRITE of size 129 at 0x7fffd795b680 thread T0
    #0 0x4447c5 in scanf_common(void*, int, bool, char const*, __va_list_tag*) (/home/src/util-linux/.libs/lt-mount+0x4447c5)
    #1 0x445892 in sscanf (/home/src/util-linux/.libs/lt-mount+0x445892)
    #2 0x7fe78709a3d3 in get_filesystems /home/src/util-linux/libmount/src/utils.c:581:7
    #3 0x7fe78709a1ba in mnt_get_filesystems /home/src/util-linux/libmount/src/utils.c:622:7
    #4 0x7fe7870aa78f in do_mount_by_pattern /home/src/util-linux/libmount/src/context_mount.c:833:7
    #5 0x7fe7870a9534 in mnt_context_do_mount /home/src/util-linux/libmount/src/context_mount.c:951:9
    #6 0x7fe7870aab2b in mnt_context_mount /home/src/util-linux/libmount/src/context_mount.c:1051:8
    #7 0x4ba9f5 in main /home/src/util-linux/sys-utils/mount.c:1107:7
    #8 0x7fe785caa03f in __libc_start_main (/usr/lib/libc.so.6+0x2003f)
    #9 0x4b9f9c in _start (/home/src/util-linux/.libs/lt-mount+0x4b9f9c)

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
Signed-off-by: Karel Zak <kzak@redhat.com>
karelzak pushed a commit that referenced this issue Nov 18, 2014
==18922==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 8 byte(s) in 1 object(s) allocated from:
    #0 0x49d12b in __interceptor_malloc (/home/src/util-linux/.libs/lt-mkswap+0x49d12b)
    #1 0x7faf2a5069c9 in __GI___strdup (/usr/lib/libc.so.6+0x819c9)
    #2 0xffff96e7e33 (<unknown module>)

SUMMARY: AddressSanitizer: 8 byte(s) leaked in 1 allocation(s).

And another one that valgrind found.

==6316== 8 bytes in 1 blocks are definitely lost in loss record 1 of 1
==6316==    at 0x4C29F90: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6316==    by 0x5E3F9C9: strdup (in /usr/lib/libc-2.20.so)
==6316==    by 0x43A25F: size_to_human_string (strutils.c:495)
==6316==    by 0x42B35C: main (mkswap.c:488)

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
karelzak pushed a commit that referenced this issue Dec 19, 2014
==3218==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fffa577e2b0 at pc 0x4501f9 bp 0x7fffa577e130 sp 0x7fffa577e108
WRITE of size 112 at 0x7fffa577e2b0 thread T0
    #0 0x4501f8 in shmctl /home/users/aadgrand/LLVM/releases/ubuntu/final/llvm.src/projects/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc:2502
    #1 0x48bd13 in ipc_shm_get_info /home/travis/build/kerolasa/lelux-utiliteetit/sys-utils/ipcutils.c:157
    #2 0x488884 in do_shm /home/travis/build/kerolasa/lelux-utiliteetit/sys-utils/ipcs.c:279
    #3 0x4844a8 in main /home/travis/build/kerolasa/lelux-utiliteetit/sys-utils/ipcs.c:175
    #4 0x2afb3f8c176c (/lib/x86_64-linux-gnu/libc.so.6+0x2176c)
    #5 0x48408c in _start (/home/travis/build/kerolasa/lelux-utiliteetit/ipcs+0x48408c)

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
karelzak pushed a commit that referenced this issue Aug 12, 2015
text-utils/colcrt.c:205:10: runtime error: index -1 out of bounds for type 'wchar_t [133]'
SUMMARY: AddressSanitizer: undefined-behavior text-utils/colcrt.c:205
=================================================================
==2357==ERROR: AddressSanitizer: global-buffer-overflow on address 0x0000013811b0 at pc 0x0000004e2514 bp 0x7ffdf6ba4450 sp 0x7ffdf6ba4448
READ of size 4 at 0x0000013811b0 thread T0
    #0 0x4e2513 in colcrt /home/src/util-linux/text-utils/colcrt.c:213:8
    #1 0x4e17d4 in main /home/src/util-linux/text-utils/colcrt.c:139:3
    #2 0x7fb77236960f in __libc_start_main (/usr/lib/libc.so.6+0x2060f)
    #3 0x4362c8 in _start (/home/src/util-linux/colcrt+0x4362c8)

Reported-by: Alaa Mubaied <alaamubaied@gmail.com>
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
karelzak pushed a commit that referenced this issue Aug 12, 2015
==2807==ERROR: AddressSanitizer: global-buffer-overflow on address 0x0000013a31f0 at pc 0x0000004e3047 bp 0x7fffcb7df8d0 sp 0x7fffcb7df8c8
READ of size 4 at 0x0000013a31f0 thread T0
    #0 0x4e3046 in move /home/src/util-linux/text-utils/colcrt.c:309:13
    #1 0x4e25b1 in pflush /home/src/util-linux/text-utils/colcrt.c:264:3
    #2 0x4e246d in colcrt /home/src/util-linux/text-utils/colcrt.c:157:4
    #3 0x4e17d4 in main /home/src/util-linux/text-utils/colcrt.c:141:3
    #4 0x7fb0cb2ee60f in __libc_start_main (/usr/lib/libc.so.6+0x2060f)
    #5 0x4362c8 in _start (/home/src/util-linux/colcrt+0x4362c8)

0x0000013a31f0 is located 0 bytes to the right of global variable 'page' defined in 'text-utils/colcrt.c:73:9' (0x1380b40) of size 140976
SUMMARY: AddressSanitizer: global-buffer-overflow /home/src/util-linux/text-utils/colcrt.c:309 move

And another crash:

==4578==ERROR: AddressSanitizer: global-buffer-overflow on address 0x0000013a3d24 at pc 0x0000004e2510 bp 0x7ffc9257b0e0 sp 0x7ffc9257b0d8
READ of size 4 at 0x0000013a3d24 thread T0
    #0 0x4e250f in colcrt /home/src/util-linux/text-utils/colcrt.c:218:8
    #1 0x4e17d4 in main /home/src/util-linux/text-utils/colcrt.c:141:3
    #2 0x7fe0ac94160f in __libc_start_main (/usr/lib/libc.so.6+0x2060f)
    #3 0x4362c8 in _start (/home/src/util-linux/colcrt+0x4362c8)

0x0000013a3d24 is located 8 bytes to the right of global variable 'page' defined in 'text-utils/colcrt.c:73:9' (0x1381240) of size 142044
SUMMARY: AddressSanitizer: global-buffer-overflow /home/src/util-linux/text-utils/colcrt.c:218 colcrt

Reported-by: Alaa Mubaied <alaamubaied@gmail.com>
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
@frinnst frinnst mentioned this issue Nov 7, 2018
evverx referenced this issue in evverx/util-linux Jun 25, 2020
The fuzzer is supposed to cover `mnt_table_parse_stream`, which is
used by systemd to parse /proc/self/mountinfo. The systemd project
has run into memory leaks there at least twice:

systemd/systemd#12252 (comment)
systemd/systemd#8504

so it seems to be a good idea to continuously fuzz that particular
function.

The patch can be tested locally by installing clang and running
./tools/oss-fuzz.sh. Currently the fuzzer is failing with
```
=================================================================
==96638==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 216 byte(s) in 1 object(s) allocated from:
    #0 0x50cd77 in calloc (/home/vagrant/util-linux/out/test_mount_fuzz+0x50cd77)
    #1 0x58716a in mnt_new_fs /home/vagrant/util-linux/libmount/src/fs.c:36:25
    #2 0x54f224 in __table_parse_stream /home/vagrant/util-linux/libmount/src/tab_parse.c:728:9
    #3 0x54eed8 in mnt_table_parse_stream /home/vagrant/util-linux/libmount/src/tab_parse.c:804:8
    #4 0x5448b2 in LLVMFuzzerTestOneInput /home/vagrant/util-linux/libmount/src/fuzz.c:19:16
    util-linux#5 0x44cc88 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/home/vagrant/util-linux/out/test_mount_fuzz+0x44cc88)
    util-linux#6 0x44d8b0 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool*) (/home/vagrant/util-linux/out/test_mount_fuzz+0x44d8b0)
    util-linux#7 0x44e270 in fuzzer::Fuzzer::MutateAndTestOne() (/home/vagrant/util-linux/out/test_mount_fuzz+0x44e270)
    util-linux#8 0x450617 in fuzzer::Fuzzer::Loop(std::vector<fuzzer::SizedFile, fuzzer::fuzzer_allocator<fuzzer::SizedFile> >&) (/home/vagrant/util-linux/out/test_mount_fuzz+0x450617)
    util-linux#9 0x43adbb in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/home/vagrant/util-linux/out/test_mount_fuzz+0x43adbb)
    util-linux#10 0x42ad46 in main (/home/vagrant/util-linux/out/test_mount_fuzz+0x42ad46)
    util-linux#11 0x7fa084f621a2 in __libc_start_main (/lib64/libc.so.6+0x271a2)

SUMMARY: AddressSanitizer: 216 byte(s) leaked in 1 allocation(s).
INFO: to ignore leaks on libFuzzer side use -detect_leaks=0.
```

Once the bug is fixed and the OSS-Fuzz counterpart is merged it should be possible
to turn on CIFuzz to make sure the fuzz target can be built and run for some time
without crashing: https://google.github.io/oss-fuzz/getting-started/continuous-integration/
evverx referenced this issue in evverx/util-linux Jun 25, 2020
The fuzzer is supposed to cover `mnt_table_parse_stream`, which is
used by systemd to parse /proc/self/mountinfo. The systemd project
has run into memory leaks there at least twice:

systemd/systemd#12252 (comment)
systemd/systemd#8504

so it seems to be a good idea to continuously fuzz that particular
function.

The patch can be tested locally by installing clang and running
./tools/oss-fuzz.sh. Currently the fuzzer is failing with
```
=================================================================
==96638==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 216 byte(s) in 1 object(s) allocated from:
    #0 0x50cd77 in calloc (/home/vagrant/util-linux/out/test_mount_fuzz+0x50cd77)
    #1 0x58716a in mnt_new_fs /home/vagrant/util-linux/libmount/src/fs.c:36:25
    #2 0x54f224 in __table_parse_stream /home/vagrant/util-linux/libmount/src/tab_parse.c:728:9
    #3 0x54eed8 in mnt_table_parse_stream /home/vagrant/util-linux/libmount/src/tab_parse.c:804:8
    #4 0x5448b2 in LLVMFuzzerTestOneInput /home/vagrant/util-linux/libmount/src/fuzz.c:19:16
    util-linux#5 0x44cc88 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/home/vagrant/util-linux/out/test_mount_fuzz+0x44cc88)
    util-linux#6 0x44d8b0 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool*) (/home/vagrant/util-linux/out/test_mount_fuzz+0x44d8b0)
    util-linux#7 0x44e270 in fuzzer::Fuzzer::MutateAndTestOne() (/home/vagrant/util-linux/out/test_mount_fuzz+0x44e270)
    util-linux#8 0x450617 in fuzzer::Fuzzer::Loop(std::vector<fuzzer::SizedFile, fuzzer::fuzzer_allocator<fuzzer::SizedFile> >&) (/home/vagrant/util-linux/out/test_mount_fuzz+0x450617)
    util-linux#9 0x43adbb in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/home/vagrant/util-linux/out/test_mount_fuzz+0x43adbb)
    util-linux#10 0x42ad46 in main (/home/vagrant/util-linux/out/test_mount_fuzz+0x42ad46)
    util-linux#11 0x7fa084f621a2 in __libc_start_main (/lib64/libc.so.6+0x271a2)

SUMMARY: AddressSanitizer: 216 byte(s) leaked in 1 allocation(s).
INFO: to ignore leaks on libFuzzer side use -detect_leaks=0.
```

Once the bug is fixed and the OSS-Fuzz counterpart is merged it should be possible
to turn on CIFuzz to make sure the fuzz target can be built and run for some time
without crashing: https://google.github.io/oss-fuzz/getting-started/continuous-integration/
evverx referenced this issue in evverx/util-linux Jun 27, 2020
The fuzzer is supposed to cover `mnt_table_parse_stream`, which is
used by systemd to parse /proc/self/mountinfo. The systemd project
has run into memory leaks there at least twice:

systemd/systemd#12252 (comment)
systemd/systemd#8504

so it seems to be a good idea to continuously fuzz that particular
function.

The patch can be tested locally by installing clang and running
./tools/oss-fuzz.sh. Currently the fuzzer is failing with
```
=================================================================
==96638==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 216 byte(s) in 1 object(s) allocated from:
    #0 0x50cd77 in calloc (/home/vagrant/util-linux/out/test_mount_fuzz+0x50cd77)
    #1 0x58716a in mnt_new_fs /home/vagrant/util-linux/libmount/src/fs.c:36:25
    #2 0x54f224 in __table_parse_stream /home/vagrant/util-linux/libmount/src/tab_parse.c:728:9
    #3 0x54eed8 in mnt_table_parse_stream /home/vagrant/util-linux/libmount/src/tab_parse.c:804:8
    #4 0x5448b2 in LLVMFuzzerTestOneInput /home/vagrant/util-linux/libmount/src/fuzz.c:19:16
    util-linux#5 0x44cc88 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/home/vagrant/util-linux/out/test_mount_fuzz+0x44cc88)
    util-linux#6 0x44d8b0 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool*) (/home/vagrant/util-linux/out/test_mount_fuzz+0x44d8b0)
    util-linux#7 0x44e270 in fuzzer::Fuzzer::MutateAndTestOne() (/home/vagrant/util-linux/out/test_mount_fuzz+0x44e270)
    util-linux#8 0x450617 in fuzzer::Fuzzer::Loop(std::vector<fuzzer::SizedFile, fuzzer::fuzzer_allocator<fuzzer::SizedFile> >&) (/home/vagrant/util-linux/out/test_mount_fuzz+0x450617)
    util-linux#9 0x43adbb in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/home/vagrant/util-linux/out/test_mount_fuzz+0x43adbb)
    util-linux#10 0x42ad46 in main (/home/vagrant/util-linux/out/test_mount_fuzz+0x42ad46)
    util-linux#11 0x7fa084f621a2 in __libc_start_main (/lib64/libc.so.6+0x271a2)

SUMMARY: AddressSanitizer: 216 byte(s) leaked in 1 allocation(s).
INFO: to ignore leaks on libFuzzer side use -detect_leaks=0.
```

Once the bug is fixed and the OSS-Fuzz counterpart is merged it should be possible
to turn on CIFuzz to make sure the fuzz target can be built and run for some time
without crashing: https://google.github.io/oss-fuzz/getting-started/continuous-integration/
evverx referenced this issue in evverx/util-linux Jul 1, 2020
Backtraces like
```
misc-utils/cal.c:295:4: runtime error: signed integer overflow: 2147483647 + 5 cannot be represented in type 'int'
==1405==WARNING: invalid path to external symbolizer!
==1405==WARNING: Failed to use and restart external symbolizer!
    #0 0x4c4c09  (/home/travis/build/karelzak/util-linux/cal+0x4c4c09)
    #1 0x7f4363046b96  (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
    #2 0x41bab9  (/home/travis/build/karelzak/util-linux/cal+0x41bab9)
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior misc-utils/cal.c:295:4 in
```
aren't very helpful

It's follow-up to util-linux#1075
evverx referenced this issue in evverx/util-linux Jul 1, 2020
Backtraces like
```
misc-utils/cal.c:295:4: runtime error: signed integer overflow: 2147483647 + 5 cannot be represented in type 'int'
==1405==WARNING: invalid path to external symbolizer!
==1405==WARNING: Failed to use and restart external symbolizer!
    #0 0x4c4c09  (/home/travis/build/karelzak/util-linux/cal+0x4c4c09)
    #1 0x7f4363046b96  (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
    #2 0x41bab9  (/home/travis/build/karelzak/util-linux/cal+0x41bab9)
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior misc-utils/cal.c:295:4 in
```
aren't very helpful

It's follow-up to util-linux#1075
evverx referenced this issue in evverx/util-linux Jul 1, 2020
Backtraces like
```
misc-utils/cal.c:295:4: runtime error: signed integer overflow: 2147483647 + 5 cannot be represented in type 'int'
==1405==WARNING: invalid path to external symbolizer!
==1405==WARNING: Failed to use and restart external symbolizer!
    #0 0x4c4c09  (/home/travis/build/karelzak/util-linux/cal+0x4c4c09)
    #1 0x7f4363046b96  (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
    #2 0x41bab9  (/home/travis/build/karelzak/util-linux/cal+0x41bab9)
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior misc-utils/cal.c:295:4 in
```
aren't very helpful

It's follow-up to util-linux#1075
karelzak pushed a commit that referenced this issue Jul 3, 2020
Backtraces like
```
misc-utils/cal.c:295:4: runtime error: signed integer overflow: 2147483647 + 5 cannot be represented in type 'int'
==1405==WARNING: invalid path to external symbolizer!
==1405==WARNING: Failed to use and restart external symbolizer!
    #0 0x4c4c09  (/home/travis/build/karelzak/util-linux/cal+0x4c4c09)
    #1 0x7f4363046b96  (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
    #2 0x41bab9  (/home/travis/build/karelzak/util-linux/cal+0x41bab9)
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior misc-utils/cal.c:295:4 in
```
aren't very helpful

It's follow-up to #1075
karelzak pushed a commit that referenced this issue Aug 7, 2020
Looks like those specifiers haven't been used since 6c9ab25
(where sscanf was removed) was merged. This should help to get
util-linux to compile with MSan. Currently it's failing with
```
...
configure: error: libmount selected, but required scanf string alloc modifier not available
...
configure:20240: ./conftest
==116617==WARNING: MemorySanitizer: use-of-uninitialized-value
    #0 0x496fd6 in main /home/vagrant/util-linux/conftest.c:171:6
    #1 0x7f5eb85ea1a2 in __libc_start_main (/lib64/libc.so.6+0x271a2)
    #2 0x41c2cd in _start (/home/vagrant/util-linux/conftest+0x41c2cd)

SUMMARY: MemorySanitizer: use-of-uninitialized-value /home/vagrant/util-linux/conftest.c:171:6 in main
Exiting
configure:20240: $? = 77
...
configure:20265: $? = 0
configure:20265: ./conftest
MemorySanitizer: bad pointer 0x000000496e60
==116627==MemorySanitizer CHECK failed: /builddir/build/BUILD/compiler-rt-9.0.1.src/lib/msan/../sanitizer_common/sanitizer_allocator_secondary.h:177 "((IsAligned(reinterpret_cast<uptr>(p), page_size_))) != (0)" (0x0, 0x0)
    #0 0x41d1d8 in MsanCheckFailed(char const*, int, char const*, unsigned long long, unsigned long long) (/home/vagrant/util-linux/conftest+0x41d1d8)
    #1 0x484e1e in __sanitizer::CheckFailed(char const*, int, char const*, unsigned long long, unsigned long long) (/home/vagrant/util-linux/conftest+0x484e1e)
    #2 0x42066c in __msan::MsanDeallocate(__sanitizer::StackTrace*, void*) (/home/vagrant/util-linux/conftest+0x42066c)
    #3 0x424bc9 in free (/home/vagrant/util-linux/conftest+0x424bc9)
    #4 0x496fae in main /home/vagrant/util-linux/conftest.c:173:2
    #5 0x7f2245f311a2 in __libc_start_main (/lib64/libc.so.6+0x271a2)
    #6 0x41c2cd in _start (/home/vagrant/util-linux/conftest+0x41c2cd)

configure:20265: $? = 77
configure: program exited with status 77
...
| }
configure:22568: result: no
configure:22926: error: libmount selected, but required scanf string alloc modifier not available
```

Signed-off-by: Evgeny Vereshchagin <evvers@ya.ru>
karelzak pushed a commit that referenced this issue Aug 10, 2020
The fuzzer is supposed to cover `mnt_table_parse_stream`, which is
used by systemd to parse /proc/self/mountinfo. The systemd project
has run into memory leaks there at least twice:

systemd/systemd#12252 (comment)
systemd/systemd#8504

so it seems to be a good idea to continuously fuzz that particular
function.

The patch can be tested locally by installing clang and running
./tools/oss-fuzz.sh. Currently the fuzzer is failing with
```
=================================================================
==96638==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 216 byte(s) in 1 object(s) allocated from:
    #0 0x50cd77 in calloc (/home/vagrant/util-linux/out/test_mount_fuzz+0x50cd77)
    #1 0x58716a in mnt_new_fs /home/vagrant/util-linux/libmount/src/fs.c:36:25
    #2 0x54f224 in __table_parse_stream /home/vagrant/util-linux/libmount/src/tab_parse.c:728:9
    #3 0x54eed8 in mnt_table_parse_stream /home/vagrant/util-linux/libmount/src/tab_parse.c:804:8
    #4 0x5448b2 in LLVMFuzzerTestOneInput /home/vagrant/util-linux/libmount/src/fuzz.c:19:16
    #5 0x44cc88 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/home/vagrant/util-linux/out/test_mount_fuzz+0x44cc88)
    #6 0x44d8b0 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool*) (/home/vagrant/util-linux/out/test_mount_fuzz+0x44d8b0)
    #7 0x44e270 in fuzzer::Fuzzer::MutateAndTestOne() (/home/vagrant/util-linux/out/test_mount_fuzz+0x44e270)
    #8 0x450617 in fuzzer::Fuzzer::Loop(std::vector<fuzzer::SizedFile, fuzzer::fuzzer_allocator<fuzzer::SizedFile> >&) (/home/vagrant/util-linux/out/test_mount_fuzz+0x450617)
    #9 0x43adbb in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/home/vagrant/util-linux/out/test_mount_fuzz+0x43adbb)
    #10 0x42ad46 in main (/home/vagrant/util-linux/out/test_mount_fuzz+0x42ad46)
    #11 0x7fa084f621a2 in __libc_start_main (/lib64/libc.so.6+0x271a2)

SUMMARY: AddressSanitizer: 216 byte(s) leaked in 1 allocation(s).
INFO: to ignore leaks on libFuzzer side use -detect_leaks=0.
```

Once the bug is fixed and the OSS-Fuzz counterpart is merged it should be possible
to turn on CIFuzz to make sure the fuzz target can be built and run for some time
without crashing: https://google.github.io/oss-fuzz/getting-started/continuous-integration/

Signed-off-by: Evgeny Vereshchagin <evvers@ya.ru>
karelzak pushed a commit that referenced this issue Mar 29, 2021
naota added a commit to naota/util-linux that referenced this issue Apr 13, 2021
This commit adds zone-aware magics and probing functions for zoned btrfs.

Superblock (and its copies) is the only data structure in btrfs with a
fixed location on a device. Since we cannot overwrite in a sequential write
required zone, we cannot place superblock in the zone.

Thus, zoned btrfs use superblock log writing to update superblock on
sequential write required zones. It uses two zones as a circular buffer to
write updated superblocks. Once the first zone is filled up, start writing
into the second buffer. When both zones are filled up and before start
writing to the first zone again, it reset the first zone.

We can determine the position of the latest superblock by reading write
pointer information from a device. One corner case is when both zones are
full. For this situation, we read out the last superblock of each zone and
compare them to determine which zone is older.

The magics can detect a superblock magic ("_BHRfs_M") at the beginning of
zone #0 or zone util-linux#1 to see if it is zoned btrfs. When both zones are filled
up, zoned btrfs reset the first zone to write a new superblock. If btrfs
crash at the moment, we do not see a superblock at zone #0. Thus, we need
to check not only zone #0 but also zone util-linux#1.

It also supports temporary magic ("!BHRfS_M") in zone #0. The mkfs.btrfs
first writes the temporary superblock to the zone during the mkfs process.
It will survive there until the zones are filled up and reset. So, we also
need to detect this temporary magic.

Finally, this commit extends probe_btrfs() to load the latest superblock
determined by the write pointers.

Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
naota added a commit to naota/util-linux that referenced this issue Apr 14, 2021
This commit adds zone-aware magics and probing functions for zoned btrfs.

Superblock (and its copies) is the only data structure in btrfs with a
fixed location on a device. Since we cannot overwrite in a sequential write
required zone, we cannot place superblock in the zone.

Thus, zoned btrfs use superblock log writing to update superblock on
sequential write required zones. It uses two zones as a circular buffer to
write updated superblocks. Once the first zone is filled up, start writing
into the second buffer. When both zones are filled up and before start
writing to the first zone again, it reset the first zone.

We can determine the position of the latest superblock by reading write
pointer information from a device. One corner case is when both zones are
full. For this situation, we read out the last superblock of each zone and
compare them to determine which zone is older.

The magics can detect a superblock magic ("_BHRfs_M") at the beginning of
zone #0 or zone util-linux#1 to see if it is zoned btrfs. When both zones are filled
up, zoned btrfs reset the first zone to write a new superblock. If btrfs
crash at the moment, we do not see a superblock at zone #0. Thus, we need
to check not only zone #0 but also zone util-linux#1.

It also supports temporary magic ("!BHRfS_M") in zone #0. The mkfs.btrfs
first writes the temporary superblock to the zone during the mkfs process.
It will survive there until the zones are filled up and reset. So, we also
need to detect this temporary magic.

Finally, this commit extends probe_btrfs() to load the latest superblock
determined by the write pointers.

Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
karelzak pushed a commit that referenced this issue Apr 28, 2021
This commit adds zone-aware magics and probing functions for zoned btrfs.

The superblock (and its copies) are the only data structure in btrfs with a
fixed location on a device. Since we cannot do overwrites in a sequential
write required zone, we cannot place the superblock in the zone.

Thus, zoned btrfs uses superblock log writing to update superblocks on
sequential write required zones. It uses two zones as a circular buffer to
write updated superblocks. Once the first zone is filled up, start writing
into the second buffer. When both zones are filled up, and before starting
to write to the first zone again, it reset the first zone.

We can determine the position of the latest superblock by reading the write
pointer information from a device. One corner case is when both zones are
full. For this situation, we read out the last superblock of each zone and
compare them to determine which zone is older.

The magics can detect a superblock magic ("_BHRfs_M") at the beginning of
zone #0 or zone #1 to see if it is zoned btrfs. When both zones are filled
up, zoned btrfs resets the first zone to write a new superblock. If btrfs
crashes at the moment, we do not see a superblock at zone #0. Thus, we need
to check not only zone #0 but also zone #1.

It also supports the temporary magic ("!BHRfS_M") in zone #0. Mkfs.btrfs
first writes the temporary superblock to the zone during the mkfs process.
It will survive there until the zones are filled up and reset. So, we also
need to detect this temporary magic.

Finally, this commit extends probe_btrfs() to load the latest superblock
determined by the write pointers.

Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
karelzak pushed a commit that referenced this issue May 24, 2021
This commit adds zone-aware magics and probing functions for zoned btrfs.

The superblock (and its copies) are the only data structure in btrfs with a
fixed location on a device. Since we cannot do overwrites in a sequential
write required zone, we cannot place the superblock in the zone.

Thus, zoned btrfs uses superblock log writing to update superblocks on
sequential write required zones. It uses two zones as a circular buffer to
write updated superblocks. Once the first zone is filled up, start writing
into the second buffer. When both zones are filled up, and before starting
to write to the first zone again, it reset the first zone.

We can determine the position of the latest superblock by reading the write
pointer information from a device. One corner case is when both zones are
full. For this situation, we read out the last superblock of each zone and
compare them to determine which zone is older.

The magics can detect a superblock magic ("_BHRfs_M") at the beginning of
zone #0 or zone #1 to see if it is zoned btrfs. When both zones are filled
up, zoned btrfs resets the first zone to write a new superblock. If btrfs
crashes at the moment, we do not see a superblock at zone #0. Thus, we need
to check not only zone #0 but also zone #1.

It also supports the temporary magic ("!BHRfS_M") in zone #0. Mkfs.btrfs
first writes the temporary superblock to the zone during the mkfs process.
It will survive there until the zones are filled up and reset. So, we also
need to detect this temporary magic.

Finally, this commit extends probe_btrfs() to load the latest superblock
determined by the write pointers.

Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
bluca added a commit to bluca/util-linux that referenced this issue Feb 22, 2023
Use the appropriate ioctl, if available, to check if a device is locked
when we get an I/O error. Save the information so that we don't have to
repeat the ioctl.

Before:

LIBBLKID_DEBUG=all blkid -p /dev/sdd2
206326: libblkid:     INIT: library debug mask: 0xffff
206326: libblkid:     INIT: library version: 2.38.1 [04-Aug-2022]
Available "LIBBLKID_DEBUG=<name>[,...]|<mask>" debug masks:
   all      [0xffff] : info about all subsystems
   cache    [0x0004] : blkid tags cache
   config   [0x0008] : config file utils
   dev      [0x0010] : device utils
   devname  [0x0020] : /proc/partitions evaluation
   devno    [0x0040] : conversions to device name
   evaluate [0x0080] : tags resolving
   help     [0x0001] : this help
   lowprobe [0x0100] : superblock/raids/partitions probing
   buffer   [0x2000] : low-probing buffers
   probe    [0x0200] : devices verification
   read     [0x0400] : cache parsing
   save     [0x0800] : cache writing
   tag      [0x1000] : tags utils
206326: libblkid: LOWPROBE: allocate a new probe
206326: libblkid: LOWPROBE: zeroize wiper
206326: libblkid: LOWPROBE: ready for low-probing, offset=0, size=234584276992, zonesize=0
206326: libblkid: LOWPROBE: whole-disk: NO, regfile: NO
206326: libblkid: LOWPROBE: start probe
206326: libblkid: LOWPROBE: zeroize wiper
206326: libblkid: LOWPROBE: chain safeprobe superblocks ENABLED
206326: libblkid: LOWPROBE: --> starting probing loop [SUBLKS idx=-1]
206326: libblkid: LOWPROBE: [0] linux_raid_member:
206326: libblkid: LOWPROBE: 	call probefunc()
206326: libblkid: LOWPROBE: 	read: off=234584211456 len=64
206326: libblkid: LOWPROBE: 	read failed: Input/output error
206326: libblkid: LOWPROBE: <-- leaving probing loop (failed=-5) [SUBLKS idx=0]
206326: libblkid: LOWPROBE: freeing values list
206326: libblkid: LOWPROBE: end probe
206326: libblkid: LOWPROBE: zeroize wiper
206326: libblkid: LOWPROBE: free probe

After:

LIBBLKID_DEBUG=all blkid -p /dev/sdd2
206221: libblkid:     INIT: library debug mask: 0xffff
206221: libblkid:     INIT: library version: 2.38.1119 [28-Mar-2022]
Available "LIBBLKID_DEBUG=<name>[,...]|<mask>" debug masks:
   all      [0x00ffff] : info about all subsystems
   cache    [0x000004] : blkid tags cache
   config   [0x000008] : config file utils
   dev      [0x000010] : device utils
   devname  [0x000020] : /proc/partitions evaluation
   devno    [0x000040] : conversions to device name
   evaluate [0x000080] : tags resolving
   help     [0x000001] : this help
   lowprobe [0x000100] : superblock/raids/partitions probing
   buffer   [0x002000] : low-probing buffers
   probe    [0x000200] : devices verification
   read     [0x000400] : cache parsing
   save     [0x000800] : cache writing
   tag      [0x001000] : tags utils
206221: libblkid: LOWPROBE: allocate a new probe
206221: libblkid: LOWPROBE: zeroize wiper
206221: libblkid: LOWPROBE: ready for low-probing, offset=0, size=234584276992, zonesize=0
206221: libblkid: LOWPROBE: whole-disk: NO, regfile: NO
206221: libblkid: LOWPROBE: start probe
206221: libblkid: LOWPROBE: zeroize wiper
206221: libblkid: LOWPROBE: chain safeprobe superblocks ENABLED
206221: libblkid: LOWPROBE: --> starting probing loop [SUBLKS idx=-1]
206221: libblkid: LOWPROBE: [0] linux_raid_member:
206221: libblkid: LOWPROBE: 	call probefunc()
206221: libblkid: LOWPROBE: 	read: off=234584211456 len=64
206221: libblkid: LOWPROBE: 	read failed: Input/output error
206221: libblkid: LOWPROBE: 	read: off=234584268800 len=256
206221: libblkid: LOWPROBE: 	read failed: Input/output error
206221: libblkid: LOWPROBE: 	read: off=0 len=256
206221: libblkid: LOWPROBE: 	read: off=4096 len=256
206221: libblkid: LOWPROBE: [1] ddf_raid_member:
206221: libblkid: LOWPROBE: 	call probefunc()
206221: libblkid: LOWPROBE: 	read: off=234584276480 len=512
206221: libblkid: LOWPROBE: 	read failed: Input/output error
206221: libblkid: LOWPROBE: [2] isw_raid_member:
206221: libblkid: LOWPROBE: 	call probefunc()
206221: libblkid: LOWPROBE: [3] lsi_mega_raid_member:
206221: libblkid: LOWPROBE: 	call probefunc()
206221: libblkid: LOWPROBE: [4] via_raid_member:
206221: libblkid: LOWPROBE: 	call probefunc()
206221: libblkid: LOWPROBE: [5] silicon_medley_raid_member:
206221: libblkid: LOWPROBE: 	call probefunc()
206221: libblkid: LOWPROBE: [6] nvidia_raid_member:
206221: libblkid: LOWPROBE: 	call probefunc()
206221: libblkid: LOWPROBE: [7] promise_fasttrack_raid_member:
206221: libblkid: LOWPROBE: 	call probefunc()
206221: libblkid: LOWPROBE: [8] hpt45x_raid_member:
206221: libblkid: LOWPROBE: 	call probefunc()
206221: libblkid: LOWPROBE: [9] hpt37x_raid_member:
206221: libblkid: LOWPROBE: 	read: off=4096 len=1024
206221: libblkid:   BUFFER: 	reuse: off=4096 len=1024 (for off=4096 len=1024)
206221: libblkid: LOWPROBE: [10] adaptec_raid_member:
206221: libblkid: LOWPROBE: 	call probefunc()
206221: libblkid: LOWPROBE: [11] jmicron_raid_member:
206221: libblkid: LOWPROBE: 	call probefunc()
206221: libblkid: LOWPROBE: [12] bcache:
206221: libblkid:   BUFFER: 	reuse: off=4096 len=1024 (for off=4096 len=1024)
206221: libblkid: LOWPROBE: [13] bcachefs:
206221: libblkid:   BUFFER: 	reuse: off=4096 len=1024 (for off=4096 len=1024)
206221: libblkid:   BUFFER: 	reuse: off=4096 len=1024 (for off=4096 len=1024)
206221: libblkid: LOWPROBE: [14] ceph_bluestore:
206221: libblkid: LOWPROBE: 	read: off=0 len=1024
206221: libblkid: LOWPROBE: [15] drbd:
206221: libblkid: LOWPROBE: 	call probefunc()
206221: libblkid: LOWPROBE: 	read: off=234584272896 len=104
206221: libblkid: LOWPROBE: 	read failed: Input/output error
206221: libblkid: LOWPROBE: 	read: off=234584272896 len=1392
206221: libblkid: LOWPROBE: 	read failed: Input/output error
206221: libblkid: LOWPROBE: [16] drbdmanage_control_volume:
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=1024)
206221: libblkid: LOWPROBE: [17] drbdproxy_datalog:
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=1024)
206221: libblkid: LOWPROBE: [18] LVM2_member:
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=1024)
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=1024)
206221: libblkid: LOWPROBE: 	read: off=1024 len=1024
206221: libblkid:   BUFFER: 	reuse: off=1024 len=1024 (for off=1024 len=1024)
206221: libblkid: LOWPROBE: [19] LVM1_member:
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=1024)
206221: libblkid: LOWPROBE: [20] DM_snapshot_cow:
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=1024)
206221: libblkid: LOWPROBE: [21] DM_verity_hash:
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=1024)
206221: libblkid: LOWPROBE: [22] DM_integrity:
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=1024)
206221: libblkid: LOWPROBE: [23] crypto_LUKS:
206221: libblkid: LOWPROBE: 	call probefunc()
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=512)
206221: libblkid: LOWPROBE: assigning VERSION [superblocks]
206221: libblkid: LOWPROBE: assigning UUID [superblocks]
206221: libblkid: LOWPROBE: assigning LABEL [superblocks]
206221: libblkid: LOWPROBE:  free value LABEL
206221: libblkid: LOWPROBE: assigning SUBSYSTEM [superblocks]
206221: libblkid: LOWPROBE: assigning TYPE [superblocks]
206221: libblkid: LOWPROBE: assigning USAGE [superblocks]
206221: libblkid: LOWPROBE: <-- leaving probing loop (type=crypto_LUKS) [SUBLKS idx=23]
206221: libblkid: LOWPROBE: freeing values list
206221: libblkid: LOWPROBE: chain safeprobe topology DISABLED
206221: libblkid: LOWPROBE: chain safeprobe partitions ENABLED
206221: libblkid: LOWPROBE: Resetting partitions values
206221: libblkid: LOWPROBE: --> starting probing loop [PARTS idx=-1]
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=1024)
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=1024)
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=1024)
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=1024)
206221: libblkid: LOWPROBE: gpt: ---> call probefunc()
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=512)
206221: libblkid: LOWPROBE: gpt: <--- (rc = 1)
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=1024)
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=1024)
206221: libblkid: LOWPROBE: ultrix: ---> call probefunc()
206221: libblkid: LOWPROBE: 	read: off=15872 len=512
206221: libblkid: LOWPROBE: ultrix: <--- (rc = 1)
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=1024)
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=1024)
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=1024)
206221: libblkid: LOWPROBE: 	read: off=28672 len=1024
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=1024)
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=1024)
206221: libblkid: LOWPROBE: atari: ---> call probefunc()
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=512)
206221: libblkid: LOWPROBE: atari: <--- (rc = 1)
206221: libblkid: LOWPROBE: <-- leaving probing loop (failed=1) [PARTS idx=12]
206221: libblkid: LOWPROBE: parts: start probing for partition entry
206221: libblkid:    DEVNO: found devno 0x0830 as /dev/sdd
206221: libblkid: LOWPROBE: allocate a wholedisk probe
206221: libblkid: LOWPROBE: allocate a new probe
206221: libblkid: LOWPROBE: zeroize wiper
206221: libblkid: LOWPROBE: ready for low-probing, offset=0, size=256060514304, zonesize=0
206221: libblkid: LOWPROBE: whole-disk: YES, regfile: NO
206221: libblkid: LOWPROBE: partlist reset
206221: libblkid: LOWPROBE: parts: initialized partitions list (size=0)
206221: libblkid: LOWPROBE: --> starting probing loop [PARTS idx=-1]
206221: libblkid: LOWPROBE: 	read: off=0 len=1024
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=1024)
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=1024)
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=1024)
206221: libblkid: LOWPROBE: 	magic sboff=510, kboff=0
206221: libblkid: LOWPROBE: dos: ---> call probefunc()
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=512)
206221: libblkid: LOWPROBE: probably GPT -- ignore
206221: libblkid: LOWPROBE: dos: <--- (rc = 1)
206221: libblkid: LOWPROBE: gpt: ---> call probefunc()
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=512)
206221: libblkid: LOWPROBE:  util-linux#1 valid PMBR partition
206221: libblkid: LOWPROBE:  checking for GPT header at 1
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=512 len=512)
206221: libblkid: LOWPROBE: 	read: off=1024 len=16384
206221: libblkid: LOWPROBE: parts: create a new partition table (type=gpt, offset=512)
206221: libblkid: LOWPROBE: parts: add partition (start=2048, size=41943040)
206221: libblkid: LOWPROBE: parts: add partition (start=41945088, size=458172416)
206221: libblkid: LOWPROBE: gpt: <--- (rc = 0)
206221: libblkid: LOWPROBE: <-- leaving probing loop (type=gpt) [PARTS idx=4]
206221: libblkid: LOWPROBE: partitions probe done [rc=0]
206221: libblkid: LOWPROBE: returning partitions binary data
206221: libblkid: LOWPROBE: trying to convert devno 0x832 to partition
206221: libblkid: LOWPROBE: searching by offset/size
206221: libblkid: LOWPROBE: assigning PART_ENTRY_SCHEME [partitions]
206221: libblkid: LOWPROBE: assigning PART_ENTRY_UUID [partitions]
206221: libblkid: LOWPROBE: assigning PART_ENTRY_TYPE [partitions]
206221: libblkid: LOWPROBE: assigning PART_ENTRY_NUMBER [partitions]
206221: libblkid: LOWPROBE: assigning PART_ENTRY_OFFSET [partitions]
206221: libblkid: LOWPROBE: assigning PART_ENTRY_SIZE [partitions]
206221: libblkid: LOWPROBE: assigning PART_ENTRY_DISK [partitions]
206221: libblkid: LOWPROBE: parts: end probing for partition entry [success]
206221: libblkid: LOWPROBE: partitions probe done [rc=0]
206221: libblkid: LOWPROBE: end probe
206221: libblkid: LOWPROBE: zeroize wiper
206221: libblkid: LOWPROBE: returning VERSION value
206221: libblkid: LOWPROBE: returning UUID value
206221: libblkid: LOWPROBE: returning SUBSYSTEM value
206221: libblkid: LOWPROBE: returning TYPE value
206221: libblkid: LOWPROBE: returning USAGE value
206221: libblkid: LOWPROBE: returning PART_ENTRY_SCHEME value
206221: libblkid: LOWPROBE: returning PART_ENTRY_UUID value
206221: libblkid: LOWPROBE: returning PART_ENTRY_TYPE value
206221: libblkid: LOWPROBE: returning PART_ENTRY_NUMBER value
206221: libblkid: LOWPROBE: returning PART_ENTRY_OFFSET value
206221: libblkid: LOWPROBE: returning PART_ENTRY_SIZE value
206221: libblkid: LOWPROBE: returning PART_ENTRY_DISK value
/dev/sdd2: VERSION="2" UUID="a918f1d0-f1de-44f5-9d93-ce9dc15cc2c7" SUBSYSTEM="HW-OPAL" TYPE="crypto_LUKS" USAGE="crypto" PART_ENTRY_SCHEME="gpt" PART_ENTRY_UUID="39ed5135-46e4-ca44-837e-da3c0781367b" PART_ENTRY_TYPE="0fc63daf-8483-4772-8e79-3d69d8477de4" PART_ENTRY_NUMBER="2" PART_ENTRY_OFFSET="41945088" PART_ENTRY_SIZE="458172416" PART_ENTRY_DISK="8:48"
206221: libblkid:   BUFFER: Resetting probing buffers
206221: libblkid:   BUFFER:  remove buffer: [off=0, len=256]
206221: libblkid:   BUFFER:  remove buffer: [off=4096, len=256]
206221: libblkid:   BUFFER:  remove buffer: [off=4096, len=1024]
206221: libblkid:   BUFFER:  remove buffer: [off=0, len=1024]
206221: libblkid:   BUFFER:  remove buffer: [off=1024, len=1024]
206221: libblkid:   BUFFER:  remove buffer: [off=15872, len=512]
206221: libblkid:   BUFFER:  remove buffer: [off=28672, len=1024]
206221: libblkid: LOWPROBE:  buffers summary: 5120 bytes by 7 read() calls
206221: libblkid: LOWPROBE: resetting results
206221: libblkid: LOWPROBE:  free value VERSION
206221: libblkid: LOWPROBE:  free value UUID
206221: libblkid: LOWPROBE:  free value SUBSYSTEM
206221: libblkid: LOWPROBE:  free value TYPE
206221: libblkid: LOWPROBE:  free value USAGE
206221: libblkid: LOWPROBE:  free value PART_ENTRY_SCHEME
206221: libblkid: LOWPROBE:  free value PART_ENTRY_UUID
206221: libblkid: LOWPROBE:  free value PART_ENTRY_TYPE
206221: libblkid: LOWPROBE:  free value PART_ENTRY_NUMBER
206221: libblkid: LOWPROBE:  free value PART_ENTRY_OFFSET
206221: libblkid: LOWPROBE:  free value PART_ENTRY_SIZE
206221: libblkid: LOWPROBE:  free value PART_ENTRY_DISK
206221: libblkid:   BUFFER: Resetting probing buffers
206221: libblkid:   BUFFER:  remove buffer: [off=0, len=1024]
206221: libblkid:   BUFFER:  remove buffer: [off=1024, len=16384]
206221: libblkid: LOWPROBE:  buffers summary: 17408 bytes by 2 read() calls
206221: libblkid: LOWPROBE: free probe
206221: libblkid: LOWPROBE: free probe

Signed-off-by: Luca Boccassi <bluca@debian.org>
bluca added a commit to bluca/util-linux that referenced this issue Feb 22, 2023
Use the appropriate ioctl, if available, to check if a device is locked
when we get an I/O error. Save the information so that we don't have to
repeat the ioctl.

Before:

LIBBLKID_DEBUG=all blkid -p /dev/sdd2
206326: libblkid:     INIT: library debug mask: 0xffff
206326: libblkid:     INIT: library version: 2.38.1 [04-Aug-2022]
Available "LIBBLKID_DEBUG=<name>[,...]|<mask>" debug masks:
   all      [0xffff] : info about all subsystems
   cache    [0x0004] : blkid tags cache
   config   [0x0008] : config file utils
   dev      [0x0010] : device utils
   devname  [0x0020] : /proc/partitions evaluation
   devno    [0x0040] : conversions to device name
   evaluate [0x0080] : tags resolving
   help     [0x0001] : this help
   lowprobe [0x0100] : superblock/raids/partitions probing
   buffer   [0x2000] : low-probing buffers
   probe    [0x0200] : devices verification
   read     [0x0400] : cache parsing
   save     [0x0800] : cache writing
   tag      [0x1000] : tags utils
206326: libblkid: LOWPROBE: allocate a new probe
206326: libblkid: LOWPROBE: zeroize wiper
206326: libblkid: LOWPROBE: ready for low-probing, offset=0, size=234584276992, zonesize=0
206326: libblkid: LOWPROBE: whole-disk: NO, regfile: NO
206326: libblkid: LOWPROBE: start probe
206326: libblkid: LOWPROBE: zeroize wiper
206326: libblkid: LOWPROBE: chain safeprobe superblocks ENABLED
206326: libblkid: LOWPROBE: --> starting probing loop [SUBLKS idx=-1]
206326: libblkid: LOWPROBE: [0] linux_raid_member:
206326: libblkid: LOWPROBE: 	call probefunc()
206326: libblkid: LOWPROBE: 	read: off=234584211456 len=64
206326: libblkid: LOWPROBE: 	read failed: Input/output error
206326: libblkid: LOWPROBE: <-- leaving probing loop (failed=-5) [SUBLKS idx=0]
206326: libblkid: LOWPROBE: freeing values list
206326: libblkid: LOWPROBE: end probe
206326: libblkid: LOWPROBE: zeroize wiper
206326: libblkid: LOWPROBE: free probe

After:

LIBBLKID_DEBUG=all blkid -p /dev/sdd2
206221: libblkid:     INIT: library debug mask: 0xffff
206221: libblkid:     INIT: library version: 2.38.1119 [28-Mar-2022]
Available "LIBBLKID_DEBUG=<name>[,...]|<mask>" debug masks:
   all      [0x00ffff] : info about all subsystems
   cache    [0x000004] : blkid tags cache
   config   [0x000008] : config file utils
   dev      [0x000010] : device utils
   devname  [0x000020] : /proc/partitions evaluation
   devno    [0x000040] : conversions to device name
   evaluate [0x000080] : tags resolving
   help     [0x000001] : this help
   lowprobe [0x000100] : superblock/raids/partitions probing
   buffer   [0x002000] : low-probing buffers
   probe    [0x000200] : devices verification
   read     [0x000400] : cache parsing
   save     [0x000800] : cache writing
   tag      [0x001000] : tags utils
206221: libblkid: LOWPROBE: allocate a new probe
206221: libblkid: LOWPROBE: zeroize wiper
206221: libblkid: LOWPROBE: ready for low-probing, offset=0, size=234584276992, zonesize=0
206221: libblkid: LOWPROBE: whole-disk: NO, regfile: NO
206221: libblkid: LOWPROBE: start probe
206221: libblkid: LOWPROBE: zeroize wiper
206221: libblkid: LOWPROBE: chain safeprobe superblocks ENABLED
206221: libblkid: LOWPROBE: --> starting probing loop [SUBLKS idx=-1]
206221: libblkid: LOWPROBE: [0] linux_raid_member:
206221: libblkid: LOWPROBE: 	call probefunc()
206221: libblkid: LOWPROBE: 	read: off=234584211456 len=64
206221: libblkid: LOWPROBE: 	read failed: Input/output error
206221: libblkid: LOWPROBE: 	read: off=234584268800 len=256
206221: libblkid: LOWPROBE: 	read failed: Input/output error
206221: libblkid: LOWPROBE: 	read: off=0 len=256
206221: libblkid: LOWPROBE: 	read: off=4096 len=256
206221: libblkid: LOWPROBE: [1] ddf_raid_member:
206221: libblkid: LOWPROBE: 	call probefunc()
206221: libblkid: LOWPROBE: 	read: off=234584276480 len=512
206221: libblkid: LOWPROBE: 	read failed: Input/output error
206221: libblkid: LOWPROBE: [2] isw_raid_member:
206221: libblkid: LOWPROBE: 	call probefunc()
206221: libblkid: LOWPROBE: [3] lsi_mega_raid_member:
206221: libblkid: LOWPROBE: 	call probefunc()
206221: libblkid: LOWPROBE: [4] via_raid_member:
206221: libblkid: LOWPROBE: 	call probefunc()
206221: libblkid: LOWPROBE: [5] silicon_medley_raid_member:
206221: libblkid: LOWPROBE: 	call probefunc()
206221: libblkid: LOWPROBE: [6] nvidia_raid_member:
206221: libblkid: LOWPROBE: 	call probefunc()
206221: libblkid: LOWPROBE: [7] promise_fasttrack_raid_member:
206221: libblkid: LOWPROBE: 	call probefunc()
206221: libblkid: LOWPROBE: [8] hpt45x_raid_member:
206221: libblkid: LOWPROBE: 	call probefunc()
206221: libblkid: LOWPROBE: [9] hpt37x_raid_member:
206221: libblkid: LOWPROBE: 	read: off=4096 len=1024
206221: libblkid:   BUFFER: 	reuse: off=4096 len=1024 (for off=4096 len=1024)
206221: libblkid: LOWPROBE: [10] adaptec_raid_member:
206221: libblkid: LOWPROBE: 	call probefunc()
206221: libblkid: LOWPROBE: [11] jmicron_raid_member:
206221: libblkid: LOWPROBE: 	call probefunc()
206221: libblkid: LOWPROBE: [12] bcache:
206221: libblkid:   BUFFER: 	reuse: off=4096 len=1024 (for off=4096 len=1024)
206221: libblkid: LOWPROBE: [13] bcachefs:
206221: libblkid:   BUFFER: 	reuse: off=4096 len=1024 (for off=4096 len=1024)
206221: libblkid:   BUFFER: 	reuse: off=4096 len=1024 (for off=4096 len=1024)
206221: libblkid: LOWPROBE: [14] ceph_bluestore:
206221: libblkid: LOWPROBE: 	read: off=0 len=1024
206221: libblkid: LOWPROBE: [15] drbd:
206221: libblkid: LOWPROBE: 	call probefunc()
206221: libblkid: LOWPROBE: 	read: off=234584272896 len=104
206221: libblkid: LOWPROBE: 	read failed: Input/output error
206221: libblkid: LOWPROBE: 	read: off=234584272896 len=1392
206221: libblkid: LOWPROBE: 	read failed: Input/output error
206221: libblkid: LOWPROBE: [16] drbdmanage_control_volume:
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=1024)
206221: libblkid: LOWPROBE: [17] drbdproxy_datalog:
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=1024)
206221: libblkid: LOWPROBE: [18] LVM2_member:
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=1024)
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=1024)
206221: libblkid: LOWPROBE: 	read: off=1024 len=1024
206221: libblkid:   BUFFER: 	reuse: off=1024 len=1024 (for off=1024 len=1024)
206221: libblkid: LOWPROBE: [19] LVM1_member:
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=1024)
206221: libblkid: LOWPROBE: [20] DM_snapshot_cow:
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=1024)
206221: libblkid: LOWPROBE: [21] DM_verity_hash:
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=1024)
206221: libblkid: LOWPROBE: [22] DM_integrity:
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=1024)
206221: libblkid: LOWPROBE: [23] crypto_LUKS:
206221: libblkid: LOWPROBE: 	call probefunc()
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=512)
206221: libblkid: LOWPROBE: assigning VERSION [superblocks]
206221: libblkid: LOWPROBE: assigning UUID [superblocks]
206221: libblkid: LOWPROBE: assigning LABEL [superblocks]
206221: libblkid: LOWPROBE:  free value LABEL
206221: libblkid: LOWPROBE: assigning SUBSYSTEM [superblocks]
206221: libblkid: LOWPROBE: assigning TYPE [superblocks]
206221: libblkid: LOWPROBE: assigning USAGE [superblocks]
206221: libblkid: LOWPROBE: <-- leaving probing loop (type=crypto_LUKS) [SUBLKS idx=23]
206221: libblkid: LOWPROBE: freeing values list
206221: libblkid: LOWPROBE: chain safeprobe topology DISABLED
206221: libblkid: LOWPROBE: chain safeprobe partitions ENABLED
206221: libblkid: LOWPROBE: Resetting partitions values
206221: libblkid: LOWPROBE: --> starting probing loop [PARTS idx=-1]
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=1024)
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=1024)
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=1024)
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=1024)
206221: libblkid: LOWPROBE: gpt: ---> call probefunc()
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=512)
206221: libblkid: LOWPROBE: gpt: <--- (rc = 1)
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=1024)
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=1024)
206221: libblkid: LOWPROBE: ultrix: ---> call probefunc()
206221: libblkid: LOWPROBE: 	read: off=15872 len=512
206221: libblkid: LOWPROBE: ultrix: <--- (rc = 1)
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=1024)
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=1024)
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=1024)
206221: libblkid: LOWPROBE: 	read: off=28672 len=1024
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=1024)
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=1024)
206221: libblkid: LOWPROBE: atari: ---> call probefunc()
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=512)
206221: libblkid: LOWPROBE: atari: <--- (rc = 1)
206221: libblkid: LOWPROBE: <-- leaving probing loop (failed=1) [PARTS idx=12]
206221: libblkid: LOWPROBE: parts: start probing for partition entry
206221: libblkid:    DEVNO: found devno 0x0830 as /dev/sdd
206221: libblkid: LOWPROBE: allocate a wholedisk probe
206221: libblkid: LOWPROBE: allocate a new probe
206221: libblkid: LOWPROBE: zeroize wiper
206221: libblkid: LOWPROBE: ready for low-probing, offset=0, size=256060514304, zonesize=0
206221: libblkid: LOWPROBE: whole-disk: YES, regfile: NO
206221: libblkid: LOWPROBE: partlist reset
206221: libblkid: LOWPROBE: parts: initialized partitions list (size=0)
206221: libblkid: LOWPROBE: --> starting probing loop [PARTS idx=-1]
206221: libblkid: LOWPROBE: 	read: off=0 len=1024
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=1024)
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=1024)
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=1024)
206221: libblkid: LOWPROBE: 	magic sboff=510, kboff=0
206221: libblkid: LOWPROBE: dos: ---> call probefunc()
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=512)
206221: libblkid: LOWPROBE: probably GPT -- ignore
206221: libblkid: LOWPROBE: dos: <--- (rc = 1)
206221: libblkid: LOWPROBE: gpt: ---> call probefunc()
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=0 len=512)
206221: libblkid: LOWPROBE:  util-linux#1 valid PMBR partition
206221: libblkid: LOWPROBE:  checking for GPT header at 1
206221: libblkid:   BUFFER: 	reuse: off=0 len=1024 (for off=512 len=512)
206221: libblkid: LOWPROBE: 	read: off=1024 len=16384
206221: libblkid: LOWPROBE: parts: create a new partition table (type=gpt, offset=512)
206221: libblkid: LOWPROBE: parts: add partition (start=2048, size=41943040)
206221: libblkid: LOWPROBE: parts: add partition (start=41945088, size=458172416)
206221: libblkid: LOWPROBE: gpt: <--- (rc = 0)
206221: libblkid: LOWPROBE: <-- leaving probing loop (type=gpt) [PARTS idx=4]
206221: libblkid: LOWPROBE: partitions probe done [rc=0]
206221: libblkid: LOWPROBE: returning partitions binary data
206221: libblkid: LOWPROBE: trying to convert devno 0x832 to partition
206221: libblkid: LOWPROBE: searching by offset/size
206221: libblkid: LOWPROBE: assigning PART_ENTRY_SCHEME [partitions]
206221: libblkid: LOWPROBE: assigning PART_ENTRY_UUID [partitions]
206221: libblkid: LOWPROBE: assigning PART_ENTRY_TYPE [partitions]
206221: libblkid: LOWPROBE: assigning PART_ENTRY_NUMBER [partitions]
206221: libblkid: LOWPROBE: assigning PART_ENTRY_OFFSET [partitions]
206221: libblkid: LOWPROBE: assigning PART_ENTRY_SIZE [partitions]
206221: libblkid: LOWPROBE: assigning PART_ENTRY_DISK [partitions]
206221: libblkid: LOWPROBE: parts: end probing for partition entry [success]
206221: libblkid: LOWPROBE: partitions probe done [rc=0]
206221: libblkid: LOWPROBE: end probe
206221: libblkid: LOWPROBE: zeroize wiper
206221: libblkid: LOWPROBE: returning VERSION value
206221: libblkid: LOWPROBE: returning UUID value
206221: libblkid: LOWPROBE: returning SUBSYSTEM value
206221: libblkid: LOWPROBE: returning TYPE value
206221: libblkid: LOWPROBE: returning USAGE value
206221: libblkid: LOWPROBE: returning PART_ENTRY_SCHEME value
206221: libblkid: LOWPROBE: returning PART_ENTRY_UUID value
206221: libblkid: LOWPROBE: returning PART_ENTRY_TYPE value
206221: libblkid: LOWPROBE: returning PART_ENTRY_NUMBER value
206221: libblkid: LOWPROBE: returning PART_ENTRY_OFFSET value
206221: libblkid: LOWPROBE: returning PART_ENTRY_SIZE value
206221: libblkid: LOWPROBE: returning PART_ENTRY_DISK value
/dev/sdd2: VERSION="2" UUID="a918f1d0-f1de-44f5-9d93-ce9dc15cc2c7" SUBSYSTEM="HW-OPAL" TYPE="crypto_LUKS" USAGE="crypto" PART_ENTRY_SCHEME="gpt" PART_ENTRY_UUID="39ed5135-46e4-ca44-837e-da3c0781367b" PART_ENTRY_TYPE="0fc63daf-8483-4772-8e79-3d69d8477de4" PART_ENTRY_NUMBER="2" PART_ENTRY_OFFSET="41945088" PART_ENTRY_SIZE="458172416" PART_ENTRY_DISK="8:48"
206221: libblkid:   BUFFER: Resetting probing buffers
206221: libblkid:   BUFFER:  remove buffer: [off=0, len=256]
206221: libblkid:   BUFFER:  remove buffer: [off=4096, len=256]
206221: libblkid:   BUFFER:  remove buffer: [off=4096, len=1024]
206221: libblkid:   BUFFER:  remove buffer: [off=0, len=1024]
206221: libblkid:   BUFFER:  remove buffer: [off=1024, len=1024]
206221: libblkid:   BUFFER:  remove buffer: [off=15872, len=512]
206221: libblkid:   BUFFER:  remove buffer: [off=28672, len=1024]
206221: libblkid: LOWPROBE:  buffers summary: 5120 bytes by 7 read() calls
206221: libblkid: LOWPROBE: resetting results
206221: libblkid: LOWPROBE:  free value VERSION
206221: libblkid: LOWPROBE:  free value UUID
206221: libblkid: LOWPROBE:  free value SUBSYSTEM
206221: libblkid: LOWPROBE:  free value TYPE
206221: libblkid: LOWPROBE:  free value USAGE
206221: libblkid: LOWPROBE:  free value PART_ENTRY_SCHEME
206221: libblkid: LOWPROBE:  free value PART_ENTRY_UUID
206221: libblkid: LOWPROBE:  free value PART_ENTRY_TYPE
206221: libblkid: LOWPROBE:  free value PART_ENTRY_NUMBER
206221: libblkid: LOWPROBE:  free value PART_ENTRY_OFFSET
206221: libblkid: LOWPROBE:  free value PART_ENTRY_SIZE
206221: libblkid: LOWPROBE:  free value PART_ENTRY_DISK
206221: libblkid:   BUFFER: Resetting probing buffers
206221: libblkid:   BUFFER:  remove buffer: [off=0, len=1024]
206221: libblkid:   BUFFER:  remove buffer: [off=1024, len=16384]
206221: libblkid: LOWPROBE:  buffers summary: 17408 bytes by 2 read() calls
206221: libblkid: LOWPROBE: free probe
206221: libblkid: LOWPROBE: free probe

Signed-off-by: Luca Boccassi <bluca@debian.org>
rpigott added a commit to rpigott/util-linux that referenced this issue Mar 23, 2023
If the fmt being parsed by block_size is exactly '%', *++fmt is the
terminator and strchr will return a valid pointer to the terminator of
spec rather than NULL, the while condition will pass and subsequent
strchr will read past the end of fmt until a spec character is found
again

ASAN aborts with the following error on the first buffer overread:

AddressSanitizer: heap-buffer-overflow on address 0x602000000212 at pc 0x55bf1c4b2d78 bp 0x7ffe33c8cff0 sp 0x7ffe33c8cfe0
READ of size 1 at 0x602000000212 thread T0
    #0 0x55bf1c4b2d77 in block_size ../text-utils/hexdump-parse.c:207
    util-linux#1 0x55bf1c4ad36f in main ../text-utils/hexdump.c:214
    util-linux#2 0x7f15f063c78f  (/usr/lib/libc.so.6+0x2378f)
    util-linux#3 0x7f15f063c849 in __libc_start_main (/usr/lib/libc.so.6+0x23849)
    util-linux#4 0x55bf1c4ac6c4 in _start (../build/hexdump+0x86c4)
rpigott added a commit to rpigott/util-linux that referenced this issue Mar 24, 2023
If the fmt being parsed by block_size is exactly '%', *++fmt is the
terminator and strchr will return a valid pointer to the terminator of
spec rather than NULL, the while condition will pass and subsequent
strchr will read past the end of fmt until a spec character is found
again

ASAN aborts with the following error on the first buffer overread:

AddressSanitizer: heap-buffer-overflow on address 0x602000000212 at pc 0x55bf1c4b2d78 bp 0x7ffe33c8cff0 sp 0x7ffe33c8cfe0
READ of size 1 at 0x602000000212 thread T0
    #0 0x55bf1c4b2d77 in block_size ../text-utils/hexdump-parse.c:207
    util-linux#1 0x55bf1c4ad36f in main ../text-utils/hexdump.c:214
    util-linux#2 0x7f15f063c78f  (/usr/lib/libc.so.6+0x2378f)
    util-linux#3 0x7f15f063c849 in __libc_start_main (/usr/lib/libc.so.6+0x23849)
    util-linux#4 0x55bf1c4ac6c4 in _start (../build/hexdump+0x86c4)
t-8ch added a commit to t-8ch/util-linux that referenced this issue Nov 20, 2023
Passing a pointer to a pid_t to tfind() which expects it to be backed by
a 'struct proc' evokes undefined behavior.
This triggers UBSAN as shown below.

Instead pass a proper 'struct proc'.

../misc-utils/lsfd.c:513:27: runtime error: member access within misaligned address 0x7ffe9ee6495c for type 'struct proc', which requires 8 byte alignment
0x7ffe9ee6495c: note: pointer points here
  1a 1a 1a 1a 01 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  d0 49 e6 9e fe 7f 00 00
              ^
    #0 0x56159cfa4a3b in proc_tree_compare ../misc-utils/lsfd.c:513
    util-linux#1 0x7f9dd4d2d743 in __tfind (/usr/lib/libc.so.6+0x10f743) (BuildId: 8bfe03f6bf9b6a6e2591babd0bbc266837d8f658)
    util-linux#2 0x56159cfa4ac3 in get_proc ../misc-utils/lsfd.c:518
    util-linux#3 0x56159cfe217b in anon_pidfd_get_name ../misc-utils/lsfd-unkn.c:203
    util-linux#4 0x56159cfe1040 in unkn_fill_column ../misc-utils/lsfd-unkn.c:93
    util-linux#5 0x56159cfaaa37 in fill_column ../misc-utils/lsfd.c:1178
    util-linux#6 0x56159cfaaac5 in convert_file ../misc-utils/lsfd.c:1193
    util-linux#7 0x56159cfaac4f in convert ../misc-utils/lsfd.c:1212
    util-linux#8 0x56159cfb2b54 in main ../misc-utils/lsfd.c:2317
    util-linux#9 0x7f9dd4c45ccf  (/usr/lib/libc.so.6+0x27ccf) (BuildId: 8bfe03f6bf9b6a6e2591babd0bbc266837d8f658)
    util-linux#10 0x7f9dd4c45d89 in __libc_start_main (/usr/lib/libc.so.6+0x27d89) (BuildId: 8bfe03f6bf9b6a6e2591babd0bbc266837d8f658)
    util-linux#11 0x56159cfa3c34 in _start (util-linux/build-meson/lsfd+0x41c34) (BuildId: 35fece1a205f96a2dbfe7a0e93b658530de675c4)

Signed-off-by: Thomas Weißschuh <thomas@t-8ch.de>
t-8ch added a commit to t-8ch/util-linux that referenced this issue Nov 20, 2023
Passing a pointer to a different datatype to tfind() then were inserted
evokes undefines behavior.
This triggers UBSAN as shown below.

Instead pass the proper structs.

```
../misc-utils/lsfd.c:513:27: runtime error: member access within misaligned address 0x7ffe9ee6495c for type 'struct proc', which requires 8 byte alignment
0x7ffe9ee6495c: note: pointer points here
  1a 1a 1a 1a 01 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  d0 49 e6 9e fe 7f 00 00
              ^
    #0 0x56159cfa4a3b in proc_tree_compare ../misc-utils/lsfd.c:513
    util-linux#1 0x7f9dd4d2d743 in __tfind (/usr/lib/libc.so.6+0x10f743) (BuildId: 8bfe03f6bf9b6a6e2591babd0bbc266837d8f658)
    util-linux#2 0x56159cfa4ac3 in get_proc ../misc-utils/lsfd.c:518
    util-linux#3 0x56159cfe217b in anon_pidfd_get_name ../misc-utils/lsfd-unkn.c:203
    util-linux#4 0x56159cfe1040 in unkn_fill_column ../misc-utils/lsfd-unkn.c:93
    util-linux#5 0x56159cfaaa37 in fill_column ../misc-utils/lsfd.c:1178
    util-linux#6 0x56159cfaaac5 in convert_file ../misc-utils/lsfd.c:1193
    util-linux#7 0x56159cfaac4f in convert ../misc-utils/lsfd.c:1212
    util-linux#8 0x56159cfb2b54 in main ../misc-utils/lsfd.c:2317
    util-linux#9 0x7f9dd4c45ccf  (/usr/lib/libc.so.6+0x27ccf) (BuildId: 8bfe03f6bf9b6a6e2591babd0bbc266837d8f658)
    util-linux#10 0x7f9dd4c45d89 in __libc_start_main (/usr/lib/libc.so.6+0x27d89) (BuildId: 8bfe03f6bf9b6a6e2591babd0bbc266837d8f658)
    util-linux#11 0x56159cfa3c34 in _start (util-linux/build-meson/lsfd+0x41c34) (BuildId: 35fece1a205f96a2dbfe7a0e93b658530de675c4)
```

Signed-off-by: Thomas Weißschuh <thomas@t-8ch.de>
karelzak pushed a commit that referenced this issue Nov 30, 2023
Passing a pointer to a different datatype to tfind() then were inserted
evokes undefines behavior.
This triggers UBSAN as shown below.

Instead pass the proper structs.

```
../misc-utils/lsfd.c:513:27: runtime error: member access within misaligned address 0x7ffe9ee6495c for type 'struct proc', which requires 8 byte alignment
0x7ffe9ee6495c: note: pointer points here
  1a 1a 1a 1a 01 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  d0 49 e6 9e fe 7f 00 00
              ^
    #0 0x56159cfa4a3b in proc_tree_compare ../misc-utils/lsfd.c:513
    #1 0x7f9dd4d2d743 in __tfind (/usr/lib/libc.so.6+0x10f743) (BuildId: 8bfe03f6bf9b6a6e2591babd0bbc266837d8f658)
    #2 0x56159cfa4ac3 in get_proc ../misc-utils/lsfd.c:518
    #3 0x56159cfe217b in anon_pidfd_get_name ../misc-utils/lsfd-unkn.c:203
    #4 0x56159cfe1040 in unkn_fill_column ../misc-utils/lsfd-unkn.c:93
    #5 0x56159cfaaa37 in fill_column ../misc-utils/lsfd.c:1178
    #6 0x56159cfaaac5 in convert_file ../misc-utils/lsfd.c:1193
    #7 0x56159cfaac4f in convert ../misc-utils/lsfd.c:1212
    #8 0x56159cfb2b54 in main ../misc-utils/lsfd.c:2317
    #9 0x7f9dd4c45ccf  (/usr/lib/libc.so.6+0x27ccf) (BuildId: 8bfe03f6bf9b6a6e2591babd0bbc266837d8f658)
    #10 0x7f9dd4c45d89 in __libc_start_main (/usr/lib/libc.so.6+0x27d89) (BuildId: 8bfe03f6bf9b6a6e2591babd0bbc266837d8f658)
    #11 0x56159cfa3c34 in _start (util-linux/build-meson/lsfd+0x41c34) (BuildId: 35fece1a205f96a2dbfe7a0e93b658530de675c4)
```

Signed-off-by: Thomas Weißschuh <thomas@t-8ch.de>
(cherry picked from commit 816109f)
karelzak pushed a commit that referenced this issue Dec 12, 2023
Submission to Project: util-linux
Open Incident: #2637 at github.com//issues/2637
Component: util-linux/sys-utils
File: dmesg.c
Code level patch applied against: https://github.com/t-8ch/util-linux/
     and we used his local-dmesg-tests from t8ch/dmesg/tests
     as we needed the numerous improvements and fixes that Thomas has
     made to the code.

With Issue 2609 support is being added for the optional PRINTK_CALLER
dmesg field that is produced by the Linux Kernel when the PRINTK_CALLER
config option is set. This patch addresses testing issue with the SYSLOG
interface when used on Linux Kernels with the PRINTK_CALLER config
option set.

Since these tests are for dmesg SYSLOG interface we are submitting
in a separate issue to not conflate with the tests we will be submitting
for the dmesg kmsg (standard) interface.

Currently dmesg -S, the syslog interface, to dmesg already supports this
optional field and produces output that includes the PRINTK_CALLER field.

So on a Linux system with the PRINTK_CALLER configuration option set the
output looks like:

    [  520.899558] [   T3919] hub 3-3:1.0: USB hub found

on a system where the PRINTK_CALLER configuration option is not set the
output looks like:

    [  520.899558] hub 3-3:1.0: USB hub found

the additional field specifies either a Thread Id or CPU id depending on
the context of the task or thread at the time the printk that added the
message to the kernel ring buffer was executed.

The code submitted with Issue 2609 adds support for the optional
PRINTK_CALLER field for the standard /dev/ksmg dmesg interface.

Karel and Thomas pointed out that we need to add appropriate tests
for the dmesg package, so tests need to be added to the Issue 2609
submission to support PRINTK_CALLER field with the /dev/kmsg interface.

However, we noticed that though the PRINTK_CALLER optional field is
supported by the dmesg syslog interface there are no tests for that
existing facility.

It was pointed that we really need tests for both dmesg interaces, the
dmesg syslog interface which we address here and the dmesg /dev/kmsg
interface that we address in Issue 2609.

It is desirable to have tests for both dmesg interfaces since they
exercise slightly different paths in the dmesg code.

So we provide tests here specifically for dmesg syslog interface when
the Linux Kernel has PRINTK_CALLER field enabled.

We make copies of the existing tests/ts/dmesg tests and tailor them to
test with input that includes the optional PRINTK_CALLER field and output
that expects that PRINTK_CALLER optional field will be included.

By providing all the syslog-printk-caller versions of all the tests
we ensure the same thorough testing of the dmesg syslog interface.

For tests using the dmesg syslog interface we use the -F interface to
produce reliable testing results just as the existing dmesg tests do.
The -F interface is specific only to the syslog interface but that is
what we are testing here.

Note that using the -F interface means that the system executing the tests
does not need to have the PRINTK_CALLER interface to do the testing. The
files provide the correct format which is very convenient.

Testing occurred on a Fedora 39 System:

[echron@terramar util-linux]$ uname -a
Linux terramar 6.6.4-200.fc39.x86_64 #1 SMP PREEMPT_DYNAMIC
      Sun Dec  3 18:13:11 UTC 2023 x86_64 GNU/Linux

[echron@terramar util-linux]$ cat /etc/fedora-release
Fedora release 39 (Thirty Nine)

The version of util-linux was from the git repository with a pull on
2023/12/09 at 10:00 AM

----------------------------
Please Note - Very Important:
----------------------------
In testing we realized we needed some fixes that we know Thomas just
added so we did a remote add of https://github.com/t-8ch/util-linux/
and we used his local-dmesg-tests t8ch/dmesg/tests

Picking up Thomas's fixes resolved the problems we were seeing with
several of our tests.

*** Please test and merge this code with Thomas's project:
     t8ch/dmesg/tests

[echron@terramar util-linux]$ ./test_dmesg -V
test_dmesg from util-linux 2.39.1003-6b081

We did the recommended make check-programs before running our programs.

Tests include syslog-printk-caller versions of all existing tests:

-------------------- util-linux regression tests --------------------

                    For development purpose only.
                 Don't execute on production system!

       kernel: 6.6.4-200.fc39.x86_64

      options: --srcdir=/usr/src/util-linux/pending/util-linux/tests/.. \
               --builddir=/usr/src/util-linux/pending/util-linux/tests/..

        dmesg: colors                         ... OK
        dmesg: colors-syslog-prtk-caller      ... OK
        dmesg: levels                         ... OK
        dmesg: levels-syslog-prtk-caller      ... OK
        dmesg: decode                         ... OK
        dmesg: decode-syslog-prtk-caller      ... OK
        dmesg: delta                          ... OK
        dmesg: delta-syslog-prtk-caller       ... OK
        dmesg: facilities                     ... OK
        dmesg: facilities-syslog-prtk-caller  ... OK
        dmesg: indentation                    ... OK
        dmesg: indent-syslog-printk-caller    ... OK
        dmesg: limit                          ... OK
        dmesg: limit-syslog-prtk-caller       ... OK

Signed-off-by: Ivan Delalande <colona@arista.com>
Signed-off-by: Edward Chron <echron@arista.com>
karelzak pushed a commit that referenced this issue Dec 12, 2023
Submission to Project: util-linux
Open Incident: #2906 at github.com//issues/2906
Component: util-linux/sys-utils
File: dmesg.c
Code level patch applied against: 2.39.3 - latest code pulled from
           git.github.com:util-linux/util-linux.git
Revision: #1 on 2023/12/08 per Review from Karel Zak

Add support to standard dmesg command for the optional Linux Kernel
debug CONFIG option PRINTK_CALLER which adds an optional dmesg field
that contains the Thread Id or CPU Id that is issuing the printk to
add the message to the kernel ring buffer. This makes debugging simpler
as dmesg entries for a specific thread or CPU can be recognized.

The dmesg -S using the old syslog interface supports printing the
PRINTK_CALLER field but currently standard dmesg does not support
printing the field if present. There are utilities that use dmesg and
so it would be optimal if dmesg supported PRINTK_CALLER as well.

The additional field provided by PRINTK_CALLER is only present
if it was configured for the Linux kernel where the dmesg command
is run. It is a debug option and not configured by default so the
dmesg output will only change for those kernels where the option was
configured when the kernel was built. For users who went to the
trouble to configure PRINTK_CALLER and have the extra field available
for debugging, having dmesg print the field is very helpful.

Size of the PRINTK_CALLER field is determined by the maximum number
tasks that can be run on the system which is limited by the value of
/proc/sys/kernel/pid_max as pid values are from 0 to value - 1.
This value determines the number of id digits needed by the caller id.
The PRINTK_CALLER field is printed as T<id> for a Task Id or C<id>
for a CPU Id for a printk in CPU context. The values are left space
padded and enclosed in parentheses such as: [    T123] or [     C16]

For consistency with dmesg -S which supports the PRINTK_CALLER field
the field is printed followed by a space. For JSON format output the
PRINTK_CALLER field is identified as caller as that is consistent with
it's naming in /dev/kmsg. No space padding is used to reduce space
consumed by the JSON output. So the output from the command on a system
with PRINTK_CALLER field enabled in the Linux .config file the dmesg
output appears as:

> dmesg
...
[  520.897104] [   T3919] usb 3-3: Product: USB 2.0 Hub

and

> dmesg -x
...
kern  :info  : [  520.897104] [   T3919] usb 3-3: Product: USB 2.0 Hub

and

> dmesg -J
...
      },{
         "pri": 6,
         "time":    520.897104,
         "caller": "T3919",
         "msg": "usb 3-3: Product: USB 2.0 Hub"
      },{

and

> dmesg -J -x
...
      },{
         "fac": "kern",
         "pri": "info",
         "time":   520.897104,
         "caller": "T3919",
         "msg": "usb 3-3: Product: USB 2.0 Hub"
      },{

>

For comparison:

> dmesg -S
...
[  520.897104] [ T3919] usb 3-3: Product: USB 2.0 Hub

and

> dmesg -S -x
...
kern  :info  : [  520.897104] [ T3919] usb 3-3: Product: USB 2.0 Hub

Note: When dmesg uses the old syslog interface the reserved space for
      the PRINTK_CALLER field is capped at 5 digits because 32-bit
      kernels are capped at 32768 as the max number of PIDs. However,
      64-bit systems are currently capped at 2^22 PIDs (0 - 4194303).
      The PID cap is set by PID_MAX_LIMIT but the system limit can be
      less so we use /proc/sys/kernel/pid_max to determine the size
      needed to hold the maximum PID value size for the current system.
      Many 64-bit systems support 2^22 PIDs (0 - 4194303) and you see:

> dmesg -x
...
kern  :info  : [  520.899558] [   T3919] hub 3-3:1.0: USB hub found
...
kern  :info  : [ 9830.456898] [  T98982] cgroup: fork rejected by pids ...
kern  :info  : [14301.158878] [ T137336] cgroup: fork rejected by pids ...
kern  :info  : [18980.803190] [T1637865] cgroup: fork rejected by pids ...

> dmesg -S -x
...
kern  :info  : [  520.899558] [ T3919] hub 3-3:1.0: USB hub found
...
kern  :info  : [ 9830.456898] [T98982] cgroup: fork rejected by pids ...
kern  :info  : [14301.158878] [T137336] cgroup: fork rejected by pids ...
kern  :info  : [18980.803190] [T1637865] cgroup: fork rejected by pids ...

This is the only difference seen with PRINTK_CALLER configured and
printing between the dmesg /dev/kmsg interface and the dmesg -S syslog
interface.

Signed-off-by: Ivan Delalande <colona@arista.com>
Signed-off-by: Edward Chron <echron@arista.com>
karelzak pushed a commit that referenced this issue Jan 23, 2024
Submission to Project: util-linux
Open Incident: #2609 at github.com//issues/2609
Component: util-linux/sys-utils
File: dmesg.c
Code level patch applied against: 2.39.3 - latest code pulled from
           git.github.com:util-linux/util-linux.git
Revision: #1 on 2023/12/08 per Review from Karel Zak
Revision: #2 on 2023/12/12 Adjust line offsets for master update and
                           Add caller_id_size init to dmesg -K
Revision: #3 on 2023/12/12 Use of sizeof for cidbuf and limit search
                           for caller_id to dmesg prefix to msg text
Revision: #4 on 2023/12/15 Ensure SYSLOG and kmsg inputs have
                           caller_id_size set appropriately
Revision: #5 on 2023/12/24 Make caller_id width consistent with
                           makedumpfile
Revision: #6 on 2023/12/30 Use updated test naming convention
Revision: #7 on 2024/01/04 Normalize kmsg caller_id spacing for test
                           platforms by removing caller_id padding
                           in test generated output.

Add support to standard dmesg command for the optional Linux Kernel
debug CONFIG option PRINTK_CALLER which adds an optional dmesg field
that contains the Thread Id or CPU Id that is issuing the printk to
add the message to the kernel ring buffer. This makes debugging simpler
as dmesg entries for a specific thread or CPU can be recognized.

The dmesg -S using the old syslog interface supports printing the
PRINTK_CALLER field but currently standard dmesg does not support
printing the field if present. There are utilities that use dmesg and
so it would be optimal if dmesg supported PRINTK_CALLER as well.

The additional field provided by PRINTK_CALLER is only present
if it was configured for the Linux kernel where the dmesg command
is run. It is a debug option and not configured by default so the
dmesg output will only change for those kernels where the option was
configured when the kernel was built. For users who went to the
trouble to configure PRINTK_CALLER and have the extra field available
for debugging, having dmesg print the field is very helpful.

Size of the PRINTK_CALLER field is determined by the maximum number
tasks that can be run on the system which is limited by the value of
/proc/sys/kernel/pid_max as pid values are from 0 to value - 1.
This value determines the number of id digits needed by the caller id.
The PRINTK_CALLER field is printed as T<id> for a Task Id or C<id>
for a CPU Id for a printk in CPU context. The values are left space
padded and enclosed in parentheses such as: [    T123] or [     C16]

For consistency with dmesg -S which supports the PRINTK_CALLER field
the field is printed followed by a space. For JSON format output the
PRINTK_CALLER field is identified as caller as that is consistent with
it's naming in /dev/kmsg. No space padding is used to reduce space
consumed by the JSON output. So the output from the command on a system
with PRINTK_CALLER field enabled in the Linux .config file the dmesg
output appears as:

> dmesg
...
[  520.897104] [   T3919] usb 3-3: Product: USB 2.0 Hub

and

> dmesg -x
...
kern  :info  : [  520.897104] [   T3919] usb 3-3: Product: USB 2.0 Hub

and

> dmesg -J
...
      },{
         "pri": 6,
         "time":    520.897104,
         "caller": "T3919",
         "msg": "usb 3-3: Product: USB 2.0 Hub"
      },{

and

> dmesg -J -x
...
      },{
         "fac": "kern",
         "pri": "info",
         "time":   520.897104,
         "caller": "T3919",
         "msg": "usb 3-3: Product: USB 2.0 Hub"
      },{

>

For comparison:

> dmesg -S
...
[  520.897104] [ T3919] usb 3-3: Product: USB 2.0 Hub

and

> dmesg -S -x
...
kern  :info  : [  520.897104] [ T3919] usb 3-3: Product: USB 2.0 Hub

Note: When dmesg uses the old syslog interface the reserved space for
      the PRINTK_CALLER field is capped at 5 digits because 32-bit
      kernels are capped at 32768 as the max number of PIDs. However,
      64-bit systems are currently capped at 2^22 PIDs (0 - 4194303).
      The PID cap is set by PID_MAX_LIMIT but the system limit can be
      less so we use /proc/sys/kernel/pid_max to determine the size
      needed to hold the maximum PID value size for the current system.
      Many 64-bit systems support 2^22 PIDs (0 - 4194303) and you see:

> dmesg -x
...
kern  :info  : [  520.899558] [   T3919] hub 3-3:1.0: USB hub found
...
kern  :info  : [ 9830.456898] [  T98982] cgroup: fork rejected by pids ...
kern  :info  : [14301.158878] [ T137336] cgroup: fork rejected by pids ...
kern  :info  : [18980.803190] [T1637865] cgroup: fork rejected by pids ...

> dmesg -S -x
...
kern  :info  : [  520.899558] [ T3919] hub 3-3:1.0: USB hub found
...
kern  :info  : [ 9830.456898] [T98982] cgroup: fork rejected by pids ...
kern  :info  : [14301.158878] [T137336] cgroup: fork rejected by pids ...
kern  :info  : [18980.803190] [T1637865] cgroup: fork rejected by pids ...

This is the only difference seen with PRINTK_CALLER configured and
printing between the dmesg /dev/kmsg interface and the dmesg -S syslog
interface.

Tests naming has been revised based on naming convention Thomas used to
introduce dmest json tests. The naming of test and input files that
reside in tests/ts/dmeg include:

<name> are existing dmesg syslog interface tests and input files.
cid-<name> are dmesg syslog interface caller_id tests and input files.
json-<name> are dmesg kmsg interface tests and input files.
cid-json-<name> are dmesg kmsg interface caller_id tests and input files.

Resulting expected files match the test names.

Signed-off-by: Ivan Delalande <colona@arista.com>
Signed-off-by: Edward Chron <echron@arista.com>
Signed-off-by: Karel Zak <kzak@redhat.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants