@@ -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:
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.nault@alphalink.fr> --- drivers/net/ppp/ppp_generic.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-)