Ticket #3567 (closed defect: fixed)

Opened 4 years ago

Last modified 4 years ago

[PATCH] fix heap-use-after-free bug when accessing already freed widget object

Reported by: and Owned by:
Priority: major Milestone: 4.8.16
Component: mc-core Version: master
Keywords: Cc:
Blocked By: Blocking:
Branch state: no branch Votes for changeset: committed-master

Description

heap-use-after-free hits by accessing mc listing mode

accessing widget object (at g_array_index loop) which was freed
already (item->quick_widget->u.input.label before at loop)

found by Clang/AddressSanitizer?

ERROR: AddressSanitizer: heap-use-after-free on address 0x60800000aaa0 at pc 0x7fcaad33ef39 bp 0x7ffc752eabd0 sp 0x7ffc752eabc8
READ of size 4 at 0x60800000aaa0 thread T0
    #0 0x7fcaad33ef38 in quick_dialog_skip /tmp/portage/app-misc/mc-9999/work/mc-9999/lib/widget/quick.c:615:33
    #1 0x5e3434 in panel_listing_box /tmp/portage/app-misc/mc-9999/work/mc-9999/src/filemanager/boxes.c:831:13
    #2 0x5f5630 in change_listing_cmd /tmp/portage/app-misc/mc-9999/work/mc-9999/src/filemanager/cmd.c:1656:17
    #3 0x52f55d in midnight_execute_cmd /tmp/portage/app-misc/mc-9999/work/mc-9999/src/filemanager/midnight.c:1113:9
    #4 0x7fcaad339319 in menubar_execute /tmp/portage/app-misc/mc-9999/work/mc-9999/lib/widget/menu.c:341:9
    #5 0x7fcaad337962 in menubar_handle_key /tmp/portage/app-misc/mc-9999/work/mc-9999/lib/widget/menu.c:539:13
    #6 0x7fcaad3359c0 in menubar_callback /tmp/portage/app-misc/mc-9999/work/mc-9999/lib/widget/menu.c:597:13
    #7 0x7fcaad31f5a3 in dlg_try_hotkey /tmp/portage/app-misc/mc-9999/work/mc-9999/lib/widget/dialog.c:450:19
    #8 0x7fcaad31e950 in dlg_key_event /tmp/portage/app-misc/mc-9999/work/mc-9999/lib/widget/dialog.c:509:19
    #9 0x7fcaad31ee12 in frontend_dlg_run /tmp/portage/app-misc/mc-9999/work/mc-9999/lib/widget/dialog.c:570:9
    #10 0x7fcaad31eb15 in dlg_run /tmp/portage/app-misc/mc-9999/work/mc-9999/lib/widget/dialog.c:1267:5
    #11 0x52d8dd in do_nc /tmp/portage/app-misc/mc-9999/work/mc-9999/src/filemanager/midnight.c:1757:9
    #12 0x4fb287 in main /tmp/portage/app-misc/mc-9999/work/mc-9999/src/main.c:463:21
    #13 0x7fcaab72d9e3 in __libc_start_main (/lib64/libc.so.6+0x209e3)
    #14 0x427248 in _start (/tmp/portage/app-misc/mc-9999/work/mc-9999/src/.libs/mc+0x427248)

0x60800000aaa0 is located 0 bytes inside of 88-byte region [0x60800000aaa0,0x60800000aaf8)
freed by thread T0 here:
    #0 0x4c9a58 in __interceptor_free (/tmp/portage/app-misc/mc-9999/work/mc-9999/src/.libs/mc+0x4c9a58)
    #1 0x7fcaad33e3e7 in quick_dialog_skip /tmp/portage/app-misc/mc-9999/work/mc-9999/lib/widget/quick.c:616:13
    #2 0x5e3434 in panel_listing_box /tmp/portage/app-misc/mc-9999/work/mc-9999/src/filemanager/boxes.c:831:13
    #3 0x5f5630 in change_listing_cmd /tmp/portage/app-misc/mc-9999/work/mc-9999/src/filemanager/cmd.c:1656:17
    #4 0x52f55d in midnight_execute_cmd /tmp/portage/app-misc/mc-9999/work/mc-9999/src/filemanager/midnight.c:1113:9
    #5 0x7fcaad339319 in menubar_execute /tmp/portage/app-misc/mc-9999/work/mc-9999/lib/widget/menu.c:341:9
    #6 0x7fcaad337962 in menubar_handle_key /tmp/portage/app-misc/mc-9999/work/mc-9999/lib/widget/menu.c:539:13
    #7 0x7fcaad3359c0 in menubar_callback /tmp/portage/app-misc/mc-9999/work/mc-9999/lib/widget/menu.c:597:13
    #8 0x7fcaad31f5a3 in dlg_try_hotkey /tmp/portage/app-misc/mc-9999/work/mc-9999/lib/widget/dialog.c:450:19
    #9 0x7fcaad31e950 in dlg_key_event /tmp/portage/app-misc/mc-9999/work/mc-9999/lib/widget/dialog.c:509:19
    #10 0x7fcaad31ee12 in frontend_dlg_run /tmp/portage/app-misc/mc-9999/work/mc-9999/lib/widget/dialog.c:570:9
    #11 0x7fcaad31eb15 in dlg_run /tmp/portage/app-misc/mc-9999/work/mc-9999/lib/widget/dialog.c:1267:5
    #12 0x52d8dd in do_nc /tmp/portage/app-misc/mc-9999/work/mc-9999/src/filemanager/midnight.c:1757:9
    #13 0x4fb287 in main /tmp/portage/app-misc/mc-9999/work/mc-9999/src/main.c:463:21
    #14 0x7fcaab72d9e3 in __libc_start_main (/lib64/libc.so.6+0x209e3)
    #15 0x427248 in _start (/tmp/portage/app-misc/mc-9999/work/mc-9999/src/.libs/mc+0x427248)

previously allocated by thread T0 here:
    #0 0x4c9ef0 in calloc (/tmp/portage/app-misc/mc-9999/work/mc-9999/src/.libs/mc+0x4c9ef0)
    #1 0x7fcaac65a51c in g_malloc0 (/usr/lib64/libglib-2.0.so.0+0x6651c)
    #2 0x7fcaad33f02e in quick_create_labeled_input /tmp/portage/app-misc/mc-9999/work/mc-9999/lib/widget/quick.c:90:26
    #3 0x7fcaad33b076 in quick_dialog_skip /tmp/portage/app-misc/mc-9999/work/mc-9999/lib/widget/quick.c:238:17
    #4 0x5e3434 in panel_listing_box /tmp/portage/app-misc/mc-9999/work/mc-9999/src/filemanager/boxes.c:831:13
    #5 0x5f5630 in change_listing_cmd /tmp/portage/app-misc/mc-9999/work/mc-9999/src/filemanager/cmd.c:1656:17
    #6 0x52f55d in midnight_execute_cmd /tmp/portage/app-misc/mc-9999/work/mc-9999/src/filemanager/midnight.c:1113:9
    #7 0x7fcaad339319 in menubar_execute /tmp/portage/app-misc/mc-9999/work/mc-9999/lib/widget/menu.c:341:9
    #8 0x7fcaad337962 in menubar_handle_key /tmp/portage/app-misc/mc-9999/work/mc-9999/lib/widget/menu.c:539:13
    #9 0x7fcaad3359c0 in menubar_callback /tmp/portage/app-misc/mc-9999/work/mc-9999/lib/widget/menu.c:597:13
    #10 0x7fcaad31f5a3 in dlg_try_hotkey /tmp/portage/app-misc/mc-9999/work/mc-9999/lib/widget/dialog.c:450:19
    #11 0x7fcaad31e950 in dlg_key_event /tmp/portage/app-misc/mc-9999/work/mc-9999/lib/widget/dialog.c:509:19
    #12 0x7fcaad31ee12 in frontend_dlg_run /tmp/portage/app-misc/mc-9999/work/mc-9999/lib/widget/dialog.c:570:9
    #13 0x7fcaad31eb15 in dlg_run /tmp/portage/app-misc/mc-9999/work/mc-9999/lib/widget/dialog.c:1267:5
    #14 0x52d8dd in do_nc /tmp/portage/app-misc/mc-9999/work/mc-9999/src/filemanager/midnight.c:1757:9
    #15 0x4fb287 in main /tmp/portage/app-misc/mc-9999/work/mc-9999/src/main.c:463:21
    #16 0x7fcaab72d9e3 in __libc_start_main (/lib64/libc.so.6+0x209e3)
    #17 0x427248 in _start (/tmp/portage/app-misc/mc-9999/work/mc-9999/src/.libs/mc+0x427248)

SUMMARY: AddressSanitizer: heap-use-after-free /tmp/portage/app-misc/mc-9999/work/mc-9999/lib/widget/quick.c:615:33 in quick_dialog_skip

Signed-off-by: Andreas Mohr <and@…>

Attachments

mc-3567-fix-heap-use-after-free-bug-widget-object.patch (7.0 KB) - added by and 4 years ago.
mc-3567-fix-heap-use-after-free-bug-widget-object.2.patch (10.6 KB) - added by and 4 years ago.
mc-3567-fix-heap-use-after-free-bug-widget-object-v5.patch (7.7 KB) - added by and 4 years ago.
mc-3567-fix-memleak-at-configure_panel_listing.patch (2.8 KB) - added by and 4 years ago.
additional memleak fix
mc-3567-fix-heap-use-after-free-bug-widget-object-v6.patch (7.8 KB) - added by mooffie 4 years ago.
Same as "v5" but with comments tweaked.
0001-configure_panel_listing-fix-memory-leak.patch (2.1 KB) - added by andrew_b 4 years ago.

Change History

comment:1 Changed 4 years ago by andrew_b

Patch is dirty.

  1. Mix of code and declaration is used.
  2. C++-style comment is used.
  3. g_list_append is worse than g_list_prepend in this case.
  4. g_list_free_full should be used to delete list and data.

comment:2 follow-up: ↓ 3 Changed 4 years ago by and

Thanks andrew, comments addressed in new patch version.

