On Tue, Aug 17, 2021 at 11:39:26PM +0000, Taylor R Campbell wrote:
> > 
> > Log Message:
> > skip symbol tables that were unloaded again to avoid EFAULT when reading
> > ksyms.
> > 
> > also restore TAILQ_FOREACH idiom.
> 
> This change isn't quite right: Reading past st = ksyms_last_snapshot
> in ksymsread, or in any context where we rely on the snapshot without
> holding ksyms_lock, is not allowed -- it will lead to a corrupted view
> of the snapshot, and possibly end up reading uninitialized memory.
> 
> That's why this code didn't use TAILQ_FOREACH -- it must stop at
> ksyms_last_snapshot; if it gets to the end of the list, and witnesses
> st = NULL, then that's a bug.

TAILQ_FOREACH just adds another exit condition that prevents entering
the loop with st = NULL.

A problem might be to continue the loop in case ksyms_last_snapshot itself
is gone.

Something like:

        if (st->sd_gone)
                goto skip;
        ...
skip:
        if (st == ksyms_last_snapshot)
                break;

avoids that case.


> The code also didn't skip entries with st->sd_gone because we arrange
> for st->sd_nmap not to be freed until the last ksymsclose, at which
> point no more ksymsread can be active.

Keeping sd_nmap isn't sufficient, ksymsread failed with EFAULT as
you still derefence pointers to the unloaded module.
Skipping the unloaded module when reading the symbols avoids this.

Reply via email to