From a36159eec6ca17402b0e146b86efaf76568dc353 Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Fri, 20 Sep 2024 01:41:23 +0000 Subject: [PATCH] 重命名 AX88772C_eeprom/asix.c 为 asix_mac.c --- kernel/drivers/net/ppp/ppp_generic.c | 264 ++++++++++++++++++++++++++++++++++------------------ 1 files changed, 172 insertions(+), 92 deletions(-) diff --git a/kernel/drivers/net/ppp/ppp_generic.c b/kernel/drivers/net/ppp/ppp_generic.c index 61de03c..b825c6a 100644 --- a/kernel/drivers/net/ppp/ppp_generic.c +++ b/kernel/drivers/net/ppp/ppp_generic.c @@ -1,12 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Generic PPP layer for Linux. * * Copyright 1999-2002 Paul Mackerras. - * - * 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. * * The generic PPP layer handles the PPP network interfaces, the * /dev/ppp device, packet and VJ compression, and multilink. @@ -276,7 +272,7 @@ static struct sk_buff *ppp_mp_reconstruct(struct ppp *ppp); static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb); #endif /* CONFIG_PPP_MULTILINK */ -static int ppp_set_compress(struct ppp *ppp, unsigned long arg); +static int ppp_set_compress(struct ppp *ppp, struct ppp_option_data *data); static void ppp_ccp_peek(struct ppp *ppp, struct sk_buff *skb, int inbound); static void ppp_ccp_closed(struct ppp *ppp); static struct compressor *find_compressor(int type); @@ -302,8 +298,6 @@ /* per net-namespace data */ static inline struct ppp_net *ppp_pernet(struct net *net) { - BUG_ON(!net); - return net_generic(net, ppp_net_id); } @@ -563,36 +557,67 @@ } #ifdef CONFIG_PPP_FILTER -static int get_filter(void __user *arg, struct sock_filter **p) +static struct bpf_prog *get_filter(struct sock_fprog *uprog) +{ + struct sock_fprog_kern fprog; + struct bpf_prog *res = NULL; + int err; + + if (!uprog->len) + return NULL; + + /* uprog->len is unsigned short, so no overflow here */ + fprog.len = uprog->len; + fprog.filter = memdup_user(uprog->filter, + uprog->len * sizeof(struct sock_filter)); + if (IS_ERR(fprog.filter)) + return ERR_CAST(fprog.filter); + + err = bpf_prog_create(&res, &fprog); + kfree(fprog.filter); + + return err ? ERR_PTR(err) : res; +} + +static struct bpf_prog *ppp_get_filter(struct sock_fprog __user *p) { struct sock_fprog uprog; - struct sock_filter *code = NULL; - int len; - if (copy_from_user(&uprog, arg, sizeof(uprog))) - return -EFAULT; - - if (!uprog.len) { - *p = NULL; - return 0; - } - - len = uprog.len * sizeof(struct sock_filter); - code = memdup_user(uprog.filter, len); - if (IS_ERR(code)) - return PTR_ERR(code); - - *p = code; - return uprog.len; + if (copy_from_user(&uprog, p, sizeof(struct sock_fprog))) + return ERR_PTR(-EFAULT); + return get_filter(&uprog); } -#endif /* CONFIG_PPP_FILTER */ + +#ifdef CONFIG_COMPAT +struct sock_fprog32 { + unsigned short len; + compat_caddr_t filter; +}; + +#define PPPIOCSPASS32 _IOW('t', 71, struct sock_fprog32) +#define PPPIOCSACTIVE32 _IOW('t', 70, struct sock_fprog32) + +static struct bpf_prog *compat_ppp_get_filter(struct sock_fprog32 __user *p) +{ + struct sock_fprog32 uprog32; + struct sock_fprog uprog; + + if (copy_from_user(&uprog32, p, sizeof(struct sock_fprog32))) + return ERR_PTR(-EFAULT); + uprog.len = uprog32.len; + uprog.filter = compat_ptr(uprog32.filter); + return get_filter(&uprog); +} +#endif +#endif static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct ppp_file *pf; struct ppp *ppp; int err = -EFAULT, val, val2, i; - struct ppp_idle idle; + struct ppp_idle32 idle32; + struct ppp_idle64 idle64; struct npioctl npi; int unit, cflags; struct slcompress *vj; @@ -688,9 +713,14 @@ break; case PPPIOCSCOMPRESS: - err = ppp_set_compress(ppp, arg); + { + struct ppp_option_data data; + if (copy_from_user(&data, argp, sizeof(data))) + err = -EFAULT; + else + err = ppp_set_compress(ppp, &data); break; - + } case PPPIOCGUNIT: if (put_user(ppp->file.index, p)) break; @@ -710,10 +740,18 @@ err = 0; break; - case PPPIOCGIDLE: - idle.xmit_idle = (jiffies - ppp->last_xmit) / HZ; - idle.recv_idle = (jiffies - ppp->last_recv) / HZ; - if (copy_to_user(argp, &idle, sizeof(idle))) + case PPPIOCGIDLE32: + idle32.xmit_idle = (jiffies - ppp->last_xmit) / HZ; + idle32.recv_idle = (jiffies - ppp->last_recv) / HZ; + if (copy_to_user(argp, &idle32, sizeof(idle32))) + break; + err = 0; + break; + + case PPPIOCGIDLE64: + idle64.xmit_idle = (jiffies - ppp->last_xmit) / HZ; + idle64.recv_idle = (jiffies - ppp->last_recv) / HZ; + if (copy_to_user(argp, &idle64, sizeof(idle64))) break; err = 0; break; @@ -762,55 +800,25 @@ #ifdef CONFIG_PPP_FILTER case PPPIOCSPASS: - { - struct sock_filter *code; - - err = get_filter(argp, &code); - if (err >= 0) { - struct bpf_prog *pass_filter = NULL; - struct sock_fprog_kern fprog = { - .len = err, - .filter = code, - }; - - err = 0; - if (fprog.filter) - err = bpf_prog_create(&pass_filter, &fprog); - if (!err) { - ppp_lock(ppp); - if (ppp->pass_filter) - bpf_prog_destroy(ppp->pass_filter); - ppp->pass_filter = pass_filter; - ppp_unlock(ppp); - } - kfree(code); - } - break; - } case PPPIOCSACTIVE: { - struct sock_filter *code; + struct bpf_prog *filter = ppp_get_filter(argp); + struct bpf_prog **which; - err = get_filter(argp, &code); - if (err >= 0) { - struct bpf_prog *active_filter = NULL; - struct sock_fprog_kern fprog = { - .len = err, - .filter = code, - }; - - err = 0; - if (fprog.filter) - err = bpf_prog_create(&active_filter, &fprog); - if (!err) { - ppp_lock(ppp); - if (ppp->active_filter) - bpf_prog_destroy(ppp->active_filter); - ppp->active_filter = active_filter; - ppp_unlock(ppp); - } - kfree(code); + if (IS_ERR(filter)) { + err = PTR_ERR(filter); + break; } + if (cmd == PPPIOCSPASS) + which = &ppp->pass_filter; + else + which = &ppp->active_filter; + ppp_lock(ppp); + if (*which) + bpf_prog_destroy(*which); + *which = filter; + ppp_unlock(ppp); + err = 0; break; } #endif /* CONFIG_PPP_FILTER */ @@ -835,6 +843,77 @@ return err; } + +#ifdef CONFIG_COMPAT +struct ppp_option_data32 { + compat_uptr_t ptr; + u32 length; + compat_int_t transmit; +}; +#define PPPIOCSCOMPRESS32 _IOW('t', 77, struct ppp_option_data32) + +static long ppp_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct ppp_file *pf; + int err = -ENOIOCTLCMD; + void __user *argp = (void __user *)arg; + + mutex_lock(&ppp_mutex); + + pf = file->private_data; + if (pf && pf->kind == INTERFACE) { + struct ppp *ppp = PF_TO_PPP(pf); + switch (cmd) { +#ifdef CONFIG_PPP_FILTER + case PPPIOCSPASS32: + case PPPIOCSACTIVE32: + { + struct bpf_prog *filter = compat_ppp_get_filter(argp); + struct bpf_prog **which; + + if (IS_ERR(filter)) { + err = PTR_ERR(filter); + break; + } + if (cmd == PPPIOCSPASS32) + which = &ppp->pass_filter; + else + which = &ppp->active_filter; + ppp_lock(ppp); + if (*which) + bpf_prog_destroy(*which); + *which = filter; + ppp_unlock(ppp); + err = 0; + break; + } +#endif /* CONFIG_PPP_FILTER */ + case PPPIOCSCOMPRESS32: + { + struct ppp_option_data32 data32; + if (copy_from_user(&data32, argp, sizeof(data32))) { + err = -EFAULT; + } else { + struct ppp_option_data data = { + .ptr = compat_ptr(data32.ptr), + .length = data32.length, + .transmit = data32.transmit + }; + err = ppp_set_compress(ppp, &data); + } + break; + } + } + } + mutex_unlock(&ppp_mutex); + + /* all other commands have compatible arguments */ + if (err == -ENOIOCTLCMD) + err = ppp_ioctl(file, cmd, (unsigned long)compat_ptr(arg)); + + return err; +} +#endif static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf, struct file *file, unsigned int cmd, unsigned long arg) @@ -904,6 +983,9 @@ .write = ppp_write, .poll = ppp_poll, .unlocked_ioctl = ppp_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = ppp_compat_ioctl, +#endif .open = ppp_open, .release = ppp_release, .llseek = noop_llseek, @@ -1527,6 +1609,8 @@ struct sk_buff *new_skb; int len; unsigned char *cp; + + skb->dev = ppp->dev; if (proto < 0x8000) { #ifdef CONFIG_PPP_FILTER @@ -2466,7 +2550,7 @@ if (ppp->mrru == 0) /* do nothing until mrru is set */ return NULL; - head = list->next; + head = __skb_peek(list); tail = NULL; skb_queue_walk_safe(list, p, tmp) { again: @@ -2756,24 +2840,20 @@ /* Process the PPPIOCSCOMPRESS ioctl. */ static int -ppp_set_compress(struct ppp *ppp, unsigned long arg) +ppp_set_compress(struct ppp *ppp, struct ppp_option_data *data) { - int err; + int err = -EFAULT; struct compressor *cp, *ocomp; - struct ppp_option_data data; void *state, *ostate; unsigned char ccp_option[CCP_MAX_OPTION_LENGTH]; - err = -EFAULT; - if (copy_from_user(&data, (void __user *) arg, sizeof(data))) + if (data->length > CCP_MAX_OPTION_LENGTH) goto out; - if (data.length > CCP_MAX_OPTION_LENGTH) - goto out; - if (copy_from_user(ccp_option, (void __user *) data.ptr, data.length)) + if (copy_from_user(ccp_option, data->ptr, data->length)) goto out; err = -EINVAL; - if (data.length < 2 || ccp_option[1] < 2 || ccp_option[1] > data.length) + if (data->length < 2 || ccp_option[1] < 2 || ccp_option[1] > data->length) goto out; cp = try_then_request_module( @@ -2783,8 +2863,8 @@ goto out; err = -ENOBUFS; - if (data.transmit) { - state = cp->comp_alloc(ccp_option, data.length); + if (data->transmit) { + state = cp->comp_alloc(ccp_option, data->length); if (state) { ppp_xmit_lock(ppp); ppp->xstate &= ~SC_COMP_RUN; @@ -2802,7 +2882,7 @@ module_put(cp->owner); } else { - state = cp->decomp_alloc(ccp_option, data.length); + state = cp->decomp_alloc(ccp_option, data->length); if (state) { ppp_recv_lock(ppp); ppp->rstate &= ~SC_DECOMP_RUN; -- Gitblit v1.6.2