On Tue, 26 Dec 2023 at 07:32, Sam Varshavchik <mr...@courier-mta.com> wrote:

> Stephen Smoogen writes:
>
> >
> > I am guessing the problem is really with the free(lastUname) since the
> rfree
>
> Yes. Multiple execution threads will reach lastUname and try to free the
> same pointer. glibc rightfully complains about the double-free.
>
>
I am trying to figure out the logic of this section:

```

    static char * lastUname = NULL; // So lastUname is NULL
    static uid_t lastUid;

    if (!thisUname) {
        lastUname = rfree(lastUname); // lastUname should still be NULL and
we are freeing NULL and setting itself back to NULL.
        return -1;
```

I expect this is where I am not understanding something basic in C from too
many years in non-pointer land. I looked at the change of these lines and
they date back to this commit.

fe645f822d (Panu Matilainen 2023-05-04 11:59:36 +0300 136)      lastUname =
rfree(lastUname);

commit fe645f822dbd71da4145f6174e526a09eb5c815e
Author: Panu Matilainen <pmati...@redhat.com>
Date:   Thu May 4 11:59:36 2023 +0300

    Simplify rpmug caching

    The simple cache whose efficiency troubled ewt back in 1997
    (see commit 97999ce92c1cad3315d85c02bb3c62007a75d846)
    has proven more than adequate over the years.

    In a local testcase based on Fedora 33 server iso contents, an install
    of 1765 packages consisting of 201344 files did a whopping 27 user +
    groups combined. So a few more alloc+free is not going to make the
    damnest difference, don't bother with reallocing the cache buffer, just
    strdup() a new one when needed.

And the code before that was gnarlier from days of yore.



> > isn't referred to (but not sure if an optimization would have removed
> it. The
> > comment before this code mentions that this is a hack to try and get
> things
> > done.. probably from long long ago when rpm was single threaded.
>
> The problem is in all of these functions. It's the same problem with all
> of
> them. Here's rpmugUname(), for example. You have two execution threads
> traversing that nest of "if" statements and all of them winding up here:
>
>     } else {
>         char *uname = NULL;
>
>         if (lookup_str(pwfile(), uid, 2, 0, &uname))
>             return NULL;
>
>         lastUid = uid;
>         free(lastUname);
>
> And now both execution threads will try to free() the same pointer.
>
> The next statement resets lastUname to the newly-allocated uname, but
> it's
> too late. If the code that executes in parallel calls rpmugUname, then
> just
> say good night.
>
> All of the static variables in all of the functions here must have a
> mutex
> wrapped around them.
>
> Or declared with a __thread attribute.
>
> The window of vulnerability is very tiny. But I have 32 cores and have 32
> execution threads churning. They have about a 5% chance of hitting the
> double-free on every build. Worse, I can see how this race condition may
> not
> result in a crash but produce a corrupted rpm.
>
>
That is ugly. The only mention of mutexes I found

lib/package.c
rpmio/macro.c
rpmio/rpmlog.c

The entries for __thread I found come in around 2019. Did you have a
bugzilla or a report on https://github.com/rpm-software-management/rpm/
which I can add anything I find?


and most date back from 2013.
-- 
Stephen Smoogen, Red Hat Automotive
Let us be kind to one another, for most of us are fighting a hard battle.
-- Ian MacClaren
--
_______________________________________________
devel mailing list -- devel@lists.fedoraproject.org
To unsubscribe send an email to devel-le...@lists.fedoraproject.org
Fedora Code of Conduct: 
https://docs.fedoraproject.org/en-US/project/code-of-conduct/
List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines
List Archives: 
https://lists.fedoraproject.org/archives/list/devel@lists.fedoraproject.org
Do not reply to spam, report it: 
https://pagure.io/fedora-infrastructure/new_issue

Reply via email to