From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on dcvr.yhbt.net X-Spam-Level: X-Spam-Status: No, score=-4.0 required=3.0 tests=ALL_TRUSTED,BAYES_00 shortcircuit=no autolearn=ham autolearn_force=no version=3.4.2 Received: from localhost (dcvr.yhbt.net [127.0.0.1]) by dcvr.yhbt.net (Postfix) with ESMTP id 749D120085 for ; Mon, 1 Feb 2021 08:28:35 +0000 (UTC) From: Eric Wong To: meta@public-inbox.org Subject: [PATCH 18/21] ds: guard against stack-not-refcounted quirk of Perl 5 Date: Sun, 31 Jan 2021 22:28:30 -1000 Message-Id: <20210201082833.3293-19-e@80x24.org> In-Reply-To: <20210201082833.3293-1-e@80x24.org> References: <20210201082833.3293-1-e@80x24.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit List-Id: The Perl 5 stack is weakly-referenced for performance reasons. This means it's possible for items in the stack to be freed while executing further down the stack. In lei (and perhaps public-facing read-only daemons in the future), we'll fork and call PublicInbox::DS->Reset in the child process. This causes %DescriptorMap to be clobbered, allowing the $DescriptorMap{$fd} arg to be freed inside the child process. When Carp::confess or Carp::longmess is called to generate a backtrace, it may access the @DB::args array. This array access is not protected by reference counting and is known to cause segfaults and other weird errors. While the caller of an unnecessary Carp::confess may be eliminated in a future commit, we can't guarantee our dependencies will be free of @DB::args access attempts in the future. So guard against this Perl 5 quirmk by defensively bumping the refcount of any object we call ->event_step on. cf. https://rt.perl.org/Public/Bug/Display.html?id=131046 https://github.com/Perl/perl5/issues/15928 --- lib/PublicInbox/DS.pm | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/PublicInbox/DS.pm b/lib/PublicInbox/DS.pm index 40994fd4..2d312f0a 100644 --- a/lib/PublicInbox/DS.pm +++ b/lib/PublicInbox/DS.pm @@ -271,6 +271,7 @@ sub EventLoop { $Epoll //= _InitPoller(); local $in_loop = 1; my @events; + my $obj; # guard stack-not-refcounted w/ Carp + @DB::args do { my $timeout = RunTimers(); @@ -281,7 +282,8 @@ sub EventLoop { # that ones in the front triggered unregister-interest actions. if we # can't find the %sock entry, it's because we're no longer interested # in that event. - $DescriptorMap{$fd}->event_step; + $obj = $DescriptorMap{$fd}; + $obj->event_step; } } while (PostEventLoop()); _run_later();