diff options
Diffstat (limited to 'drivers/net/ppp/ppp_synctty.c')
| -rw-r--r-- | drivers/net/ppp/ppp_synctty.c | 72 |
1 files changed, 33 insertions, 39 deletions
diff --git a/drivers/net/ppp/ppp_synctty.c b/drivers/net/ppp/ppp_synctty.c index d02ba2494d93..9c4932198931 100644 --- a/drivers/net/ppp/ppp_synctty.c +++ b/drivers/net/ppp/ppp_synctty.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * PPP synchronous tty channel driver for Linux. * @@ -15,11 +16,6 @@ * * Also touched by the grubby hands of Paul Fulghum paulkf@microgate.com * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * * This driver provides the encapsulation and framing for sending * and receiving PPP frames over sync serial lines. It relies on * the generic PPP layer to give it frames to send and to process @@ -47,7 +43,7 @@ #include <linux/interrupt.h> #include <linux/slab.h> #include <linux/refcount.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <linux/uaccess.h> #define PPP_VERSION "2.4.2" @@ -94,11 +90,11 @@ static struct sk_buff* ppp_sync_txmunge(struct syncppp *ap, struct sk_buff *); static int ppp_sync_send(struct ppp_channel *chan, struct sk_buff *skb); static int ppp_sync_ioctl(struct ppp_channel *chan, unsigned int cmd, unsigned long arg); -static void ppp_sync_process(unsigned long arg); +static void ppp_sync_process(struct tasklet_struct *t); static int ppp_sync_push(struct syncppp *ap); static void ppp_sync_flush_output(struct syncppp *ap); -static void ppp_sync_input(struct syncppp *ap, const unsigned char *buf, - char *flags, int count); +static void ppp_sync_input(struct syncppp *ap, const u8 *buf, const u8 *flags, + int count); static const struct ppp_channel_ops sync_ops = { .start_xmit = ppp_sync_send, @@ -181,7 +177,7 @@ ppp_sync_open(struct tty_struct *tty) ap->raccm = ~0U; skb_queue_head_init(&ap->rqueue); - tasklet_init(&ap->tsk, ppp_sync_process, (unsigned long) ap); + tasklet_setup(&ap->tsk, ppp_sync_process); refcount_set(&ap->refcnt, 1); init_completion(&ap->dead_cmp); @@ -249,10 +245,9 @@ ppp_sync_close(struct tty_struct *tty) * Wait for I/O to driver to complete and unregister PPP channel. * This is already done by the close routine, so just call that. */ -static int ppp_sync_hangup(struct tty_struct *tty) +static void ppp_sync_hangup(struct tty_struct *tty) { ppp_sync_close(tty); - return 0; } /* @@ -260,8 +255,8 @@ static int ppp_sync_hangup(struct tty_struct *tty) * Pppd reads and writes packets via /dev/ppp instead. */ static ssize_t -ppp_sync_read(struct tty_struct *tty, struct file *file, - unsigned char __user *buf, size_t count) +ppp_sync_read(struct tty_struct *tty, struct file *file, u8 *buf, size_t count, + void **cookie, unsigned long offset) { return -EAGAIN; } @@ -271,15 +266,14 @@ ppp_sync_read(struct tty_struct *tty, struct file *file, * from the ppp generic stuff. */ static ssize_t -ppp_sync_write(struct tty_struct *tty, struct file *file, - const unsigned char *buf, size_t count) +ppp_sync_write(struct tty_struct *tty, struct file *file, const u8 *buf, + size_t count) { return -EAGAIN; } static int -ppp_synctty_ioctl(struct tty_struct *tty, struct file *file, - unsigned int cmd, unsigned long arg) +ppp_synctty_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { struct syncppp *ap = sp_get(tty); int __user *p = (int __user *)arg; @@ -307,7 +301,7 @@ ppp_synctty_ioctl(struct tty_struct *tty, struct file *file, /* flush our buffers and the serial port's buffer */ if (arg == TCIOFLUSH || arg == TCOFLUSH) ppp_sync_flush_output(ap); - err = n_tty_ioctl_helper(tty, file, cmd, arg); + err = n_tty_ioctl_helper(tty, cmd, arg); break; case FIONREAD: @@ -318,7 +312,7 @@ ppp_synctty_ioctl(struct tty_struct *tty, struct file *file, break; default: - err = tty_mode_ioctl(tty, file, cmd, arg); + err = tty_mode_ioctl(tty, cmd, arg); break; } @@ -326,17 +320,10 @@ ppp_synctty_ioctl(struct tty_struct *tty, struct file *file, return err; } -/* No kernel lock - fine */ -static __poll_t -ppp_sync_poll(struct tty_struct *tty, struct file *file, poll_table *wait) -{ - return 0; -} - /* May sleep, don't call from interrupt level or with interrupts disabled */ static void -ppp_sync_receive(struct tty_struct *tty, const unsigned char *buf, - char *cflags, int count) +ppp_sync_receive(struct tty_struct *tty, const u8 *buf, const u8 *cflags, + size_t count) { struct syncppp *ap = sp_get(tty); unsigned long flags; @@ -368,7 +355,7 @@ ppp_sync_wakeup(struct tty_struct *tty) static struct tty_ldisc_ops ppp_sync_ldisc = { .owner = THIS_MODULE, - .magic = TTY_LDISC_MAGIC, + .num = N_SYNC_PPP, .name = "pppsync", .open = ppp_sync_open, .close = ppp_sync_close, @@ -376,7 +363,6 @@ static struct tty_ldisc_ops ppp_sync_ldisc = { .read = ppp_sync_read, .write = ppp_sync_write, .ioctl = ppp_synctty_ioctl, - .poll = ppp_sync_poll, .receive_buf = ppp_sync_receive, .write_wakeup = ppp_sync_wakeup, }; @@ -386,7 +372,7 @@ ppp_sync_init(void) { int err; - err = tty_register_ldisc(N_SYNC_PPP, &ppp_sync_ldisc); + err = tty_register_ldisc(&ppp_sync_ldisc); if (err != 0) printk(KERN_ERR "PPP_sync: error %d registering line disc.\n", err); @@ -467,6 +453,10 @@ ppp_sync_ioctl(struct ppp_channel *chan, unsigned int cmd, unsigned long arg) case PPPIOCSMRU: if (get_user(val, (int __user *) argp)) break; + if (val > U16_MAX) { + err = -EINVAL; + break; + } if (val < PPP_MRU) val = PPP_MRU; ap->mru = val; @@ -484,9 +474,9 @@ ppp_sync_ioctl(struct ppp_channel *chan, unsigned int cmd, unsigned long arg) * to the ppp_generic code, and to tell the ppp_generic code * if we can accept more output now. */ -static void ppp_sync_process(unsigned long arg) +static void ppp_sync_process(struct tasklet_struct *t) { - struct syncppp *ap = (struct syncppp *) arg; + struct syncppp *ap = from_tasklet(ap, t, tsk); struct sk_buff *skb; /* process received packets */ @@ -516,6 +506,11 @@ ppp_sync_txmunge(struct syncppp *ap, struct sk_buff *skb) unsigned char *data; int islcp; + /* Ensure we can safely access protocol field and LCP code */ + if (!pskb_may_pull(skb, 3)) { + kfree_skb(skb); + return NULL; + } data = skb->data; proto = get_unaligned_be16(data); @@ -668,8 +663,7 @@ ppp_sync_flush_output(struct syncppp *ap) * frame is considered to be in error and is tossed. */ static void -ppp_sync_input(struct syncppp *ap, const unsigned char *buf, - char *flags, int count) +ppp_sync_input(struct syncppp *ap, const u8 *buf, const u8 *flags, int count) { struct sk_buff *skb; unsigned char *p; @@ -702,7 +696,7 @@ ppp_sync_input(struct syncppp *ap, const unsigned char *buf, /* strip address/control field if present */ p = skb->data; - if (p[0] == PPP_ALLSTATIONS && p[1] == PPP_UI) { + if (skb->len >= 2 && p[0] == PPP_ALLSTATIONS && p[1] == PPP_UI) { /* chop off address/control */ if (skb->len < 3) goto err; @@ -730,11 +724,11 @@ err: static void __exit ppp_sync_cleanup(void) { - if (tty_unregister_ldisc(N_SYNC_PPP) != 0) - printk(KERN_ERR "failed to unregister Sync PPP line discipline\n"); + tty_unregister_ldisc(&ppp_sync_ldisc); } module_init(ppp_sync_init); module_exit(ppp_sync_cleanup); +MODULE_DESCRIPTION("PPP synchronous TTY channel module"); MODULE_LICENSE("GPL"); MODULE_ALIAS_LDISC(N_SYNC_PPP); |
