Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

syncppp: Fix crashes.

The syncppp layer wants a mid-level netdev private pointer.

It was using netdev->priv but that only worked by accident,
and thus this scheme was broken when the device private
allocation strategy changed.

Add a proper mid-layer private pointer for uses like this,
update syncppp and all users, and remove the HDLC_PPP broken
tag from drivers/net/wan/Kconfig

Signed-off-by: David S. Miller <davem@davemloft.net>

+21 -18
+1 -3
drivers/net/wan/Kconfig
··· 150 150 151 151 config HDLC_PPP 152 152 tristate "Synchronous Point-to-Point Protocol (PPP) support" 153 - depends on HDLC && BROKEN 153 + depends on HDLC 154 154 help 155 155 Generic HDLC driver supporting PPP over WAN connections. 156 - This module is currently broken and will cause a kernel panic 157 - when a device configured in PPP mode is activated. 158 156 159 157 It will be replaced by new PPP implementation in Linux 2.6.26. 160 158
+7 -7
drivers/net/wan/cosa.c
··· 629 629 d->base_addr = chan->cosa->datareg; 630 630 d->irq = chan->cosa->irq; 631 631 d->dma = chan->cosa->dma; 632 - d->priv = chan; 632 + d->ml_priv = chan; 633 633 sppp_attach(&chan->pppdev); 634 634 if (register_netdev(d)) { 635 635 printk(KERN_WARNING "%s: register_netdev failed.\n", d->name); ··· 650 650 651 651 static int cosa_sppp_open(struct net_device *d) 652 652 { 653 - struct channel_data *chan = d->priv; 653 + struct channel_data *chan = d->ml_priv; 654 654 int err; 655 655 unsigned long flags; 656 656 ··· 690 690 691 691 static int cosa_sppp_tx(struct sk_buff *skb, struct net_device *dev) 692 692 { 693 - struct channel_data *chan = dev->priv; 693 + struct channel_data *chan = dev->ml_priv; 694 694 695 695 netif_stop_queue(dev); 696 696 ··· 701 701 702 702 static void cosa_sppp_timeout(struct net_device *dev) 703 703 { 704 - struct channel_data *chan = dev->priv; 704 + struct channel_data *chan = dev->ml_priv; 705 705 706 706 if (test_bit(RXBIT, &chan->cosa->rxtx)) { 707 707 chan->stats.rx_errors++; ··· 720 720 721 721 static int cosa_sppp_close(struct net_device *d) 722 722 { 723 - struct channel_data *chan = d->priv; 723 + struct channel_data *chan = d->ml_priv; 724 724 unsigned long flags; 725 725 726 726 netif_stop_queue(d); ··· 800 800 801 801 static struct net_device_stats *cosa_net_stats(struct net_device *dev) 802 802 { 803 - struct channel_data *chan = dev->priv; 803 + struct channel_data *chan = dev->ml_priv; 804 804 return &chan->stats; 805 805 } 806 806 ··· 1217 1217 int cmd) 1218 1218 { 1219 1219 int rv; 1220 - struct channel_data *chan = dev->priv; 1220 + struct channel_data *chan = dev->ml_priv; 1221 1221 rv = cosa_ioctl_common(chan->cosa, chan, cmd, (unsigned long)ifr->ifr_data); 1222 1222 if (rv == -ENOIOCTLCMD) { 1223 1223 return sppp_do_ioctl(dev, ifr, cmd);
+1 -1
drivers/net/wan/hdlc_ppp.c
··· 45 45 int (*old_ioctl)(struct net_device *, struct ifreq *, int); 46 46 int result; 47 47 48 - dev->priv = &state(hdlc)->syncppp_ptr; 48 + dev->ml_priv = &state(hdlc)->syncppp_ptr; 49 49 state(hdlc)->syncppp_ptr = &state(hdlc)->pppdev; 50 50 state(hdlc)->pppdev.dev = dev; 51 51
+6 -6
drivers/net/wan/hostess_sv11.c
··· 75 75 76 76 static int hostess_open(struct net_device *d) 77 77 { 78 - struct sv11_device *sv11=d->priv; 78 + struct sv11_device *sv11=d->ml_priv; 79 79 int err = -1; 80 80 81 81 /* ··· 128 128 129 129 static int hostess_close(struct net_device *d) 130 130 { 131 - struct sv11_device *sv11=d->priv; 131 + struct sv11_device *sv11=d->ml_priv; 132 132 /* 133 133 * Discard new frames 134 134 */ ··· 159 159 160 160 static int hostess_ioctl(struct net_device *d, struct ifreq *ifr, int cmd) 161 161 { 162 - /* struct sv11_device *sv11=d->priv; 162 + /* struct sv11_device *sv11=d->ml_priv; 163 163 z8530_ioctl(d,&sv11->sync.chanA,ifr,cmd) */ 164 164 return sppp_do_ioctl(d, ifr,cmd); 165 165 } 166 166 167 167 static struct net_device_stats *hostess_get_stats(struct net_device *d) 168 168 { 169 - struct sv11_device *sv11=d->priv; 169 + struct sv11_device *sv11=d->ml_priv; 170 170 if(sv11) 171 171 return z8530_get_stats(&sv11->sync.chanA); 172 172 else ··· 179 179 180 180 static int hostess_queue_xmit(struct sk_buff *skb, struct net_device *d) 181 181 { 182 - struct sv11_device *sv11=d->priv; 182 + struct sv11_device *sv11=d->ml_priv; 183 183 return z8530_queue_xmit(&sv11->sync.chanA, skb); 184 184 } 185 185 ··· 325 325 /* 326 326 * Initialise the PPP components 327 327 */ 328 + d->ml_priv = sv; 328 329 sppp_attach(&sv->netdev); 329 330 330 331 /* ··· 334 333 335 334 d->base_addr = iobase; 336 335 d->irq = irq; 337 - d->priv = sv; 338 336 339 337 if(register_netdev(d)) 340 338 {
+1
drivers/net/wan/lmc/lmc_main.c
··· 891 891 892 892 /* Initialize the sppp layer */ 893 893 /* An ioctl can cause a subsequent detach for raw frame interface */ 894 + dev->ml_priv = sc; 894 895 sc->if_type = LMC_PPP; 895 896 sc->check = 0xBEAFCAFE; 896 897 dev->base_addr = pci_resource_start(pdev, 0);
+1
drivers/net/wan/sealevel.c
··· 241 241 return NULL; 242 242 243 243 sv = d->priv; 244 + d->ml_priv = sv; 244 245 sv->if_ptr = &sv->pppdev; 245 246 sv->pppdev.dev = d; 246 247 d->base_addr = iobase;
+3
include/linux/netdevice.h
··· 715 715 struct net *nd_net; 716 716 #endif 717 717 718 + /* mid-layer private */ 719 + void *ml_priv; 720 + 718 721 /* bridge stuff */ 719 722 struct net_bridge_port *br_port; 720 723 /* macvlan */
+1 -1
include/net/syncppp.h
··· 59 59 60 60 static inline struct sppp *sppp_of(struct net_device *dev) 61 61 { 62 - struct ppp_device **ppp = dev->priv; 62 + struct ppp_device **ppp = dev->ml_priv; 63 63 BUG_ON((*ppp)->dev != dev); 64 64 return &(*ppp)->sppp; 65 65 }