* [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: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-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-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