comment:3 in reply to: ↑ 2 Changed 4 years ago by andrew_b

Replying to and:

Comments addressed in new patch version.

Mix of code and declaration is still there. Please be careful.

comment:4 Changed 4 years ago by and

fixed in v3

By the way I found more memleaks, should I create new tickets each
or do your want to create a metaticket for that stuff
where I will attach fix memleak patches for review?

I have no problem with create new ticket each.

comment:5 Changed 4 years ago by mooffie

I've read the code and the solution is fine.

I think a less cryptic (and less wrong) comment would be preferable. What about "Prevent heap-use-after-free: the label may follow, not precede, its quick input in the 'widgets' array. So we just mark it." ? Or, shorter, "Prevent heap-use-after-free: we may yet to encounter the label in this 'widgets' array." I prefer the former.

comment:6 Changed 4 years ago by mooffie

(An alternative solution is to tweak quick_create_labeled_input() to always add the 'label' before the 'input'. But in the future we may forget about the significance of this order and re-introduce the bug.)

comment:7 Changed 4 years ago by mooffie

Another way to write this patch is to call g_list_prepend (removelist, ...) right after the call to quick_create_labeled_input. Then we'll be able to delete the whole loop at the end. Saves code. For clarity we could name this list heap_allocated_quick_widgets instead of removelist.

comment:8 follow-up: ↓ 12 Changed 4 years ago by zaytsev

How about attaching a cleaner patch? ;-)

comment:9 follow-up: ↓ 10 Changed 4 years ago by and

thanks mooffie, your suggestion is even smarter

v4 patch attached plus fix for a second memleak in this context
(quick widget u.input.result can hold strdup value too, yet never freed neither needed)

comment:10 in reply to: ↑ 9 Changed 4 years ago by mooffie

Replying to and:

v4 patch attached plus fix for a second memleak in this context


This "fix" prevents dialogs from extracting data from QUICK_INPUT() inputs. E.g., the "Select" and "Unselect" dialogs (+ and - keys) no longer work.

(quick widget u.input.result can hold strdup value too, yet never freed neither needed)


I don't quite understand.

==

Another thing:

How about changing:

GList *heap_allocated_quick_widgets = NULL; 

to:

GList *extra_quick_widgets = NULL; /* Widgets not directly requested by the user. */

I think it'd be clearer. The name I suggested earlier was awful.

Changed 4 years ago by and

additional memleak fix

comment:11 Changed 4 years ago by and

My bad, I tested only "listing mode" where I hit heap+memleak bug
Reverse wrong second memleak fix from heap bugfix
and attach two separate files with proper memleak fix, I think.

Changed 4 years ago by mooffie

Same as "v5" but with comments tweaked.

comment:12 in reply to: ↑ 8 Changed 4 years ago by mooffie

Replying to zaytsev:

How about attaching a cleaner patch? ;-)

"v6" looks fine to me.

comment:13 follow-up: ↓ 15 Changed 4 years ago by mooffie

As for mc-3567-fix-memleak-at-configure_panel_listing.patch :

I think it'd be nicer if configure_panel_listing() didn't g_free() any of its arguments: it'd g_strdup() them. The code calling this function (one such place) would g_free() them.

But that's just my personal opinion. Maybe cmd.c already has some convention for such cases. We see that set_panel_filter_to() does use its argument directly --but it prefixes its name with "allocated_" to inform the user of this.

comment:14 Changed 4 years ago by andrew_b

  • Blocked By 3547 added

mc-3567-fix-heap-use-after-free-bug-widget-object-v6.patch​: applied with renamed variable.

comment:15 in reply to: ↑ 13 ; follow-ups: ↓ 16 ↓ 17 Changed 4 years ago by andrew_b

Replying to mooffie:

As for mc-3567-fix-memleak-at-configure_panel_listing.patch :

I think it'd be nicer if configure_panel_listing() didn't g_free() any of its arguments:

I agree.

it'd g_strdup() them.

I disagree. There is no need in extra string duplication.

The code calling this function (one such place) would g_free() them.

Attached patch 0001-configure_panel_listing-fix-memory-leak.patch.

Changed 4 years ago by andrew_b

comment:16 in reply to: ↑ 15 Changed 4 years ago by and

Replying to andrew_b:

Attached patch 0001-configure_panel_listing-fix-memory-leak.patch.

looks fine, I can't reproduce second memleak

comment:17 in reply to: ↑ 15 Changed 4 years ago by mooffie

Replying to andrew_b:

Attached patch 0001-configure_panel_listing-fix-memory-leak.patch.

That's a nice technique.

comment:18 Changed 4 years ago by andrew_b

  • Status changed from new to closed
  • Votes for changeset set to committed-master
  • Resolution set to fixed

mc-3567-fix-heap-use-after-free-bug-widget-object-v6.patch​: [5f076e9e0510e04f1826946356e444ccff16f418].
Fix memleak in configure_panel_listing: [2b1fa34c9affbd0f428cd1ffeaacf69fdeffd5bd].

comment:19 Changed 4 years ago by andrew_b

  • Blocked By 3547 removed
Note: See TracTickets for help on using tickets.