On 06/07/20(Mon) 16:42, Vitaliy Makkoveev wrote:
> [...] 
> pipex(4) is simultaneously locked by NET_LOCK() and KERNEL_LOCK() but
> with two exceptions:
> 
> 1. As you pointed pipex_pppoe_input() called without KERNEL_LOCK() held.
> 2. pppac_start() called without NET_LOCK() held. Or with NET_LOCK()
>    held. It depends on `if_snd' usage.
> 
> Diff below enforces pppac_start() to be called with NET_LOCK() held.
> Also all externally called pipex(4) input and output routines have
> NET_ASSERT_LOCKED() assertion.
> 
> Now pipex(4) is fully protected by NET_LOCK() so description of struct
> members chenget too.
> 
> Index: sys/net/if_pppx.c
> ===================================================================
> RCS file: /cvs/src/sys/net/if_pppx.c,v
> retrieving revision 1.90
> diff -u -p -r1.90 if_pppx.c
> --- sys/net/if_pppx.c 24 Jun 2020 08:52:53 -0000      1.90
> +++ sys/net/if_pppx.c 6 Jul 2020 11:10:17 -0000
> @@ -1117,6 +1117,8 @@ pppacopen(dev_t dev, int flags, int mode
>       ifp->if_output = pppac_output;
>       ifp->if_start = pppac_start;
>       ifp->if_ioctl = pppac_ioctl;
> +     /* XXXSMP: be sure pppac_start() called under NET_LOCK() */
> +     IFQ_SET_MAXLEN(&ifp->if_snd, 1);

Is it possible to grab the NET_LOCK() inside pppac_start() instead of
grabbing it outside?  This should allow *start() routine to be called
from any context.

It might be interesting to see that as a difference between the NET_LOCK()
used to protect the network stack internals and the NET_LOCK() used to
protect pipex(4) internals.  Such distinction might help to convert the
latter into a different lock or primitive.

> Index: sys/net/pipex.c
> ===================================================================
> RCS file: /cvs/src/sys/net/pipex.c,v
> retrieving revision 1.117
> diff -u -p -r1.117 pipex.c
> --- sys/net/pipex.c   30 Jun 2020 14:05:13 -0000      1.117
> +++ sys/net/pipex.c   6 Jul 2020 11:10:17 -0000
> @@ -869,6 +869,7 @@ pipex_output(struct mbuf *m0, int af, in
>       struct ip ip;
>       struct mbuf *mret;
>  
> +     NET_ASSERT_LOCKED();

This function doesn't touch any shared data structure, we'd better move
the NET_ASSERT_LOCKED() above rn_lookuo() in pipex_lookup_by_ip_address().

Note that `pipex_rd_head4' and `pipex_rd_head6' are, with this diff,
also protected by the NET_LOCK() and should be annotated as such.

>       session = NULL;
>       mret = NULL;
>       switch (af) {
> @@ -962,6 +963,8 @@ pipex_ppp_output(struct mbuf *m0, struct
>  {
>       u_char *cp, hdr[16];
>  
> +     NET_ASSERT_LOCKED();

Same here, it seems that the only reason the NET_LOCK() is necessary in
the output path is to prevent corruption of the `session' descriptor being
used.  So we'd rather put the assertion above the LIST_FOREACH(). 

Anyway all of those can be addressed later, your diff is ok mpi@

Reply via email to