-
Notifications
You must be signed in to change notification settings - Fork 353
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
rpmbuild double-free #2826
Comments
Thanks for the report and backtrace. The rpmug thread-unsafety is of course painfully obvious, that it ends up called during the threaded packaging operation less so because the call happens from librpm side. It's curious that nobody has run into this before now. The core issue has been there since 4.15 already (so four years), it's just that in 4.19 it causes a double-free, before that I think one could've gotten silently corrupted user/group names in packages. We'll look into it. |
The height of embarrasment with this crash is that rpm has zero use for the uid/gid info when writing an archive. We could just skip the rpmug lookups entirely because the uid/gid is never written to the archive, only the names are (and even that only with cpio). |
This seems like a huge overkill when in 4.19.1 there's exactly one rpmfiStat() call that unnecessarily invokes an rpmug lookup in a threaded scenario, but then rpmfiStat() and rpmfilesStat() are public APIs that people expect to be safe for use within the originating thread. Collect all the caching data into a struct and allocate on per-thread basis, this seems like the path of least trouble in this case and git diff --stat agrees. It's worth noting that this also simplifies the caching, we no longer keep separate name to id and id to name, totaling caches totaling four. We simply cache one id/name for for user and another for group data. Also, reset ids to 0 rather than -1, this is far more obviously a safe value as we have special cases to handle id 0. rpmugUname() and rpmugGname() are have no users in the current codebase, so this was developed wrt commit c576d96 where they still are used, to avoid nasty surprises later on if somebody finds a new case for these. Fixes: rpm-software-management#2826
Collect all the cached data into a struct and which is allocated on per-thread basis, this seems like the path of least trouble in this case and git diff --stat agrees. It's worth noting that this also simplifies the caching, we no longer keep separate name to id and id to name caches (totaling four). We simply cache one id/name for for user and another for group data. Also, reset ids to 0 rather than -1, this is far more obviously a safe value as we have special cases to handle id 0. rpmugUname() and rpmugGname() are have no users in the current codebase, so this was developed wrt commit c576d96 where they still are used, to avoid nasty surprises later on if somebody finds a new case for these. This all seems like a huge overkill when in 4.19.1 there's exactly one rpmfiStat() call that unnecessarily invokes an rpmug lookup in a threaded scenario, but then rpmfiStat() and rpmfilesStat() are public APIs that people expect to be safe for use within the originating thread. Fixes: rpm-software-management#2826
Collect all the cached data into a struct and which is allocated on per-thread basis, this seems like the path of least trouble in this case and git diff --stat agrees. It's worth noting that this also simplifies the caching, we no longer keep separate name to id and id to name caches (totaling four). We simply cache one id/name for for user and another for group data. Also, reset ids to 0 rather than -1, this is far more obviously a safe value as we have special cases to handle id 0. rpmugUname() and rpmugGname() are have no users in the current codebase, so this was developed wrt commit c576d96 where they still are used, to avoid nasty surprises later on if somebody finds a new case for these. This all seems like a huge overkill when in there's exactly one user in a rpmfiStat() call that unnecessarily invokes an rpmug lookup in a threaded scenario, but then rpmfiStat() and rpmfilesStat() are public APIs that people expect to be safe for use within the originating thread. Fixes: rpm-software-management#2826
Now with the caching data in a single struct from the previous commit, we can easily make this per-thread for a minimal fix for thread-safety. Fixes: rpm-software-management#2826
Now with the caching data in a single struct from the previous commit, we can easily make this per-thread for a minimal fix for thread-safety. Fixes: #2826
Now with the caching data in a single struct from the previous commit, we can easily make this per-thread for a minimal fix for thread-safety. Fixes: rpm-software-management#2826
Now with the caching data in a single struct from the previous commit, we can easily make this per-thread for a minimal fix for thread-safety. Fixes: rpm-software-management#2826 (cherry picked from commit c86f088)
Now with the caching data in a single struct from the previous commit, we can easily make this per-thread for a minimal fix for thread-safety. Fixes: rpm-software-management#2826 (cherry picked from commit c86f088)
Recent version of rpmbuild have a small chance of crashing with a double-free. Typical crash:
I was able to extract a backtrace:
I believe that the ball starts rolling in the
in
packageBinaries
, see stack frame #19.It keeps rolling downhill into rpmug.c (stack frame #8), which is very, very much thread-unsafe. Boom.
All usage of
static
variables inrpmug.c
is thread-unsafe.It should be possible to reliably reproduce this crash by sticking, say,
sleep (1);
just beforefree(lastUname);
on line 148, and then building an srpm that packages a bunch of binaryrpms.\textlive will do nicely...
rpmuguid() is not thread safe.
rpmuggid() is not thread safe.
rpmugUname() is not thread safe.
rpmugGname() is not thread safe.
The text was updated successfully, but these errors were encountered: