[Swan-dev] race condition in free_root_certs()

Andrew Cagney andrew.cagney at gmail.com
Sat May 1 22:49:57 UTC 2021


On Sat, 1 May 2021 at 15:51, D. Hugh Redelmeier <hugh at mimosa.com> wrote:

> The only place where I notice a refcnt_t manipulated without a lock is
> in free_root_certs.
>
>
Oops, yea.  I don't think it is a problem (but could certainly do with more
notes).  free_root_certs() is called:

- during shutdown and after all the crypto has been cleaned up
-> there should be no helper threads
-> there should be no other references
if this isn't the case then, oops, stumble on - we're going down

- when pluto is idle (as in no request for root certs has happened for 5
minutes)
-> having a structure sit on a reference for 5 minutes is a bug (or I'm
debugging a crypto thread :-)

In the latter case, this kicks in:

        /*
         * Deal with a helper thread being stuck (because it is being
debugged?);
         * need to peek at the refcnt.
         */
        if (root_cert_db->refcnt.count > 1) {
                llog(RC_LOG, logger, "root certs still in use; suspect
stuck thread");
                /* extend or set cert cache lifetime */
                schedule_oneshot_timer(EVENT_FREE_ROOT_CERTS,
FREE_ROOT_CERTS_TIMEOUT);
                return;
        }

Should the race you describe occur, then the next free_root-certs() call in
5 minutes will fix things up.

With that in mind, all I think is needed is a function returning the
refcnt, or even just return that more than one thing is using the object.

(sometimes I wonder if refcnt and the memory allocator should be merged)

One problem is that the refcount can change between being observed and
> the action that is affected by the observation.
>
> Another is that the actual refcnt member isn't guaranteed to be
> atomic.  If all operations were serialized by the mutex, this would
> not be a problem.
>
> The unprotected observation is a test to see if there will be any
> remaining references after this reference is deleted.
>
> It would be simple to change root_certs_delref() to safely return the
> necessary information.  I've actually started to do that.
>
> But it is a little bit awkward that the existing code does not delete
> the reference if the count was larger than one.  My simple change does
> delete the reference.
>
> I guess that the brute-force fix would be to add a function
> "refcnt_delref_if_only".  It doesn't feel optimal.
>
> What's the right fix?
> _______________________________________________
> Swan-dev mailing list
> Swan-dev at lists.libreswan.org
> https://lists.libreswan.org/mailman/listinfo/swan-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.libreswan.org/pipermail/swan-dev/attachments/20210501/ed21d162/attachment.html>


More information about the Swan-dev mailing list