diff options
Diffstat (limited to 'drivers/net/ppp')
-rw-r--r-- | drivers/net/ppp/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/ppp/ppp_async.c | 10 | ||||
-rw-r--r-- | drivers/net/ppp/ppp_generic.c | 44 | ||||
-rw-r--r-- | drivers/net/ppp/ppp_mppe.h | 1 | ||||
-rw-r--r-- | drivers/net/ppp/ppp_synctty.c | 11 |
5 files changed, 47 insertions, 20 deletions
diff --git a/drivers/net/ppp/Makefile b/drivers/net/ppp/Makefile index a6b6297b0066..16c457d6b324 100644 --- a/drivers/net/ppp/Makefile +++ b/drivers/net/ppp/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # Makefile for the Linux PPP network device drivers. # diff --git a/drivers/net/ppp/ppp_async.c b/drivers/net/ppp/ppp_async.c index 814fd8fae67d..1b28e6e702f5 100644 --- a/drivers/net/ppp/ppp_async.c +++ b/drivers/net/ppp/ppp_async.c @@ -69,7 +69,7 @@ struct asyncppp { struct tasklet_struct tsk; - atomic_t refcnt; + refcount_t refcnt; struct semaphore dead_sem; struct ppp_channel chan; /* interface to generic ppp layer */ unsigned char obuf[OBUFSIZE]; @@ -140,14 +140,14 @@ static struct asyncppp *ap_get(struct tty_struct *tty) read_lock(&disc_data_lock); ap = tty->disc_data; if (ap != NULL) - atomic_inc(&ap->refcnt); + refcount_inc(&ap->refcnt); read_unlock(&disc_data_lock); return ap; } static void ap_put(struct asyncppp *ap) { - if (atomic_dec_and_test(&ap->refcnt)) + if (refcount_dec_and_test(&ap->refcnt)) up(&ap->dead_sem); } @@ -185,7 +185,7 @@ ppp_asynctty_open(struct tty_struct *tty) skb_queue_head_init(&ap->rqueue); tasklet_init(&ap->tsk, ppp_async_process, (unsigned long) ap); - atomic_set(&ap->refcnt, 1); + refcount_set(&ap->refcnt, 1); sema_init(&ap->dead_sem, 0); ap->chan.private = ap; @@ -234,7 +234,7 @@ ppp_asynctty_close(struct tty_struct *tty) * our channel ops (i.e. ppp_async_send/ioctl) are in progress * by the time it returns. */ - if (!atomic_dec_and_test(&ap->refcnt)) + if (!refcount_dec_and_test(&ap->refcnt)) down(&ap->dead_sem); tasklet_kill(&ap->tsk); diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c index a404552555d4..d8e5747ff4e3 100644 --- a/drivers/net/ppp/ppp_generic.c +++ b/drivers/net/ppp/ppp_generic.c @@ -51,6 +51,7 @@ #include <asm/unaligned.h> #include <net/slhc_vj.h> #include <linux/atomic.h> +#include <linux/refcount.h> #include <linux/nsproxy.h> #include <net/net_namespace.h> @@ -84,7 +85,7 @@ struct ppp_file { struct sk_buff_head xq; /* pppd transmit queue */ struct sk_buff_head rq; /* receive queue for pppd */ wait_queue_head_t rwait; /* for poll on reading /dev/ppp */ - atomic_t refcnt; /* # refs (incl /dev/ppp attached) */ + refcount_t refcnt; /* # refs (incl /dev/ppp attached) */ int hdrlen; /* space to leave for headers */ int index; /* interface unit / channel number */ int dead; /* unit/channel has been shut down */ @@ -120,7 +121,7 @@ struct ppp { int n_channels; /* how many channels are attached 54 */ spinlock_t rlock; /* lock for receive side 58 */ spinlock_t wlock; /* lock for transmit side 5c */ - int *xmit_recursion __percpu; /* xmit recursion detect */ + int __percpu *xmit_recursion; /* xmit recursion detect */ int mru; /* max receive unit 60 */ unsigned int flags; /* control bits 64 */ unsigned int xstate; /* transmit state bits 68 */ @@ -389,7 +390,7 @@ static int ppp_open(struct inode *inode, struct file *file) /* * This could (should?) be enforced by the permissions on /dev/ppp. */ - if (!capable(CAP_NET_ADMIN)) + if (!ns_capable(file->f_cred->user_ns, CAP_NET_ADMIN)) return -EPERM; return 0; } @@ -408,7 +409,7 @@ static int ppp_release(struct inode *unused, struct file *file) unregister_netdevice(ppp->dev); rtnl_unlock(); } - if (atomic_dec_and_test(&pf->refcnt)) { + if (refcount_dec_and_test(&pf->refcnt)) { switch (pf->kind) { case INTERFACE: ppp_destroy_interface(PF_TO_PPP(pf)); @@ -881,7 +882,7 @@ static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf, mutex_lock(&pn->all_ppp_mutex); ppp = ppp_find_unit(pn, unit); if (ppp) { - atomic_inc(&ppp->file.refcnt); + refcount_inc(&ppp->file.refcnt); file->private_data = &ppp->file; err = 0; } @@ -896,7 +897,7 @@ static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf, spin_lock_bh(&pn->all_channels_lock); chan = ppp_find_channel(pn, unit); if (chan) { - atomic_inc(&chan->file.refcnt); + refcount_inc(&chan->file.refcnt); file->private_data = &chan->file; err = 0; } @@ -959,7 +960,10 @@ static __net_exit void ppp_exit_net(struct net *net) unregister_netdevice_many(&list); rtnl_unlock(); + mutex_destroy(&pn->all_ppp_mutex); idr_destroy(&pn->units_idr); + WARN_ON_ONCE(!list_empty(&pn->all_channels)); + WARN_ON_ONCE(!list_empty(&pn->new_channels)); } static struct pernet_operations ppp_net_ops = { @@ -1339,7 +1343,17 @@ ppp_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats64) static int ppp_dev_init(struct net_device *dev) { + struct ppp *ppp; + netdev_lockdep_set_classes(dev); + + ppp = netdev_priv(dev); + /* Let the netdevice take a reference on the ppp file. This ensures + * that ppp_destroy_interface() won't run before the device gets + * unregistered. + */ + refcount_inc(&ppp->file.refcnt); + return 0; } @@ -1362,6 +1376,15 @@ static void ppp_dev_uninit(struct net_device *dev) wake_up_interruptible(&ppp->file.rwait); } +static void ppp_dev_priv_destructor(struct net_device *dev) +{ + struct ppp *ppp; + + ppp = netdev_priv(dev); + if (refcount_dec_and_test(&ppp->file.refcnt)) + ppp_destroy_interface(ppp); +} + static const struct net_device_ops ppp_netdev_ops = { .ndo_init = ppp_dev_init, .ndo_uninit = ppp_dev_uninit, @@ -1387,6 +1410,7 @@ static void ppp_setup(struct net_device *dev) dev->tx_queue_len = 3; dev->type = ARPHRD_PPP; dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; + dev->priv_destructor = ppp_dev_priv_destructor; netif_keep_dst(dev); } @@ -2656,7 +2680,7 @@ ppp_unregister_channel(struct ppp_channel *chan) pch->file.dead = 1; wake_up_interruptible(&pch->file.rwait); - if (atomic_dec_and_test(&pch->file.refcnt)) + if (refcount_dec_and_test(&pch->file.refcnt)) ppp_destroy_channel(pch); } @@ -3026,7 +3050,7 @@ init_ppp_file(struct ppp_file *pf, int kind) pf->kind = kind; skb_queue_head_init(&pf->xq); skb_queue_head_init(&pf->rq); - atomic_set(&pf->refcnt, 1); + refcount_set(&pf->refcnt, 1); init_waitqueue_head(&pf->rwait); } @@ -3144,7 +3168,7 @@ ppp_connect_channel(struct channel *pch, int unit) list_add_tail(&pch->clist, &ppp->channels); ++ppp->n_channels; pch->ppp = ppp; - atomic_inc(&ppp->file.refcnt); + refcount_inc(&ppp->file.refcnt); ppp_unlock(ppp); ret = 0; @@ -3175,7 +3199,7 @@ ppp_disconnect_channel(struct channel *pch) if (--ppp->n_channels == 0) wake_up_interruptible(&ppp->file.rwait); ppp_unlock(ppp); - if (atomic_dec_and_test(&ppp->file.refcnt)) + if (refcount_dec_and_test(&ppp->file.refcnt)) ppp_destroy_interface(ppp); err = 0; } diff --git a/drivers/net/ppp/ppp_mppe.h b/drivers/net/ppp/ppp_mppe.h index 7a14e058c668..677b3b3f7425 100644 --- a/drivers/net/ppp/ppp_mppe.h +++ b/drivers/net/ppp/ppp_mppe.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #define MPPE_PAD 4 /* MPPE growth per frame */ #define MPPE_MAX_KEY_LEN 16 /* largest key length (128-bit) */ diff --git a/drivers/net/ppp/ppp_synctty.c b/drivers/net/ppp/ppp_synctty.c index 7868c29071d4..7196f00f0991 100644 --- a/drivers/net/ppp/ppp_synctty.c +++ b/drivers/net/ppp/ppp_synctty.c @@ -46,6 +46,7 @@ #include <linux/init.h> #include <linux/interrupt.h> #include <linux/slab.h> +#include <linux/refcount.h> #include <asm/unaligned.h> #include <linux/uaccess.h> @@ -72,7 +73,7 @@ struct syncppp { struct tasklet_struct tsk; - atomic_t refcnt; + refcount_t refcnt; struct completion dead_cmp; struct ppp_channel chan; /* interface to generic ppp layer */ }; @@ -141,14 +142,14 @@ static struct syncppp *sp_get(struct tty_struct *tty) read_lock(&disc_data_lock); ap = tty->disc_data; if (ap != NULL) - atomic_inc(&ap->refcnt); + refcount_inc(&ap->refcnt); read_unlock(&disc_data_lock); return ap; } static void sp_put(struct syncppp *ap) { - if (atomic_dec_and_test(&ap->refcnt)) + if (refcount_dec_and_test(&ap->refcnt)) complete(&ap->dead_cmp); } @@ -182,7 +183,7 @@ ppp_sync_open(struct tty_struct *tty) skb_queue_head_init(&ap->rqueue); tasklet_init(&ap->tsk, ppp_sync_process, (unsigned long) ap); - atomic_set(&ap->refcnt, 1); + refcount_set(&ap->refcnt, 1); init_completion(&ap->dead_cmp); ap->chan.private = ap; @@ -232,7 +233,7 @@ ppp_sync_close(struct tty_struct *tty) * our channel ops (i.e. ppp_sync_send/ioctl) are in progress * by the time it returns. */ - if (!atomic_dec_and_test(&ap->refcnt)) + if (!refcount_dec_and_test(&ap->refcnt)) wait_for_completion(&ap->dead_cmp); tasklet_kill(&ap->tsk); |