On 4 October 2017 at 14:17, Thierry Vignaud <[email protected]> wrote:
>>>>>>>>> Also this new rpm introduced segfault regressions in both RPM4 &
>>>>>>>>> urpmi
>>>>>>>>> testsuites
>>>>>>>>> See attached gdb traces in BUG*.txt
>>>>>>>>> valgrind seems to hint about invalid writes/reads
>>>>>>>>> See you
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> The urpmi issue is when checking bogus pkgs.
>>>>>>>> The RPM4 issue is when traversing the transaction (not the rpmdb)
>>>>>>>> Attached are the valgrind outputs
>>>>>>>>
>>>>>>>
>>>>>>> So we have stuff like
>>>>>>>
>>>>>>> ==14087== Invalid write of size 4
>>>>>>> ==14087==    at 0x103AA6DD: headerUnlink (header.c:188)
>>>>>>> ==14087==    by 0x103AA6DD: headerFree (header.c:194)
>>>>>>> ==14087==    by 0xFF69314: XS_RPM4__Header_DESTROY (RPM4.xs:890)
>>>>>>> ==14087==    by 0x3F512E2C40: Perl_pp_entersub (pp_hot.c:4231)
>>>>>>> ==14087==    by 0x3F5125551E: Perl_call_sv (perl.c:2848)
>>>>>>> ==14087==    by 0x3F512E7C09: S_curse (sv.c:6987)
>>>>>>> ==14087==    by 0x3F512E84F7: Perl_sv_clear (sv.c:6591)
>>>>>>> ==14087==    by 0x3F512E898D: Perl_sv_free2 (sv.c:7088)
>>>>>>> ==14087==    by 0x3F513182E6: UnknownInlinedFun (inline.h:200)
>>>>>>> ==14087==    by 0x3F513182E6: Perl_free_tmps (scope.c:212)
>>>>>>> ==14087==    by 0x3F512DAD74: Perl_pp_nextstate (pp_hot.c:52)
>>>>>>> ==14087==    by 0x3F512DAA55: Perl_runops_standard (run.c:41)
>>>>>>> ==14087==    by 0x3F5125D236: S_run_body (perl.c:2524)
>>>>>>> ==14087==    by 0x3F5125D236: perl_run (perl.c:2447)
>>>>>>> ==14087==    by 0x400C79: main (perlmain.c:123)
>>>>>>> ==14087==  Address 0xffeffef8c is on thread 1's stack
>>>>>>> ==14087==  396 bytes below stack pointer
>>>>>>>
>>>>>>> ...and all the failures are around headerFree(), but none of the
>>>>>>> traces
>>>>>>> go
>>>>>>> into rpm itself, so I dont really know what does "traversing the
>>>>>>> transaction" actually mean.
>>>>>>
>>>>>>
>>>>>>
>>>>>> in both URPM & RPM4 bindings, there's a family of traverse functions
>>>>>> that enable to execute a callback on each package of either:
>>>>>> - rpmdb
>>>>>> - the current transaction,
>>>>>> - pkgs header from an hdlist file
>>>>>> - synthetic metadata from a synthesis file
>>>>>> calling the callback on the currrent header
>>>>>>
>>>>>> See:
>>>>>> - Db_traverse*() & Trans_traverse() in perl-URPM/URPM.xs
>>>>>> - Ts_traverse() in RPM4-0.36/src/RPM4.xs
>>>>>>
>>>>>> It's loosely documented at
>>>>>> http://search.cpan.org/~tvignaud/URPM-5.12/URPM.pm or
>>>>>>
>>>>>>
>>>>>> http://search.cpan.org/~tvignaud/RPM4-0.36/lib/RPM4/Transaction.pm#Hdlist::Db-%3Etraverse_headers(sub)
>>>>>> (RPM4's doc is very incomplete -- I'm only maintaining this b/c other
>>>>>> tools depend on that and I cannot break them when upgrading rpm)
>>>>>>
>>>>>>> But the problem is simply with perl-RPM4 and
>>>>>>> urpmi passing uninitialized variables to headerFree().
>>>>>>>
>>>>>>> What changed in rpm is that rpmReadPackageFile() no longer does this
>>>>>>> as
>>>>>>> the
>>>>>>> first thing:
>>>>>>>
>>>>>>>       if (hdrp)
>>>>>>>           *hdrp = NULL;
>>>>>>>
>>>>>>> Ie if you pass an uninitialized pointer as hdrp, it remains
>>>>>>> uninitialized
>>>>>>> unless rpmReadPackageFile() returns with a success code.
>>>>>>> Which is how I think it should be, but it does deserve a release note
>>>>>>> on
>>>>>>> the
>>>>>>> changed API.
>>>>>>>
>>>>>>> So the moral of the story is basically: if you depend on your
>>>>>>> variables
>>>>>>> being initialized, initialize them by yourself. It's a good practise
>>>>>>> anyway.
>>>>>>
>>>>>>
>>>>>>
>>>>>> I'll check for uninitialized variables later today
>>>>>
>>>>>
>>>>>
>>>>> Actually the bug happen when running the transaction
>>>>>
>>>>
>>>> Right, that makes sense, there's a second rpmReadPackageFile() inside
>>>> transaction run.
>>>
>>>
>>> Intestingly, perl-RPM4 no more segfaults (there still faillures
>>> though) if I alter the transrun() method (which calls rpmtsRun in
>>> rpmlib) 's perl callback to *not* call std rpmShowProgress())
>>> See attached patch
>>>
>>> Aka previously it runs both the passed perl callback + rpmlib default
>>> callback which worked smoothly.
>>> But since rpm-4.14, calling std rpm callback results a segfault...
>>> I'm happy to not call that and I don't think we have any tool actually
>>> running transactions^W installing packages through RPM4 right now but
>>> still that's a regression in rpm...
>>> Maybe some new unlink call or sg like that
>>>
>>
>> Are you saying you still get that segfault with this fix?
>> https://github.com/rpm-software-management/rpm/commit/082e6e77dd613efa643b02ee0417c1382f520893
>
> That fix was for URPM segfaulting while verifying bad rpms, here I'm
> talking about RPM4 segfaulting while installing packages
> (different binding, different issue)
> The URPM issue is fixed by the above commit (s/is/should/ - I hadn't
> actually tested your fix)
> The RPM4 issue is a different issue, even if both happen in headerFree() .
> You might get confused by the perl gdb traces that looks similar but
> the issues really are different.
> They show the point where the perl interpreter segfault, but not the
> point where the call in rpmlib has garbaged things as this action has
> finished and we'd return to the perl interpreter.
>
>> From the traceback you posted it was tripping on the uninitialized header
>> pointer as the other one. And if you disable the entire callback then there
>> are no open files returned and the whole error path is different.
>
> There's still a perl callback that's run.
> Actually there's a C/XS wrapper (transCallback()), running the
> optional pure perl callback if present
> Ts_transrun => rpmtsSetNotifyCallback with transCallback wrapper as
> callback and the actual perl callback as parameter
> (similar to what URPM is doing)
> Then during the actual installation, rpmlib calls the callback
> (transCallback) which set up the perl arg stack & calls the perl
> callback which itself used to call the rpmlib default callback.
>
> Here, the segfault is also in headerFree() but only happen in the
> install callback while installing pkgs and only if the perl callback
> calls the default rpmlib progress callback.
>
>> BTW, your workaround in
>> http://gitweb.mageia.org/software/rpm/perl-URPM/commit/?id=87dbde4f3b078173e53cd45cac000c2d2751b370
>> is not the one you want: initialize to NULL instead
>
> Ack. Thx
> Though from what you said, I should be able to remove any
> initialization at all as the rpmReadPackageFile() regression is fixed
> and should now always set the return parameter.
> See you

