* [Tarantool-patches] [PATCH] relay: fix use after free in subscribe_f
@ 2021-05-12 11:39 Serge Petrenko via Tarantool-patches
2021-05-12 11:48 ` Cyrill Gorcunov via Tarantool-patches
` (2 more replies)
0 siblings, 3 replies; 8+ messages in thread
From: Serge Petrenko via Tarantool-patches @ 2021-05-12 11:39 UTC (permalink / raw)
To: v.shpilevoy, gorcunov; +Cc: tarantool-patches
relay_subscribe_f() remembered old recovery pointer, which might be
replaced by relay_restart_recovery() if a raft message is delivered during
cbus_process() loop in relay_send_is_raft_enabled().
Fix the issue by moving variable initialization below
relay_send_is_raft_enabled()
Closes #6031
---
https://github.com/tarantool/tarantool/issues/6031
https://github.com/tarantool/tarantool/tree/sp/gh-6031-use-after-free
src/box/relay.cc | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/box/relay.cc b/src/box/relay.cc
index ff43c2fc7..32d3a58dd 100644
--- a/src/box/relay.cc
+++ b/src/box/relay.cc
@@ -741,7 +741,6 @@ static int
relay_subscribe_f(va_list ap)
{
struct relay *relay = va_arg(ap, struct relay *);
- struct recovery *r = relay->r;
coio_enable();
relay_set_cord_name(relay->io.fd);
@@ -756,6 +755,8 @@ relay_subscribe_f(va_list ap)
if (!relay->replica->anon)
relay_send_is_raft_enabled(relay, &raft_enabler, true);
+ struct recovery *r = relay->r;
+
/*
* Setup garbage collection trigger.
* Not needed for anonymous replicas, since they
--
2.30.1 (Apple Git-130)
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Tarantool-patches] [PATCH] relay: fix use after free in subscribe_f
2021-05-12 11:39 [Tarantool-patches] [PATCH] relay: fix use after free in subscribe_f Serge Petrenko via Tarantool-patches
@ 2021-05-12 11:48 ` Cyrill Gorcunov via Tarantool-patches
2021-05-13 10:36 ` Serge Petrenko via Tarantool-patches
2021-05-12 20:25 ` Vladislav Shpilevoy via Tarantool-patches
2021-05-14 7:44 ` Kirill Yukhin via Tarantool-patches
2 siblings, 1 reply; 8+ messages in thread
From: Cyrill Gorcunov via Tarantool-patches @ 2021-05-12 11:48 UTC (permalink / raw)
To: Serge Petrenko; +Cc: v.shpilevoy, tarantool-patches
On Wed, May 12, 2021 at 02:39:07PM +0300, Serge Petrenko wrote:
> relay_subscribe_f() remembered old recovery pointer, which might be
> replaced by relay_restart_recovery() if a raft message is delivered during
> cbus_process() loop in relay_send_is_raft_enabled().
>
> Fix the issue by moving variable initialization below
> relay_send_is_raft_enabled()
>
> Closes #6031
> ---
> https://github.com/tarantool/tarantool/issues/6031
> https://github.com/tarantool/tarantool/tree/sp/gh-6031-use-after-free
>
> src/box/relay.cc | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/src/box/relay.cc b/src/box/relay.cc
> index ff43c2fc7..32d3a58dd 100644
> --- a/src/box/relay.cc
> +++ b/src/box/relay.cc
> @@ -741,7 +741,6 @@ static int
> relay_subscribe_f(va_list ap)
> {
> struct relay *relay = va_arg(ap, struct relay *);
> - struct recovery *r = relay->r;
>
> coio_enable();
> relay_set_cord_name(relay->io.fd);
> @@ -756,6 +755,8 @@ relay_subscribe_f(va_list ap)
> if (!relay->replica->anon)
> relay_send_is_raft_enabled(relay, &raft_enabler, true);
>
> + struct recovery *r = relay->r;
Could you please add a comment why it is important to fetch `relay->r`
at exactly this stage. Something like
/*
* Fetching relay->r should be done after
* cbus processing since the pointer may
* be updated undeneath.
*/
struct recovery *r = relay->r;
Or something like this. Because commits messages are good but we
read the code in first place and this very nontrivial moment.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Tarantool-patches] [PATCH] relay: fix use after free in subscribe_f
2021-05-12 11:39 [Tarantool-patches] [PATCH] relay: fix use after free in subscribe_f Serge Petrenko via Tarantool-patches
2021-05-12 11:48 ` Cyrill Gorcunov via Tarantool-patches
@ 2021-05-12 20:25 ` Vladislav Shpilevoy via Tarantool-patches
2021-05-13 10:34 ` Serge Petrenko via Tarantool-patches
2021-05-14 7:44 ` Kirill Yukhin via Tarantool-patches
2 siblings, 1 reply; 8+ messages in thread
From: Vladislav Shpilevoy via Tarantool-patches @ 2021-05-12 20:25 UTC (permalink / raw)
To: Serge Petrenko, gorcunov; +Cc: tarantool-patches
Hi! Thanks for the patch!
> diff --git a/src/box/relay.cc b/src/box/relay.cc
> index ff43c2fc7..32d3a58dd 100644
> --- a/src/box/relay.cc
> +++ b/src/box/relay.cc
> @@ -756,6 +755,8 @@ relay_subscribe_f(va_list ap)
> if (!relay->replica->anon)
> relay_send_is_raft_enabled(relay, &raft_enabler, true);
>
> + struct recovery *r = relay->r;
> +
There is another cbus_process() on line 808. Won't it lead to the same issue
if recovery would be restarted? I see it is for version < 1.7.4 so probably
not. Another option would be to simply inline relay->r in its usage places
and not remember it into a variable.
Anyway LGTM. Up to you if want to inline.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Tarantool-patches] [PATCH] relay: fix use after free in subscribe_f
2021-05-12 20:25 ` Vladislav Shpilevoy via Tarantool-patches
@ 2021-05-13 10:34 ` Serge Petrenko via Tarantool-patches
2021-05-13 11:23 ` Vladislav Shpilevoy via Tarantool-patches
2021-05-13 11:44 ` Cyrill Gorcunov via Tarantool-patches
0 siblings, 2 replies; 8+ messages in thread
From: Serge Petrenko via Tarantool-patches @ 2021-05-13 10:34 UTC (permalink / raw)
To: Vladislav Shpilevoy, gorcunov; +Cc: tarantool-patches
12.05.2021 23:25, Vladislav Shpilevoy пишет:
> Hi! Thanks for the patch!
>
>> diff --git a/src/box/relay.cc b/src/box/relay.cc
>> index ff43c2fc7..32d3a58dd 100644
>> --- a/src/box/relay.cc
>> +++ b/src/box/relay.cc
>> @@ -756,6 +755,8 @@ relay_subscribe_f(va_list ap)
>> if (!relay->replica->anon)
>> relay_send_is_raft_enabled(relay, &raft_enabler, true);
>>
>> + struct recovery *r = relay->r;
>> +
> There is another cbus_process() on line 808. Won't it lead to the same issue
> if recovery would be restarted? I see it is for version < 1.7.4 so probably
> not. Another option would be to simply inline relay->r in its usage places
> and not remember it into a variable.
>
> Anyway LGTM. Up to you if want to inline.
Thanks for the review!
Yep, let's inline this.
I've also added a changelog entry.
The patch's changed a lot so here's the whole new version.
===========================================
Author: Serge Petrenko <sergepetrenko@tarantool.org>
Date: Wed May 12 12:58:34 2021 +0300
relay: fix use after free in subscribe_f
relay_subscribe_f() remembered old recovery pointer, which might be
replaced by relay_restart_recovery() if a raft message is delivered
during
cbus_process() loop in relay_send_is_raft_enabled().
Fix the issue by removing the alias altogether and referencing relay->r
directly to prevent any further mistakes.
Closes #6031
diff --git a/changelogs/unreleased/gh-6031-relay-use-after-free.md
b/changelogs/unreleased/gh-6031-relay-use-after-free.md
new file mode 100644
index 000000000..910b29614
--- /dev/null
+++ b/changelogs/unreleased/gh-6031-relay-use-after-free.md
@@ -0,0 +1,3 @@
+## bugfix/replication
+
+* Fix use after free in relay thread when using elections (gh-6031).
diff --git a/src/box/relay.cc b/src/box/relay.cc
index ff43c2fc7..5a21a4499 100644
--- a/src/box/relay.cc
+++ b/src/box/relay.cc
@@ -741,7 +741,6 @@ static int
relay_subscribe_f(va_list ap)
{
struct relay *relay = va_arg(ap, struct relay *);
- struct recovery *r = relay->r;
coio_enable();
relay_set_cord_name(relay->io.fd);
@@ -764,7 +763,7 @@ relay_subscribe_f(va_list ap)
struct trigger on_close_log;
trigger_create(&on_close_log, relay_on_close_log_f, relay, NULL);
if (!relay->replica->anon)
- trigger_add(&r->on_close_log, &on_close_log);
+ trigger_add(&relay->r->on_close_log, &on_close_log);
/* Setup WAL watcher for sending new rows to the replica. */
wal_set_watcher(&relay->wal_watcher, relay->endpoint.name,
@@ -816,7 +815,7 @@ relay_subscribe_f(va_list ap)
continue;
struct vclock *send_vclock;
if (relay->version_id < version_id(1, 7, 4))
- send_vclock = &r->vclock;
+ send_vclock = &relay->r->vclock;
else
send_vclock = &relay->recv_vclock;
===========================================
--
Serge Petrenko
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Tarantool-patches] [PATCH] relay: fix use after free in subscribe_f
2021-05-12 11:48 ` Cyrill Gorcunov via Tarantool-patches
@ 2021-05-13 10:36 ` Serge Petrenko via Tarantool-patches
0 siblings, 0 replies; 8+ messages in thread
From: Serge Petrenko via Tarantool-patches @ 2021-05-13 10:36 UTC (permalink / raw)
To: Cyrill Gorcunov; +Cc: v.shpilevoy, tarantool-patches
12.05.2021 14:48, Cyrill Gorcunov пишет:
> On Wed, May 12, 2021 at 02:39:07PM +0300, Serge Petrenko wrote:
>> relay_subscribe_f() remembered old recovery pointer, which might be
>> replaced by relay_restart_recovery() if a raft message is delivered during
>> cbus_process() loop in relay_send_is_raft_enabled().
>>
>> Fix the issue by moving variable initialization below
>> relay_send_is_raft_enabled()
>>
>> Closes #6031
>> ---
>> https://github.com/tarantool/tarantool/issues/6031
>> https://github.com/tarantool/tarantool/tree/sp/gh-6031-use-after-free
>>
>> src/box/relay.cc | 3 ++-
>> 1 file changed, 2 insertions(+), 1 deletion(-)
>>
>> diff --git a/src/box/relay.cc b/src/box/relay.cc
>> index ff43c2fc7..32d3a58dd 100644
>> --- a/src/box/relay.cc
>> +++ b/src/box/relay.cc
>> @@ -741,7 +741,6 @@ static int
>> relay_subscribe_f(va_list ap)
>> {
>> struct relay *relay = va_arg(ap, struct relay *);
>> - struct recovery *r = relay->r;
>>
>> coio_enable();
>> relay_set_cord_name(relay->io.fd);
>> @@ -756,6 +755,8 @@ relay_subscribe_f(va_list ap)
>> if (!relay->replica->anon)
>> relay_send_is_raft_enabled(relay, &raft_enabler, true);
>>
>> + struct recovery *r = relay->r;
> Could you please add a comment why it is important to fetch `relay->r`
> at exactly this stage. Something like
>
> /*
> * Fetching relay->r should be done after
> * cbus processing since the pointer may
> * be updated undeneath.
> */
> struct recovery *r = relay->r;
>
> Or something like this. Because commits messages are good but we
> read the code in first place and this very nontrivial moment.
Hi! Thanks for the review.
Vlad suggested to inline relay->r. It has only 2 usage places after all.
I agree this was nontrivial. It's better with the inline, I think.
--
Serge Petrenko
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Tarantool-patches] [PATCH] relay: fix use after free in subscribe_f
2021-05-13 10:34 ` Serge Petrenko via Tarantool-patches
@ 2021-05-13 11:23 ` Vladislav Shpilevoy via Tarantool-patches
2021-05-13 11:44 ` Cyrill Gorcunov via Tarantool-patches
1 sibling, 0 replies; 8+ messages in thread
From: Vladislav Shpilevoy via Tarantool-patches @ 2021-05-13 11:23 UTC (permalink / raw)
To: Serge Petrenko, gorcunov; +Cc: tarantool-patches
Hi! Thanks for the fixes!
LGTM.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Tarantool-patches] [PATCH] relay: fix use after free in subscribe_f
2021-05-13 10:34 ` Serge Petrenko via Tarantool-patches
2021-05-13 11:23 ` Vladislav Shpilevoy via Tarantool-patches
@ 2021-05-13 11:44 ` Cyrill Gorcunov via Tarantool-patches
1 sibling, 0 replies; 8+ messages in thread
From: Cyrill Gorcunov via Tarantool-patches @ 2021-05-13 11:44 UTC (permalink / raw)
To: Serge Petrenko; +Cc: Vladislav Shpilevoy, tarantool-patches
On Thu, May 13, 2021 at 01:34:55PM +0300, Serge Petrenko wrote:
>
> Author: Serge Petrenko <sergepetrenko@tarantool.org>
> Date: Wed May 12 12:58:34 2021 +0300
>
> relay: fix use after free in subscribe_f
>
Ack
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Tarantool-patches] [PATCH] relay: fix use after free in subscribe_f
2021-05-12 11:39 [Tarantool-patches] [PATCH] relay: fix use after free in subscribe_f Serge Petrenko via Tarantool-patches
2021-05-12 11:48 ` Cyrill Gorcunov via Tarantool-patches
2021-05-12 20:25 ` Vladislav Shpilevoy via Tarantool-patches
@ 2021-05-14 7:44 ` Kirill Yukhin via Tarantool-patches
2 siblings, 0 replies; 8+ messages in thread
From: Kirill Yukhin via Tarantool-patches @ 2021-05-14 7:44 UTC (permalink / raw)
To: Serge Petrenko; +Cc: tarantool-patches, v.shpilevoy
Hello,
On 12 май 14:39, Serge Petrenko via Tarantool-patches wrote:
> relay_subscribe_f() remembered old recovery pointer, which might be
> replaced by relay_restart_recovery() if a raft message is delivered during
> cbus_process() loop in relay_send_is_raft_enabled().
>
> Fix the issue by moving variable initialization below
> relay_send_is_raft_enabled()
>
> Closes #6031
> ---
> https://github.com/tarantool/tarantool/issues/6031
> https://github.com/tarantool/tarantool/tree/sp/gh-6031-use-after-free
I've checked your patch into 2.8 and master.
--
Regards, Kirill Yukhin
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2021-05-14 7:44 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-12 11:39 [Tarantool-patches] [PATCH] relay: fix use after free in subscribe_f Serge Petrenko via Tarantool-patches
2021-05-12 11:48 ` Cyrill Gorcunov via Tarantool-patches
2021-05-13 10:36 ` Serge Petrenko via Tarantool-patches
2021-05-12 20:25 ` Vladislav Shpilevoy via Tarantool-patches
2021-05-13 10:34 ` Serge Petrenko via Tarantool-patches
2021-05-13 11:23 ` Vladislav Shpilevoy via Tarantool-patches
2021-05-13 11:44 ` Cyrill Gorcunov via Tarantool-patches
2021-05-14 7:44 ` Kirill Yukhin via Tarantool-patches
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox