Re: Port driver use-after-free

Lukas Larsson <[email protected]> Tue, 21 Feb 2017 09:47:09 +0100
Newsgroups gmane.comp.lang.erlang.bugs
Message-ID <CAP3zBqNfB_JLFH5Dx8zmC5XeDi3fTuZmN0JS=_2Y4ez5e-6pdw@mail.gmail.com>
--===============5983759396355999728==
Content-Type: multipart/alternative; boundary=001a11353442eec0480549066cb3

--001a11353442eec0480549066cb3
Content-Type: text/plain; charset=UTF-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 <
[email protected]> 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
> [email protected]
> http://erlang.org/mailman/listinfo/erlang-bugs
>
>

--001a11353442eec0480549066cb3
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Hello,<div><br></div><div>Thanks for the bug report and fi=
x. The solution which I will include upstream is to add a call to=C2=A0erts=
_emasculate_writable_binary in the code that your patch deleted.</div><div>=
<br></div><div>Lukas</div></div><div class=3D"gmail_extra"><br><div class=
=3D"gmail_quote">On Fri, Feb 17, 2017 at 10:20 AM, Salikhov Dinislam <span =
dir=3D"ltr">&lt;<a href=3D"mailto:[email protected]" target=
=3D"_blank">[email protected]</a>&gt;</span> wrote:<br><block=
quote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc=
 solid;padding-left:1ex">Hello,<br>
<br>
Failure scenario:<br>
1. A process calls erlang:port_control() and passes a binary to port driver=
.<br>
2. The driver is not invoked immediately, so the binary&#39;s refc is incre=
mented and the pointers to binary and to binary&#39;s data are kept in stru=
ct ErtsProc2PortSigData_ for later call. The process is in pending queue.<b=
r>
3. The pending process is the only one having the refcount to binary.<br>
4. An event occurs causing garbage collecting of the pending process.<br>
5. The binary is relocated, so the pointers kept in ErtsProc2PortSigData_ b=
ecome invalid.<br>
6. The driver manipulates with already freed data.<br>
<br>
Unfortunately, I don&#39;t have the minimal code sample reproducing the iss=
ue.<br>
The described behavior is observed only on high loads and leads to VM crash=
.<br>
The issue presents in=C2=A0 OTP-18.3 release. I didn&#39;t try it for later=
 releases, but I couldn&#39;t find any related fixes done either.<br>
<br>
The memory for binary was first allocated as:<br>
0x481a39 &lt;do_erts_alcu_alloc+270&gt;<br>
0x481c06 &lt;erts_alcu_alloc_thr_pref+135&gt;<br>
0x58db08 &lt;erts_alloc+75&gt;<br>
0x58dc91 &lt;erts_bin_nrml_alloc+68&gt;<br>
0x591362 &lt;erts_bs_append+1566&gt;<br>
0x44177b &lt;process_main+51114&gt;<br>
0x508a27 &lt;sched_thread_func+499&gt;<br>
0x68f72d &lt;thr_wrapper+235&gt;<br>
<br>
And then reallocated as:<br>
0x482026 &lt;do_erts_alcu_realloc+190&gt;<br>
0x4828f9 &lt;realloc_thr_pref+257&gt;<br>
0x482ac1 &lt;erts_alcu_realloc_thr_pref+51<wbr>&gt;<br>
0x585984 &lt;erts_realloc_fnf+81&gt;<br>
0x586200 &lt;erts_bin_realloc+110&gt;<br>
0x58caac &lt;sweep_off_heap+1277&gt;<br>
0x58a37e &lt;major_collection+3163&gt;<br>
0x586ca8 &lt;erts_garbage_collect+493&gt;<br>
0x43c36b &lt;process_main+29594&gt;<br>
0x508a27 &lt;sched_thread_func+499&gt;<br>
0x68f72d &lt;thr_wrapper+235&gt;<br>
<br>
In the attachment there is a patch with a quick fix for the issue.<br>
The idea is to always copy the data passed to the port driver if the actual=
 call is pended.<br>
It is fine for small data, but can lead to performance degradation if megab=
ytes-size binaries are passed to port_control(), that&#39;s why I haven&#39=
;t done a PR.<span class=3D"HOEnZb"><font color=3D"#888888"><br>
<br>
Salikhov Dinislam<br>
</font></span><br>______________________________<wbr>_________________<br>
erlang-bugs mailing list<br>
<a href=3D"mailto:[email protected]">[email protected]</a><br>
<a href=3D"http://erlang.org/mailman/listinfo/erlang-bugs" rel=3D"noreferre=
r" target=3D"_blank">http://erlang.org/mailman/<wbr>listinfo/erlang-bugs</a=
><br>
<br></blockquote></div><br></div>

--001a11353442eec0480549066cb3--

--===============5983759396355999728==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

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

--===============5983759396355999728==--