Quantcast

Port driver use-after-free

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Port driver use-after-free

Salikhov Dinislam
Hello,

Failure scenario:
1. A process calls erlang:port_control() and passes a binary to port driver.
2. The driver is not invoked immediately, so the binary's refc is
incremented and the pointers to binary and to binary's data are kept in
struct ErtsProc2PortSigData_ for later call. The process is in pending
queue.
3. The pending process is the only one having the refcount to binary.
4. An event occurs causing garbage collecting of the pending process.
5. The binary is relocated, so the pointers kept in
ErtsProc2PortSigData_ become invalid.
6. The driver manipulates with already freed data.

Unfortunately, I don't have the minimal code sample reproducing the issue.
The described behavior is observed only on high loads and leads to VM crash.
The issue presents in  OTP-18.3 release. I didn't try it for later
releases, but I couldn't find any related fixes done either.

The memory for binary was first allocated as:
0x481a39 <do_erts_alcu_alloc+270>
0x481c06 <erts_alcu_alloc_thr_pref+135>
0x58db08 <erts_alloc+75>
0x58dc91 <erts_bin_nrml_alloc+68>
0x591362 <erts_bs_append+1566>
0x44177b <process_main+51114>
0x508a27 <sched_thread_func+499>
0x68f72d <thr_wrapper+235>

And then reallocated as:
0x482026 <do_erts_alcu_realloc+190>
0x4828f9 <realloc_thr_pref+257>
0x482ac1 <erts_alcu_realloc_thr_pref+51>
0x585984 <erts_realloc_fnf+81>
0x586200 <erts_bin_realloc+110>
0x58caac <sweep_off_heap+1277>
0x58a37e <major_collection+3163>
0x586ca8 <erts_garbage_collect+493>
0x43c36b <process_main+29594>
0x508a27 <sched_thread_func+499>
0x68f72d <thr_wrapper+235>

In the attachment there is a patch with a quick fix for the issue.
The idea is to always copy the data passed to the port driver if the
actual call is pended.
It is fine for small data, but can lead to performance degradation if
megabytes-size binaries are passed to port_control(), that's why I
haven't done a PR.

Salikhov Dinislam

_______________________________________________
erlang-bugs mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-bugs

erlang.patch (1K) Download Attachment
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Port driver use-after-free

Lukas Larsson-8
Hello,

Thanks for the bug report and fix. The solution which I will include upstream is to add a call to erts_emasculate_writable_binary in the code that your patch deleted.

Lukas

On Fri, Feb 17, 2017 at 10:20 AM, Salikhov Dinislam <[hidden email]> wrote:
Hello,

Failure scenario:
1. A process calls erlang:port_control() and passes a binary to port driver.
2. The driver is not invoked immediately, so the binary's refc is incremented and the pointers to binary and to binary's data are kept in struct ErtsProc2PortSigData_ for later call. The process is in pending queue.
3. The pending process is the only one having the refcount to binary.
4. An event occurs causing garbage collecting of the pending process.
5. The binary is relocated, so the pointers kept in ErtsProc2PortSigData_ become invalid.
6. The driver manipulates with already freed data.

Unfortunately, I don't have the minimal code sample reproducing the issue.
The described behavior is observed only on high loads and leads to VM crash.
The issue presents in  OTP-18.3 release. I didn't try it for later releases, but I couldn't find any related fixes done either.

The memory for binary was first allocated as:
0x481a39 <do_erts_alcu_alloc+270>
0x481c06 <erts_alcu_alloc_thr_pref+135>
0x58db08 <erts_alloc+75>
0x58dc91 <erts_bin_nrml_alloc+68>
0x591362 <erts_bs_append+1566>
0x44177b <process_main+51114>
0x508a27 <sched_thread_func+499>
0x68f72d <thr_wrapper+235>

And then reallocated as:
0x482026 <do_erts_alcu_realloc+190>
0x4828f9 <realloc_thr_pref+257>
0x482ac1 <erts_alcu_realloc_thr_pref+51>
0x585984 <erts_realloc_fnf+81>
0x586200 <erts_bin_realloc+110>
0x58caac <sweep_off_heap+1277>
0x58a37e <major_collection+3163>
0x586ca8 <erts_garbage_collect+493>
0x43c36b <process_main+29594>
0x508a27 <sched_thread_func+499>
0x68f72d <thr_wrapper+235>

In the attachment there is a patch with a quick fix for the issue.
The idea is to always copy the data passed to the port driver if the actual call is pended.
It is fine for small data, but can lead to performance degradation if megabytes-size binaries are passed to port_control(), that's why I haven't done a PR.

Salikhov Dinislam

_______________________________________________
erlang-bugs mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-bugs



_______________________________________________
erlang-bugs mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-bugs
Loading...