ppp->npmode is read by ppp_ioctl(), ppp_receive_nonmp_frame() and ppp_start_xmit(). But it is only modified by ppp_ioctl(). However, the only protected access is done by ppp_receive_nonmp_frame() which runs under ppp_recv_lock() protection.
We could protect ppp->npmode with ppp_recv_lock() in ppp_start_xmit() too, but taking the recv lock in the xmit path would look strange. So this patch takes the xmit lock instead and holds both locks before writing in ppp_ioctl(). Signed-off-by: Guillaume Nault <g.na...@alphalink.fr> --- drivers/net/ppp/ppp_generic.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c index 24777f4..2eb39cd 100644 --- a/drivers/net/ppp/ppp_generic.c +++ b/drivers/net/ppp/ppp_generic.c @@ -767,11 +767,18 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) i = err; if (cmd == PPPIOCGNPMODE) { err = -EFAULT; + + ppp_lock(ppp); npi.mode = ppp->npmode[i]; + ppp_unlock(ppp); + if (copy_to_user(argp, &npi, sizeof(npi))) break; } else { + ppp_lock(ppp); ppp->npmode[i] = npi.mode; + ppp_unlock(ppp); + /* we may be able to transmit more packets now (??) */ netif_wake_queue(ppp->dev); } @@ -1023,13 +1030,18 @@ ppp_start_xmit(struct sk_buff *skb, struct net_device *dev) struct ppp *ppp = netdev_priv(dev); int npi, proto; unsigned char *pp; + enum NPmode npmode; npi = ethertype_to_npindex(ntohs(skb->protocol)); if (npi < 0) goto outf; + ppp_xmit_lock(ppp); + npmode = ppp->npmode[npi]; + ppp_xmit_unlock(ppp); + /* Drop, accept or reject the packet */ - switch (ppp->npmode[npi]) { + switch (npmode) { case NPMODE_PASS: break; case NPMODE_QUEUE: -- 2.7.0