Skip to content
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

Fix handling protocol->init() failure, fix double-free #18

Merged

Conversation

past-due
Copy link
Contributor

If upnp_init() fails, state->impl has already been freed.

upnp_cleanup() then later accesses state->impl.

Caught by AddressSanitizer:

=================================================================
==12240==ERROR: AddressSanitizer: heap-use-after-free on address 0x000103203da0 at pc 0x00010073e018 bp 0x00016fe86770 sp 0x00016fe86768
READ of size 4 at 0x000103203da0 thread T1
    #0 0x10073e014 in upnp_cleanup+0x1e8 (libplum.0.4.0.dylib:arm64+0x3e014)
    #1 0x100714460 in reset_protocol+0x308 (libplum.0.4.0.dylib:arm64+0x14460)
    #2 0x10070eccc in client_run+0xd9c (libplum.0.4.0.dylib:arm64+0xeccc)
    #3 0x10070df1c in client_thread_entry+0x14 (libplum.0.4.0.dylib:arm64+0xdf1c)
    #4 0x1004615bc in _pthread_start+0x84 (/usr/lib/system/introspection/libsystem_pthread.dylib:arm64e+0x15bc)
    #5 0x10046ba9c in thread_start+0x4 (/usr/lib/system/introspection/libsystem_pthread.dylib:arm64e+0xba9c)

0x000103203da0 is located 0 bytes inside of 96-byte region [0x000103203da0,0x000103203e00)
freed by thread T1 here:
    #0 0x1008b6ce0 in wrap_free+0x98 (/usr/lib/clang/15.0.0/lib/darwin/libclang_rt.asan_osx_dynamic.dylib:arm64e+0x52ce0)
    #1 0x10073dd58 in upnp_init+0xf78 (libplum.0.4.0.dylib:arm64+0x3dd58)
    #2 0x10070e818 in client_run+0x8e8 (libplum.0.4.0.dylib:arm64+0xe818)
    #3 0x10070df1c in client_thread_entry+0x14 (libplum.0.4.0.dylib:arm64+0xdf1c)
    #4 0x1004615bc in _pthread_start+0x84 (/usr/lib/system/introspection/libsystem_pthread.dylib:arm64e+0x15bc)
    #5 0x10046ba9c in thread_start+0x4 (/usr/lib/system/introspection/libsystem_pthread.dylib:arm64e+0xba9c)

previously allocated by thread T1 here:
    #0 0x1008b6ba4 in wrap_malloc+0x94 (/usr/lib/clang/15.0.0/lib/darwin/libclang_rt.asan_osx_dynamic.dylib:arm64e+0x52ba4)
    #1 0x10073cf4c in upnp_init+0x16c (libplum.0.4.0.dylib:arm64+0x3cf4c)
    #2 0x10070e818 in client_run+0x8e8 (libplum.0.4.0.dylib:arm64+0xe818)
    #3 0x10070df1c in client_thread_entry+0x14 (libplum.0.4.0.dylib:arm64+0xdf1c)
    #4 0x1004615bc in _pthread_start+0x84 (/usr/lib/system/introspection/libsystem_pthread.dylib:arm64e+0x15bc)
    #5 0x10046ba9c in thread_start+0x4 (/usr/lib/system/introspection/libsystem_pthread.dylib:arm64e+0xba9c)

Thread T1 created by T0 here:
    #0 0x1008afb10 in wrap_pthread_create+0x54 (/usr/lib/clang/15.0.0/lib/darwin/libclang_rt.asan_osx_dynamic.dylib:arm64e+0x4bb10)
    #1 0x1007102f8 in client_start+0x1cc (libplum.0.4.0.dylib:arm64+0x102f8)
    #2 0x10073352c in plum_create_mapping+0xa0 (libplum.0.4.0.dylib:arm64+0x3352c)
    #3 0x1000034d8 in main+0x374 (example:arm64+0x1000034d8)
    #4 0x19f01e0dc  (<unknown module>)

SUMMARY: AddressSanitizer: heap-use-after-free (libplum.0.4.0.dylib:arm64+0x3e014) in upnp_cleanup+0x1e8
==12240==ABORTING

Copy link
Owner

@paullouisageneau paullouisageneau left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, but this is not how the issue should be fixed. The actual problem is that cleanup must not be called if init fails, precisely because the state is not initialized in that case. The same issue probably exists for other protocols like with pcp_init() and pcp_cleanup().

I think the proper fix is to reset client->protocol to NULL if client->protocol->init() fails:

err = client->protocol->init(&client->protocol_state);

@past-due past-due changed the title upnp.c: Fix heap-use-after-free Fix handling protocol->init() failure, fix double-free Jun 17, 2024
@past-due
Copy link
Contributor Author

past-due commented Jun 17, 2024

I think the proper fix is to reset client->protocol to NULL if client->protocol->init() fails:

err = client->protocol->init(&client->protocol_state);

Implemented this fix.

I also reset state->impl = NULL after freeing, everywhere that is done.

And fixed a possible double-free in http_perform_rec() (error: already frees buffer, but there were a few places that also did so before goto error).

Copy link
Owner

@paullouisageneau paullouisageneau left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks good, thank you for the fixes!

@paullouisageneau paullouisageneau merged commit c5f5f3c into paullouisageneau:master Jun 19, 2024
3 checks passed
@past-due past-due deleted the fix_user_after_free branch July 7, 2024 18:25
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

Successfully merging this pull request may close these issues.

None yet

3 participants