You can test by building the perl-RPM4 packages with the attached spec
file, w/o installing it.
Sources are at 
http://search.cpan.org/CPAN/authors/id/T/TV/TVIGNAUD/RPM4-0.36.tar.gz
then in order to run the broken test with the just compiled module:
cd BUILD/RPM4-0.36/
PERL_DL_NONLAZY=1 PERL_USE_UNSAFE_INC=1 gdb -q --args perl
"-MExtUtils::Command::MM" "-MTest::Harness" -Iblib/lib -Iblib/arch
t/05transaction.t
What's interesting is that:
- it segfaults on FC26 with rpm-4.13.0.1-7.fc26.x86_64
- it doesn't segfaults but show failures on mga6 with rpm-4.13.0.1-3.1.mga6

Some patch difference could explain that
I see that it hasn't been rebuild for rpm updates between
4.13.0-0.rc1.32.mga6 & 4.13.0.1-3.mga6 and I guess the other
regressions weren't checked for after a signing segfault in the
testsuite due to rpm-4.13 was fixed
# This spec is in the SVN
# $Id: perl-RPM4.spec 141783 2007-03-12 14:05:45Z nanardon $

%define module	RPM4

%define rpm_version %(rpm -q --queryformat '%|EPOCH?{[%{EPOCH}:%{VERSION}]}:{%{VERSION}}|' rpm)

%{?perl_default_filter}

Name:		perl-%{module}
Version:	0.36
Release:	3.1
Summary:	Perl bindings to use rpmlib and manage hdlist files
License:	GPL
Group:		Development/Perl
Source:		%{module}-%{version}.tar.xz
Patch0:		fix-a-segv.patch
Patch1:		0001-disable-tests-that-involve-a-pasphrase.patch
# workaround a testsuite regression with rpm-4.14:
#Patch3:		reload-spec-file-before-builds.patch
Url:		http://search.cpan.org/dist/RPM4/

BuildRequires:	perl-devel >= 5.8.0
BuildRequires:	pkgconfig(rpm) >= 4.12.90
BuildRequires:	perl-Digest-SHA1
#BuildRequires:	librpmconstant-devel
#BuildRequires:	packdrake
BuildRequires:	perl-MDV-Packdrakeng
BuildRequires:	gnupg

# we can now expect librpm API to be at least backward compatible
Requires:	rpm >= %{rpm_version}

%description
This module provides a perl interface to the rpmlib.

It allows to write scripts to:
  - query rpm headers,
  - query rpm database,
  - build rpm specs,
  - install/uninstall specfiles,
  - check dependencies.

It includes:
- rpm_produced, give what rpm will be produced by a src.rpm or a specfile.

%prep
%setup -q -n %{module}-%{version}
%autopatch -p1

%build
%{__perl} Makefile.PL INSTALLDIRS=vendor
%make_build

%check
%ifarch x86_64
make test TEST_VERBOSE=1 || :
%endif

%install
%make_install
find %{buildroot} -type f -name perllocal.pod -exec rm -f {} ';'

%files
%doc README
%doc examples
%_bindir/*
%{perl_vendorarch}/*
%{_mandir}/*/*


_______________________________________________
Rpm-maint mailing list
[email protected]
http://lists.rpm.org/mailman/listinfo/rpm-maint

Reply via email to