hc
2024-09-20 a36159eec6ca17402b0e146b86efaf76568dc353
kernel/drivers/net/ppp/ppp_generic.c
....@@ -1,12 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Generic PPP layer for Linux.
34 *
45 * Copyright 1999-2002 Paul Mackerras.
5
- *
6
- * This program is free software; you can redistribute it and/or
7
- * modify it under the terms of the GNU General Public License
8
- * as published by the Free Software Foundation; either version
9
- * 2 of the License, or (at your option) any later version.
106 *
117 * The generic PPP layer handles the PPP network interfaces, the
128 * /dev/ppp device, packet and VJ compression, and multilink.
....@@ -276,7 +272,7 @@
276272 static struct sk_buff *ppp_mp_reconstruct(struct ppp *ppp);
277273 static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb);
278274 #endif /* CONFIG_PPP_MULTILINK */
279
-static int ppp_set_compress(struct ppp *ppp, unsigned long arg);
275
+static int ppp_set_compress(struct ppp *ppp, struct ppp_option_data *data);
280276 static void ppp_ccp_peek(struct ppp *ppp, struct sk_buff *skb, int inbound);
281277 static void ppp_ccp_closed(struct ppp *ppp);
282278 static struct compressor *find_compressor(int type);
....@@ -302,8 +298,6 @@
302298 /* per net-namespace data */
303299 static inline struct ppp_net *ppp_pernet(struct net *net)
304300 {
305
- BUG_ON(!net);
306
-
307301 return net_generic(net, ppp_net_id);
308302 }
309303
....@@ -563,36 +557,67 @@
563557 }
564558
565559 #ifdef CONFIG_PPP_FILTER
566
-static int get_filter(void __user *arg, struct sock_filter **p)
560
+static struct bpf_prog *get_filter(struct sock_fprog *uprog)
561
+{
562
+ struct sock_fprog_kern fprog;
563
+ struct bpf_prog *res = NULL;
564
+ int err;
565
+
566
+ if (!uprog->len)
567
+ return NULL;
568
+
569
+ /* uprog->len is unsigned short, so no overflow here */
570
+ fprog.len = uprog->len;
571
+ fprog.filter = memdup_user(uprog->filter,
572
+ uprog->len * sizeof(struct sock_filter));
573
+ if (IS_ERR(fprog.filter))
574
+ return ERR_CAST(fprog.filter);
575
+
576
+ err = bpf_prog_create(&res, &fprog);
577
+ kfree(fprog.filter);
578
+
579
+ return err ? ERR_PTR(err) : res;
580
+}
581
+
582
+static struct bpf_prog *ppp_get_filter(struct sock_fprog __user *p)
567583 {
568584 struct sock_fprog uprog;
569
- struct sock_filter *code = NULL;
570
- int len;
571585
572
- if (copy_from_user(&uprog, arg, sizeof(uprog)))
573
- return -EFAULT;
574
-
575
- if (!uprog.len) {
576
- *p = NULL;
577
- return 0;
578
- }
579
-
580
- len = uprog.len * sizeof(struct sock_filter);
581
- code = memdup_user(uprog.filter, len);
582
- if (IS_ERR(code))
583
- return PTR_ERR(code);
584
-
585
- *p = code;
586
- return uprog.len;
586
+ if (copy_from_user(&uprog, p, sizeof(struct sock_fprog)))
587
+ return ERR_PTR(-EFAULT);
588
+ return get_filter(&uprog);
587589 }
588
-#endif /* CONFIG_PPP_FILTER */
590
+
591
+#ifdef CONFIG_COMPAT
592
+struct sock_fprog32 {
593
+ unsigned short len;
594
+ compat_caddr_t filter;
595
+};
596
+
597
+#define PPPIOCSPASS32 _IOW('t', 71, struct sock_fprog32)
598
+#define PPPIOCSACTIVE32 _IOW('t', 70, struct sock_fprog32)
599
+
600
+static struct bpf_prog *compat_ppp_get_filter(struct sock_fprog32 __user *p)
601
+{
602
+ struct sock_fprog32 uprog32;
603
+ struct sock_fprog uprog;
604
+
605
+ if (copy_from_user(&uprog32, p, sizeof(struct sock_fprog32)))
606
+ return ERR_PTR(-EFAULT);
607
+ uprog.len = uprog32.len;
608
+ uprog.filter = compat_ptr(uprog32.filter);
609
+ return get_filter(&uprog);
610
+}
611
+#endif
612
+#endif
589613
590614 static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
591615 {
592616 struct ppp_file *pf;
593617 struct ppp *ppp;
594618 int err = -EFAULT, val, val2, i;
595
- struct ppp_idle idle;
619
+ struct ppp_idle32 idle32;
620
+ struct ppp_idle64 idle64;
596621 struct npioctl npi;
597622 int unit, cflags;
598623 struct slcompress *vj;
....@@ -688,9 +713,14 @@
688713 break;
689714
690715 case PPPIOCSCOMPRESS:
691
- err = ppp_set_compress(ppp, arg);
716
+ {
717
+ struct ppp_option_data data;
718
+ if (copy_from_user(&data, argp, sizeof(data)))
719
+ err = -EFAULT;
720
+ else
721
+ err = ppp_set_compress(ppp, &data);
692722 break;
693
-
723
+ }
694724 case PPPIOCGUNIT:
695725 if (put_user(ppp->file.index, p))
696726 break;
....@@ -710,10 +740,18 @@
710740 err = 0;
711741 break;
712742
713
- case PPPIOCGIDLE:
714
- idle.xmit_idle = (jiffies - ppp->last_xmit) / HZ;
715
- idle.recv_idle = (jiffies - ppp->last_recv) / HZ;
716
- if (copy_to_user(argp, &idle, sizeof(idle)))
743
+ case PPPIOCGIDLE32:
744
+ idle32.xmit_idle = (jiffies - ppp->last_xmit) / HZ;
745
+ idle32.recv_idle = (jiffies - ppp->last_recv) / HZ;
746
+ if (copy_to_user(argp, &idle32, sizeof(idle32)))
747
+ break;
748
+ err = 0;
749
+ break;
750
+
751
+ case PPPIOCGIDLE64:
752
+ idle64.xmit_idle = (jiffies - ppp->last_xmit) / HZ;
753
+ idle64.recv_idle = (jiffies - ppp->last_recv) / HZ;
754
+ if (copy_to_user(argp, &idle64, sizeof(idle64)))
717755 break;
718756 err = 0;
719757 break;
....@@ -762,55 +800,25 @@
762800
763801 #ifdef CONFIG_PPP_FILTER
764802 case PPPIOCSPASS:
765
- {
766
- struct sock_filter *code;
767
-
768
- err = get_filter(argp, &code);
769
- if (err >= 0) {
770
- struct bpf_prog *pass_filter = NULL;
771
- struct sock_fprog_kern fprog = {
772
- .len = err,
773
- .filter = code,
774
- };
775
-
776
- err = 0;
777
- if (fprog.filter)
778
- err = bpf_prog_create(&pass_filter, &fprog);
779
- if (!err) {
780
- ppp_lock(ppp);
781
- if (ppp->pass_filter)
782
- bpf_prog_destroy(ppp->pass_filter);
783
- ppp->pass_filter = pass_filter;
784
- ppp_unlock(ppp);
785
- }
786
- kfree(code);
787
- }
788
- break;
789
- }
790803 case PPPIOCSACTIVE:
791804 {
792
- struct sock_filter *code;
805
+ struct bpf_prog *filter = ppp_get_filter(argp);
806
+ struct bpf_prog **which;
793807
794
- err = get_filter(argp, &code);
795
- if (err >= 0) {
796
- struct bpf_prog *active_filter = NULL;
797
- struct sock_fprog_kern fprog = {
798
- .len = err,
799
- .filter = code,
800
- };
801
-
802
- err = 0;
803
- if (fprog.filter)
804
- err = bpf_prog_create(&active_filter, &fprog);
805
- if (!err) {
806
- ppp_lock(ppp);
807
- if (ppp->active_filter)
808
- bpf_prog_destroy(ppp->active_filter);
809
- ppp->active_filter = active_filter;
810
- ppp_unlock(ppp);
811
- }
812
- kfree(code);
808
+ if (IS_ERR(filter)) {
809
+ err = PTR_ERR(filter);
810
+ break;
813811 }
812
+ if (cmd == PPPIOCSPASS)
813
+ which = &ppp->pass_filter;
814
+ else
815
+ which = &ppp->active_filter;
816
+ ppp_lock(ppp);
817
+ if (*which)
818
+ bpf_prog_destroy(*which);
819
+ *which = filter;
820
+ ppp_unlock(ppp);
821
+ err = 0;
814822 break;
815823 }
816824 #endif /* CONFIG_PPP_FILTER */
....@@ -835,6 +843,77 @@
835843
836844 return err;
837845 }
846
+
847
+#ifdef CONFIG_COMPAT
848
+struct ppp_option_data32 {
849
+ compat_uptr_t ptr;
850
+ u32 length;
851
+ compat_int_t transmit;
852
+};
853
+#define PPPIOCSCOMPRESS32 _IOW('t', 77, struct ppp_option_data32)
854
+
855
+static long ppp_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
856
+{
857
+ struct ppp_file *pf;
858
+ int err = -ENOIOCTLCMD;
859
+ void __user *argp = (void __user *)arg;
860
+
861
+ mutex_lock(&ppp_mutex);
862
+
863
+ pf = file->private_data;
864
+ if (pf && pf->kind == INTERFACE) {
865
+ struct ppp *ppp = PF_TO_PPP(pf);
866
+ switch (cmd) {
867
+#ifdef CONFIG_PPP_FILTER
868
+ case PPPIOCSPASS32:
869
+ case PPPIOCSACTIVE32:
870
+ {
871
+ struct bpf_prog *filter = compat_ppp_get_filter(argp);
872
+ struct bpf_prog **which;
873
+
874
+ if (IS_ERR(filter)) {
875
+ err = PTR_ERR(filter);
876
+ break;
877
+ }
878
+ if (cmd == PPPIOCSPASS32)
879
+ which = &ppp->pass_filter;
880
+ else
881
+ which = &ppp->active_filter;
882
+ ppp_lock(ppp);
883
+ if (*which)
884
+ bpf_prog_destroy(*which);
885
+ *which = filter;
886
+ ppp_unlock(ppp);
887
+ err = 0;
888
+ break;
889
+ }
890
+#endif /* CONFIG_PPP_FILTER */
891
+ case PPPIOCSCOMPRESS32:
892
+ {
893
+ struct ppp_option_data32 data32;
894
+ if (copy_from_user(&data32, argp, sizeof(data32))) {
895
+ err = -EFAULT;
896
+ } else {
897
+ struct ppp_option_data data = {
898
+ .ptr = compat_ptr(data32.ptr),
899
+ .length = data32.length,
900
+ .transmit = data32.transmit
901
+ };
902
+ err = ppp_set_compress(ppp, &data);
903
+ }
904
+ break;
905
+ }
906
+ }
907
+ }
908
+ mutex_unlock(&ppp_mutex);
909
+
910
+ /* all other commands have compatible arguments */
911
+ if (err == -ENOIOCTLCMD)
912
+ err = ppp_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
913
+
914
+ return err;
915
+}
916
+#endif
838917
839918 static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf,
840919 struct file *file, unsigned int cmd, unsigned long arg)
....@@ -904,6 +983,9 @@
904983 .write = ppp_write,
905984 .poll = ppp_poll,
906985 .unlocked_ioctl = ppp_ioctl,
986
+#ifdef CONFIG_COMPAT
987
+ .compat_ioctl = ppp_compat_ioctl,
988
+#endif
907989 .open = ppp_open,
908990 .release = ppp_release,
909991 .llseek = noop_llseek,
....@@ -1527,6 +1609,8 @@
15271609 struct sk_buff *new_skb;
15281610 int len;
15291611 unsigned char *cp;
1612
+
1613
+ skb->dev = ppp->dev;
15301614
15311615 if (proto < 0x8000) {
15321616 #ifdef CONFIG_PPP_FILTER
....@@ -2466,7 +2550,7 @@
24662550
24672551 if (ppp->mrru == 0) /* do nothing until mrru is set */
24682552 return NULL;
2469
- head = list->next;
2553
+ head = __skb_peek(list);
24702554 tail = NULL;
24712555 skb_queue_walk_safe(list, p, tmp) {
24722556 again:
....@@ -2756,24 +2840,20 @@
27562840
27572841 /* Process the PPPIOCSCOMPRESS ioctl. */
27582842 static int
2759
-ppp_set_compress(struct ppp *ppp, unsigned long arg)
2843
+ppp_set_compress(struct ppp *ppp, struct ppp_option_data *data)
27602844 {
2761
- int err;
2845
+ int err = -EFAULT;
27622846 struct compressor *cp, *ocomp;
2763
- struct ppp_option_data data;
27642847 void *state, *ostate;
27652848 unsigned char ccp_option[CCP_MAX_OPTION_LENGTH];
27662849
2767
- err = -EFAULT;
2768
- if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
2850
+ if (data->length > CCP_MAX_OPTION_LENGTH)
27692851 goto out;
2770
- if (data.length > CCP_MAX_OPTION_LENGTH)
2771
- goto out;
2772
- if (copy_from_user(ccp_option, (void __user *) data.ptr, data.length))
2852
+ if (copy_from_user(ccp_option, data->ptr, data->length))
27732853 goto out;
27742854
27752855 err = -EINVAL;
2776
- if (data.length < 2 || ccp_option[1] < 2 || ccp_option[1] > data.length)
2856
+ if (data->length < 2 || ccp_option[1] < 2 || ccp_option[1] > data->length)
27772857 goto out;
27782858
27792859 cp = try_then_request_module(
....@@ -2783,8 +2863,8 @@
27832863 goto out;
27842864
27852865 err = -ENOBUFS;
2786
- if (data.transmit) {
2787
- state = cp->comp_alloc(ccp_option, data.length);
2866
+ if (data->transmit) {
2867
+ state = cp->comp_alloc(ccp_option, data->length);
27882868 if (state) {
27892869 ppp_xmit_lock(ppp);
27902870 ppp->xstate &= ~SC_COMP_RUN;
....@@ -2802,7 +2882,7 @@
28022882 module_put(cp->owner);
28032883
28042884 } else {
2805
- state = cp->decomp_alloc(ccp_option, data.length);
2885
+ state = cp->decomp_alloc(ccp_option, data->length);
28062886 if (state) {
28072887 ppp_recv_lock(ppp);
28082888 ppp->rstate &= ~SC_DECOMP_RUN;