Ticket #3983 (closed defect: worksforme)
SIGBUS, Bus error in __memcmp_avx2_movbe (or __memcmp_sse2) when comparing two dirs(F9,c,c,T) that contain symlink to 0 byte file
Reported by: | howaboutsynergy | Owned by: | |
---|---|---|---|
Priority: | major | Milestone: | |
Component: | mc-core | Version: | master |
Keywords: | Cc: | howaboutsynergy@… | |
Blocked By: | #3960 | Blocking: | |
Branch state: | no branch | Votes for changeset: |
Description
What version of Midnight Commander is used?
$ LC_MESSAGES=C mc -V GNU Midnight Commander 4.8.22-130-ge1d11906b Built with GLib 2.60.1 Using the S-Lang library with terminfo database With builtin Editor With subshell support as default With support for background operations With mouse support on xterm With internationalization support With multiple codepages support Virtual File Systems: cpiofs, tarfs, sfs, extfs, ftpfs, sftpfs, fish Data types: char: 8; int: 32; long: 64; void *: 64; size_t: 64; off_t: 64;
$ LC_MESSAGES=C mc -F Home directory: /home/user Profile root directory: /home/user [System data] Config directory: /etc/mc/ Data directory: /usr/share/mc/ File extension handlers: /usr/lib/mc/ext.d/ VFS plugins and scripts: /usr/lib/mc/ extfs.d: /usr/lib/mc/extfs.d/ fish: /usr/lib/mc/fish/ [User data] Config directory: /home/user/.config/mc/ Data directory: /home/user/.local/share/mc/ skins: /home/user/.local/share/mc/skins/ extfs.d: /home/user/.local/share/mc/extfs.d/ fish: /home/user/.local/share/mc/fish/ mcedit macros: /home/user/.local/share/mc/mc.macros mcedit external macros: /home/user/.local/share/mc/mcedit/macros.d/macro.* Cache directory: /home/user/.cache/mc/
$ mc --configure-options '--prefix=/usr' '--sysconfdir=/etc' '--libexecdir=/usr/lib' '--enable-background' '--enable-network' '--enable-netcode' '--enable-charset' '--enable-nls' '--with-vfs' '--with-edit' '--with-screen=slang' '--without-x' '--without-samba' '--without-gpm-mouse' '--without-gnome' '--with-debug' '--without-included-gettext' '--disable-dependency-tracking' 'CFLAGS=-pipe -march=native -Wno-trigraphs -fno-schedule-insns2 -fno-delete-null-pointer-checks -mtune=native -fomit-frame-pointer -O2 -D_FORTIFY_SOURCE=2 -O2 -fbuiltin -ggdb3'
$ type mc mc is aliased to `. mc-wrapper.sh --nomouse --subshell --stickchars' $ type mc-wrapper.sh mc-wrapper.sh is /home/user/bin/mc-wrapper.sh $ which mc-wrapper.sh /home/user/bin/mc-wrapper.sh $ cat `which mc-wrapper.sh` MC_USER=`id | sed 's/[^(]*(//;s/).*//'` MC_PWD_FILE="${TMPDIR-/tmp}/mc-$MC_USER/mc.pwd.$$" /usr/bin/mc -P "$MC_PWD_FILE" "$@" if test -r "$MC_PWD_FILE"; then MC_PWD="`cat "$MC_PWD_FILE"`" if test -n "$MC_PWD" && test -d "$MC_PWD"; then cd "$MC_PWD" fi unset MC_PWD fi rm -f "$MC_PWD_FILE" unset MC_PWD_FILE unset MC_USER
$ coredumpctl -r|head -2 TIME PID UID GID SIG COREFILE EXE Mon 2019-05-06 13:36:45 CEST 13484 1000 1000 7 present /usr/bin/mc
Note: below I've redirected the gdb output into /tmp/a file because I don't have scrollback buffer via ssh (and haven't yet figured out how to get one):
$ coredumpctl gdb >/tmp/a GNU gdb (GDB) 8.2.1 Copyright (C) 2018 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-pc-linux-gnu". Type "show configuration" for configuration details. For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>. Find the GDB manual and other documentation resources online at: <http://www.gnu.org/software/gdb/documentation/>. For help, type "help". Type "apropos word" to search for commands related to "word"... Reading symbols from /usr/bin/mc...done. [New LWP 13484] [Thread debugging using libthread_db enabled] Using host libthread_db library "/usr/lib/libthread_db.so.1". Core was generated by `/usr/bin/mc -P /tmp/mc-user/mc.pwd.1908 --nomouse --subshell --stickchars'. Program terminated with signal SIGBUS, Bus error. #0 0x00007fcc3acba480 in __memcmp_avx2_movbe () from /usr/lib/libc.so.6 (gdb) bt #0 0x00007fcc3acba480 in __memcmp_avx2_movbe () from /usr/lib/libc.so.6 #1 0x000055a43a906808 in compare_files (size=29, vpath2=0x55a43ba32700, vpath1=0x55a43ba3f2c0) at cmd.c:238 #2 compare_dir (panel=0x55a43ba2c560, other=0x55a43ba33b70, mode=mode@entry=compare_thourough) at cmd.c:339 #3 0x000055a43a908042 in compare_dirs_cmd () at cmd.c:1165 #4 0x000055a43a8a9d05 in midnight_execute_cmd (sender=0x55a43ba22a00, command=109) at midnight.c:1115 #5 0x000055a43a8d903d in send_message (data=0x0, parm=<optimized out>, msg=MSG_ACTION, sender=0x55a43ba22a00, w=<optimized out>) at ../../lib/widget/widget-common.h:210 #6 menubar_execute (menubar=0x55a43ba22a00) at menu.c:345 #7 0x000055a43a8d9baa in menubar_handle_key (key=<optimized out>, menubar=0x55a43ba22a00) at menu.c:533 #8 menubar_callback (w=0x55a43ba22a00, sender=<optimized out>, msg=<optimized out>, parm=<optimized out>, data=<optimized out>) at menu.c:627 #9 0x000055a43a8925ca in send_message (data=0x0, parm=99, msg=MSG_HOTKEY, sender=0x0, w=0x55a43ba22a00) at ../../lib/widget/widget-common.h:210 #10 dlg_try_hotkey (h=0x55a43ba12210, h=0x55a43ba12210, d_key=99) at dialog.c:422 #11 dlg_key_event (d_key=99, h=0x55a43ba12210) at dialog.c:482 #12 dlg_process_event (h=0x55a43ba12210, key=99, event=<optimized out>) at dialog.c:1164 #13 0x000055a43a8928ab in frontend_dlg_run (h=0x55a43ba12210) at dialog.c:544 #14 dlg_run (h=0x55a43ba12210) at dialog.c:1197 #15 0x000055a43a8ab42c in do_nc () at midnight.c:1783 #16 0x000055a43a886504 in main (argc=<optimized out>, argv=<optimized out>) at main.c:409 (gdb) bt full #0 0x00007fcc3acba480 in __memcmp_avx2_movbe () from /usr/lib/libc.so.6 No symbol table info available. #1 0x000055a43a906808 in compare_files (size=29, vpath2=0x55a43ba32700, vpath1=0x55a43ba3f2c0) at cmd.c:238 data2 = 0x7fcc3b35f000 <error: Cannot access memory at address 0x7fcc3b35f000> data1 = 0x7fcc3b389000 <error: Cannot access memory at address 0x7fcc3b389000> file2 = <optimized out> file1 = <optimized out> result = -1 file1 = <optimized out> result = <optimized out> file2 = <optimized out> data1 = <optimized out> data2 = <optimized out> #2 compare_dir (panel=0x55a43ba2c560, other=0x55a43ba33b70, mode=mode@entry=compare_thourough) at cmd.c:339 src_name = 0x55a43ba3f2c0 dst_name = 0x55a43ba32700 target = <optimized out> source = <optimized out> i = 2 j = <optimized out> #3 0x000055a43a908042 in compare_dirs_cmd () at cmd.c:1165 choice = 2 thorough_flag = compare_thourough #4 0x000055a43a8a9d05 in midnight_execute_cmd (sender=0x55a43ba22a00, command=109) at midnight.c:1115 res = MSG_HANDLED #5 0x000055a43a8d903d in send_message (data=0x0, parm=<optimized out>, msg=MSG_ACTION, sender=0x55a43ba22a00, w=<optimized out>) at ../../lib/widget/widget-common.h:210 ret = MSG_NOT_HANDLED ret = <optimized out> #6 menubar_execute (menubar=0x55a43ba22a00) at menu.c:345 w = 0x55a43ba22a00 menu = <optimized out> entry = 0x55a43ba0fe10 #7 0x000055a43a8d9baa in menubar_handle_key (key=<optimized out>, menubar=0x55a43ba22a00) at menu.c:533 entry = <optimized out> menu = 0x55a43ba21170 i = 0x55a43ba0c560 = {0x55a43ba0fe10, 0x55a43ba0feb0, 0x55a43ba0ff50, 0x55a43ba0fff0, 0x0, 0x55a43ba10090, 0x55a43ba10130, 0x55a43ba20e50, 0x55a43ba20ef0, 0x55a43ba20f90, 0x0, 0x55a43ba21030, 0x55a43ba210d0, 0x55a43ba0fa00} #8 menubar_callback (w=0x55a43ba22a00, sender=<optimized out>, msg=<optimized out>, parm=<optimized out>, data=<optimized out>) at menu.c:627 menubar = 0x55a43ba22a00 #9 0x000055a43a8925ca in send_message (data=0x0, parm=99, msg=MSG_HOTKEY, sender=0x0, w=0x55a43ba22a00) at ../../lib/widget/widget-common.h:210 ret = MSG_NOT_HANDLED ret = <optimized out> #10 dlg_try_hotkey (h=0x55a43ba12210, h=0x55a43ba12210, d_key=99) at dialog.c:422 hot_cur = <optimized out> current = 0x55a43ba22a00 handled = MSG_NOT_HANDLED c = 99 hot_cur = <optimized out> current = <optimized out> handled = <optimized out> c = <optimized out> #11 dlg_key_event (d_key=99, h=0x55a43ba12210) at dialog.c:482 handled = <optimized out> handled = <optimized out> #12 dlg_process_event (h=0x55a43ba12210, key=99, event=<optimized out>) at dialog.c:1164 No locals. #13 0x000055a43a8928ab in frontend_dlg_run (h=0x55a43ba12210) at dialog.c:544 d_key = <optimized out> wh = 0x55a43ba12210 event = {buttons = 0, x = -1, y = 982048309, type = (GPM_DOWN | GPM_DOUBLE | GPM_MFLAG | GPM_HARD | unknown: 21504)} wh = <optimized out> event = <optimized out> d_key = <optimized out> #14 dlg_run (h=0x55a43ba12210) at dialog.c:1197 No locals. #15 0x000055a43a8ab42c in do_nc () at midnight.c:1783 ret = <optimized out> #16 0x000055a43a886504 in main (argc=<optimized out>, argv=<optimized out>) at main.c:409 mcerror = 0x0 config_migrated = 0 config_migrate_msg = 0x0 exit_code = 1 (gdb) q PID: 13484 (mc) UID: 1000 (user) GID: 1000 (user) Signal: 7 (BUS) Timestamp: Mon 2019-05-06 13:36:45 CEST (11min ago) Command Line: /usr/bin/mc -P /tmp/mc-user/mc.pwd.1908 --nomouse --subshell --stickchars Executable: /usr/bin/mc Control Group: /system.slice/sshd.service Unit: sshd.service Slice: system.slice Boot ID: 85b887fbf341469ea4a8be2dd78878ac Machine ID: 5767ef25f523419aaa049f3d74481940 Hostname: i87k Storage: /var/lib/systemd/coredump/core.mc.1000.85b887fbf341469ea4a8be2dd78878ac.13484.1557142605000000 Message: Process 13484 (mc) of user 1000 dumped core. Stack trace of thread 13484: #0 0x00007fcc3acba480 __memcmp_avx2_movbe (libc.so.6) #1 0x000055a43a906808 compare_files (mc) #2 0x000055a43a908042 compare_dirs_cmd (mc) #3 0x000055a43a8a9d05 midnight_execute_cmd (mc) #4 0x000055a43a8d903d send_message (mc) #5 0x000055a43a8d9baa menubar_handle_key (mc) #6 0x000055a43a8925ca send_message (mc) #7 0x000055a43a8928ab frontend_dlg_run (mc) #8 0x000055a43a8ab42c do_nc (mc) #9 0x000055a43a886504 main (mc) #10 0x00007fcc3ab83ce3 __libc_start_main (libc.so.6) #11 0x000055a43a88666e _start (mc)
What steps will reproduce the problem?
Attached directory structure and files for reproduction purposes:
- chdir into /home/user/TODO/coredump_mc/leftdir/mc on the left panel
- chdir into /home/user/TODO/coredump_mc/rightdir/mc on the right panel
- then do F9, c, c, T to compare the dirs and crash
The above stacktrace was on an Intel i8700k CPU desktop PC(has avx and avx2), the below one is on an Ideapad Z575 laptop with AMD A6-3400M APU with Radeon(tm) HD Graphics CPU (it doesn't have avx):
$ coredumpctl gdb PID: 31065 (mc) UID: 1000 (user) GID: 1000 (user) Signal: 7 (BUS) Timestamp: Mon 2019-05-06 14:00:12 CEST (1min 34s ago) Command Line: /usr/bin/mc -P /tmp/mc-user/mc.pwd.25438 --nomouse --subshell --stickchars Executable: /usr/bin/mc Control Group: /user.slice/user-1000.slice/session-c1.scope Unit: session-c1.scope Slice: user-1000.slice Session: c1 Owner UID: 1000 (user) Boot ID: dfe6cd331478451b8c6522386e636e51 Machine ID: ac27e28ecb9e47208f622bcf7f772c6b Hostname: Z575 Storage: /var/lib/systemd/coredump/core.mc.1000.dfe6cd331478451b8c6522386e636e51.31065.1557144012000000 Message: Process 31065 (mc) of user 1000 dumped core. Stack trace of thread 31065: #0 0x00007f93b4764100 __memcmp_sse2 (libc.so.6) #1 0x0000564da47c0527 compare_files (mc) #2 0x0000564da476191d midnight_execute_cmd (mc) #3 0x0000564da479231d send_message (mc) #4 0x0000564da4792eda menubar_handle_key (mc) #5 0x0000564da4749b14 send_message (mc) #6 0x0000564da4749df9 frontend_dlg_run (mc) #7 0x0000564da4762fec do_nc (mc) #8 0x0000564da473d53c main (mc) #9 0x00007f93b46effce __libc_start_main (libc.so.6) #10 0x0000564da473d6be _start (mc) GNU gdb (GDB) 8.2.1 Copyright (C) 2018 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-pc-linux-gnu". Type "show configuration" for configuration details. For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>. Find the GDB manual and other documentation resources online at: <http://www.gnu.org/software/gdb/documentation/>. For help, type "help". Type "apropos word" to search for commands related to "word"... Reading symbols from /usr/bin/mc...done. [New LWP 31065] [Thread debugging using libthread_db enabled] Using host libthread_db library "/usr/lib/libthread_db.so.1". Core was generated by `/usr/bin/mc -P /tmp/mc-user/mc.pwd.25438 --nomouse --subshell --stickchars'. Program terminated with signal SIGBUS, Bus error. #0 __memcmp_sse2 () at ../sysdeps/x86_64/memcmp.S:40 40 ../sysdeps/x86_64/memcmp.S: No such file or directory. (gdb) bt #0 __memcmp_sse2 () at ../sysdeps/x86_64/memcmp.S:40 #1 0x0000564da47c0527 in compare_files (size=29, vpath2=0x564da4e0fe70, vpath1=0x564da4e13880) at cmd.c:238 #2 compare_dir (panel=0x564da4e0d500, other=0x564da4e0e8b0, mode=compare_thourough) at cmd.c:339 #3 0x0000564da47c1e18 in compare_dirs_cmd () at cmd.c:1166 #4 0x0000564da476191d in midnight_execute_cmd (sender=0x564da4dff080, command=109) at midnight.c:1115 #5 0x0000564da479231d in send_message (data=0x0, parm=<optimized out>, msg=MSG_ACTION, sender=0x564da4dff080, w=<optimized out>) at ../../lib/widget/widget-common.h:210 #6 menubar_execute (menubar=0x564da4dff080) at menu.c:345 #7 0x0000564da4792eda in menubar_handle_key (key=<optimized out>, menubar=0x564da4dff080) at menu.c:533 #8 menubar_callback (w=0x564da4dff080, sender=<optimized out>, msg=<optimized out>, parm=<optimized out>, data=<optimized out>) at menu.c:627 #9 0x0000564da4749b14 in send_message (data=0x0, parm=99, msg=MSG_HOTKEY, sender=0x0, w=0x564da4dff080) at ../../lib/widget/widget-common.h:210 #10 dlg_try_hotkey (h=0x564da4df2000, h=0x564da4df2000, d_key=99) at dialog.c:422 #11 dlg_key_event (d_key=99, h=0x564da4df2000) at dialog.c:482 #12 dlg_process_event (h=0x564da4df2000, key=99, event=<optimized out>) --Type <RET> for more, q to quit, c to continue without paging--c at dialog.c:1164 #13 0x0000564da4749df9 in frontend_dlg_run (h=0x564da4df2000) at dialog.c:544 #14 dlg_run (h=0x564da4df2000) at dialog.c:1197 #15 0x0000564da4762fec in do_nc () at midnight.c:1783 #16 0x0000564da473d53c in main (argc=<optimized out>, argv=<optimized out>) at main.c:409 (gdb) bt full #0 __memcmp_sse2 () at ../sysdeps/x86_64/memcmp.S:40 No locals. #1 0x0000564da47c0527 in compare_files (size=29, vpath2=0x564da4e0fe70, vpath1=0x564da4e13880) at cmd.c:238 data2 = 0x7f93b4f05000 <error: Cannot access memory at address 0x7f93b4f05000> data1 = <optimized out> file2 = <optimized out> file1 = <optimized out> result = -1 file1 = <optimized out> result = <optimized out> file2 = <optimized out> data1 = <optimized out> data2 = <optimized out> #2 compare_dir (panel=0x564da4e0d500, other=0x564da4e0e8b0, mode=compare_thourough) at cmd.c:339 src_name = 0x564da4e13880 dst_name = 0x564da4e0fe70 target = <optimized out> source = <optimized out> i = 2 j = <optimized out> --Type <RET> for more, q to quit, c to continue without paging--c #3 0x0000564da47c1e18 in compare_dirs_cmd () at cmd.c:1166 choice = <optimized out> thorough_flag = <optimized out> #4 0x0000564da476191d in midnight_execute_cmd (sender=0x564da4dff080, command=109) at midnight.c:1115 res = MSG_HANDLED #5 0x0000564da479231d in send_message (data=0x0, parm=<optimized out>, msg=MSG_ACTION, sender=0x564da4dff080, w=<optimized out>) at ../../lib/widget/widget-common.h:210 ret = MSG_NOT_HANDLED ret = <optimized out> #6 menubar_execute (menubar=0x564da4dff080) at menu.c:345 w = 0x564da4dff080 menu = <optimized out> entry = 0x564da4dfd8a0 #7 0x0000564da4792eda in menubar_handle_key (key=<optimized out>, menubar=0x564da4dff080) at menu.c:533 entry = <optimized out> menu = 0x564da4df2460 i = 0x564da4ded160 = {0x564da4dfd8a0, 0x564da4dfd940, 0x564da4df4b90, 0x564da4df4c30, 0x0, 0x564da4df4cd0, 0x564da4df4d70, 0x564da4df4e10, 0x564da4df05f0, 0x564da4df0690, 0x0, 0x564da4df0730, 0x564da4df07d0, 0x564da4df0870} #8 menubar_callback (w=0x564da4dff080, sender=<optimized out>, msg=<optimized out>, parm=<optimized out>, data=<optimized out>) at menu.c:627 menubar = 0x564da4dff080 #9 0x0000564da4749b14 in send_message (data=0x0, parm=99, msg=MSG_HOTKEY, sender=0x0, w=0x564da4dff080) at ../../lib/widget/widget-common.h:210 ret = MSG_NOT_HANDLED ret = <optimized out> #10 dlg_try_hotkey (h=0x564da4df2000, h=0x564da4df2000, d_key=99) at dialog.c:422 hot_cur = <optimized out> current = 0x564da4dff080 handled = MSG_NOT_HANDLED c = 99 hot_cur = <optimized out> current = <optimized out> handled = <optimized out> c = <optimized out> #11 dlg_key_event (d_key=99, h=0x564da4df2000) at dialog.c:482 handled = <optimized out> handled = <optimized out> #12 dlg_process_event (h=0x564da4df2000, key=99, event=<optimized out>) at dialog.c:1164 No locals. #13 0x0000564da4749df9 in frontend_dlg_run (h=0x564da4df2000) at dialog.c:544 d_key = <optimized out> wh = 0x564da4df2000 event = {buttons = -1528805856, x = -1, y = -1534984512, type = (GPM_MOVE | GPM_DOWN | GPM_UP | GPM_TRIPLE | unknown: 22016)} wh = <optimized out> event = <optimized out> d_key = <optimized out> #14 dlg_run (h=0x564da4df2000) at dialog.c:1197 No locals. #15 0x0000564da4762fec in do_nc () at midnight.c:1783 ret = <optimized out> #16 0x0000564da473d53c in main (argc=<optimized out>, argv=<optimized out>) at main.c:409 mcerror = 0x0 config_migrated = 0 config_migrate_msg = 0x0 exit_code = 1 (gdb) q
Attachments
Change History
comment:1 Changed 6 years ago by howaboutsynergy
oh I just realized that I was also applying a bunch of other patches on top of master. I'm including them here also, but let me know if you want me to try it without the patches... hopefully they are irrelevant to the issue.
Changed 6 years ago by howaboutsynergy
- Attachment fix_the_sometimes_truncated_shell_output_in_mc.patch added
comment:2 Changed 6 years ago by howaboutsynergy
Simplified reproduction steps to: one dir containing a symlink(absolute or relative) to a 0 byte file, then F9,c,c,t
ie.
- cd /tmp
- mkdir 3
- cd 3
- touch newemptyfile
- mkdir leftright
- cd leftright && ln -rs ../newemptyfile
- now enter mc and ensure both panels are inside dir leftright then press F9,c,c,t
comment:3 Changed 6 years ago by howaboutsynergy
- Cc howaboutsynergy@… added
- Summary changed from SIGBUS, Bus error in __memcmp_avx2_movbe (or __memcmp_sse2) when comparing two dirs (F9,c,c,T) to SIGBUS, Bus error in __memcmp_avx2_movbe (or __memcmp_sse2) when comparing two dirs(F9,c,c,T) that contain symlink to 0 byte file
comment:4 Changed 6 years ago by andrew_b
Thanks! But most patches are not matched to ticket topic. Please create separate tickets or attach simple patches to #3955.
Also please format your patches accordingly our coding style.
comment:5 Changed 6 years ago by howaboutsynergy
Ah, sorry for the confusion. Please ignore the patches!
The only reason I added them was because of https://midnight-commander.org/ticket/3983#comment:1 ie. because I thought that they might be needed to reproduce this issue (because I had them applied on master when I encountered this bug, and I forgot that I had them - I know that I should've tested master without any patches). But I can kinda see now that they have no effect on this issue, so they should be ignored! I don't know how to delete them from here.
comment:6 Changed 6 years ago by howaboutsynergy
actually all attachments should be deleted because there are simpler reproduction steps in https://midnight-commander.org/ticket/3983#comment:2 and thus dirs_for_F9_c_c_t.tar.xz is not needed either.
comment:7 Changed 6 years ago by howaboutsynergy
ok this isn't a mc bug, it's a <mmap-ing a symlink that points to 0 byte file> bug. It works if file is more than 0 bytes in length. Else, accessing the first byte of the resulting mmap causes the crash! In other words, mmap yields a 0 byte sized mmap which seems like a bug in mmap especially since the manual says:
The length argument specifies the length of the mapping (which must be greater than 0).
which is clearly trying to avoid exactly this type of situation (0 byte sized mmap result ie. addr[0] will SIGBUS error)
But mc could temporarily mitigate by adding O_NOFOLLOW to prevent this crash, though then comparing the same symlinks in the same dir, it will show them as different.
non-mc repro. code:
#include <sys/types.h> #include <sys/stat.h> #define __USE_XOPEN2K8 1 //to get O_NOFOLLOW #include <fcntl.h> #include <unistd.h> // close #include <stdio.h> //printf #define __USE_MISC 1 //to get MAP_FILE #include <sys/mman.h> //mmap #include <stdlib.h> #include <bits/mman-linux.h> // MAP_FILE #include <string.h> // memcmp int main() { int file; off_t size=12; file = open("./3/symlink_to_emptyfile", O_RDONLY // | O_NOFOLLOW //open will fail since the file is a symlink! 12 bytes symlink ); if (file >= 0) { printf("!! open success\n"); char *addr; addr = mmap (0, size, PROT_READ, MAP_FILE | MAP_PRIVATE, file, 0); if (addr != MAP_FAILED){ printf("!! mmap ok\n"); printf("!! 1st byte of mmap: %c\n", addr[0]); munmap(addr, size); } } else { printf("!! open failed\n"); } close(file); return 0; }
Program terminated with signal SIGBUS, Bus error. #0 0x0000561126fa0216 in main () at b.c:28 28 printf("!! 1st byte of mmap: %c\n", addr[0]); (gdb) bt full #0 0x0000561126fa0216 in main () at b.c:28 addr = 0x7fdce7d5f000 <error: Cannot access memory at address 0x7fdce7d5f000> file = 3 size = 12
./3/symlink_to_emptyfile is a symlink to ../emptyfile which is a 0 byte file.
(it works if it's a 1 byte file, for example)
That being said, mc is using size of symlink but comparing contents of files the symlink points to. Otherwise, if mc were using the size of the file that the symlink points to, then it wouldn't even mmap anything and thus not reach the crash.
So there are two bugs here that could be squashed by using the correct size.
comment:8 Changed 6 years ago by howaboutsynergy
made mmap issue here: https://bugzilla.kernel.org/show_bug.cgi?id=203537
comment:9 Changed 6 years ago by howaboutsynergy
Ok, it looks like it's not a mmap bug, because it acts like a truncated file from offset 0, thus accessing that memory will SIGBUS, according to man 2 mmap:
SIGBUS Attempted access to a portion of the buffer that does not correspond to the file (for example, beyond the end of the file, including the case where another process has truncated the file).
So then it's up to mc to check if the file that the symlink points to is 0 bytes and if so, not mmap.
ie. Currently, just changing the size used to be size of the file that the symlink points to instead of size of the symlink, would fix this issue and the other issue mentioned in my prev. comment where only the first X bytes of the the file contents get compared (X is size of symlink, eg. le PATH_MAX)
comment:10 follow-up: ↓ 11 Changed 6 years ago by howaboutsynergy
There is a better workaround for this. Replacing #ifdef HAVE_MMAP with #if 0 in function compare_files in file src/filemanager/cmd.c
This is a better workaround than using MMAP with O_NOFOLLOW in (both) open function calls.
But I'm still interested in a proper fix for this, which means it would have to handle a bunch of cases concerning symlinks and normal files being compared... Looks like I'd have to ensure they are being tested inside ./tests/src/filemanager to match the location of cmd.c.
Any hints are welcome, meanwhile I'm looking into it. Cheers! ;)
comment:11 in reply to: ↑ 10 ; follow-up: ↓ 12 Changed 6 years ago by andrew_b
Replying to howaboutsynergy:
There is a better workaround for this. Replacing #ifdef HAVE_MMAP with #if 0 in function compare_files in file src/filemanager/cmd.c
Just configure --with-mmap=no.
comment:12 in reply to: ↑ 11 Changed 6 years ago by howaboutsynergy
Replying to andrew_b:
Replying to howaboutsynergy:
There is a better workaround for this. Replacing #ifdef HAVE_MMAP with #if 0 in function compare_files in file src/filemanager/cmd.c
Just configure --with-mmap=no.
Thanks. I didn't know about that.
Looks like there's only one other use of mmap:
src/vfs/smbfs/helpers/include/local.h:116:/* if mmap is enabled, then this is the maximum size of file to use src/vfs/smbfs/helpers/include/local.h:117: the mmap code on. We don't want to mmap huge files as virtual intl/gettextP.h:163: /* 1 if the memory is mmap()ed, 0 if the memory is malloc()ed. */ intl/gettextP.h:165: /* Size of mmap()ed memory. */ intl/loadmsgcat.c:471:# define mmap(addr, len, prot, flags, fd, offset) \ intl/loadmsgcat.c:845: /* Now we are ready to load the file. If mmap() is available we try intl/loadmsgcat.c:847: data = (struct mo_file_header *) mmap (NULL, size, PROT_READ, intl/loadmsgcat.c:852: /* mmap() call was successful. */ intl/loadmsgcat.c:859: /* If the data is not yet available (i.e. mmap'ed) we try to load intl/xsize.h:41: implementation that uses mmap --, it's recommended to use size_overflow_p()
Meanwhile, I think I can get some inspiration from exec_get_export_variables_ext.c on how to do the file comparison tests...
*by file comparison tests I mean calling compare_dir function from src/filemanager/cmd.c
comment:13 follow-up: ↓ 14 Changed 6 years ago by howaboutsynergy
before I get too deep into this, do you require real/full name before accepting patches? I ask because I see full names of the people at the top of the source files.
EDIT: I'm still messing around with check see the Details block in this https://github.com/libcheck/check/issues/187#issue-444185772
comment:14 in reply to: ↑ 13 ; follow-up: ↓ 15 Changed 6 years ago by andrew_b
Replying to howaboutsynergy:
do you require real/full name before accepting patches?
No. This is desirable but not required.
comment:15 in reply to: ↑ 14 Changed 6 years ago by howaboutsynergy
Replying to andrew_b:
Replying to howaboutsynergy:
do you require real/full name before accepting patches?
No. This is desirable but not required.
Awesome!
Here's an unrelated thing that I found and I think that maybe mc can fix, related to tests:
https://midnight-commander.org/ticket/3986
comment:17 Changed 7 weeks ago by zaytsev
- Status changed from new to closed
- Resolution set to worksforme
- Milestone Future Releases deleted
I have removed mmap support in #3960, so this ticket can now be closed.