@@ -554,29 +554,58 @@ static __poll_t ppp_poll(struct file *file, poll_table *wait)
554
554
}
555
555
556
556
#ifdef CONFIG_PPP_FILTER
557
- static int get_filter (void __user * arg , struct sock_filter * * p )
557
+ static struct bpf_prog * get_filter (struct sock_fprog * uprog )
558
+ {
559
+ struct sock_fprog_kern fprog ;
560
+ struct bpf_prog * res = NULL ;
561
+ int err ;
562
+
563
+ if (!uprog -> len )
564
+ return NULL ;
565
+
566
+ /* uprog->len is unsigned short, so no overflow here */
567
+ fprog .len = uprog -> len * sizeof (struct sock_filter );
568
+ fprog .filter = memdup_user (uprog -> filter , fprog .len );
569
+ if (IS_ERR (fprog .filter ))
570
+ return ERR_CAST (fprog .filter );
571
+
572
+ err = bpf_prog_create (& res , & fprog );
573
+ kfree (fprog .filter );
574
+
575
+ return err ? ERR_PTR (err ) : res ;
576
+ }
577
+
578
+ static struct bpf_prog * ppp_get_filter (struct sock_fprog __user * p )
558
579
{
559
580
struct sock_fprog uprog ;
560
- struct sock_filter * code = NULL ;
561
- int len ;
562
581
563
- if (copy_from_user (& uprog , arg , sizeof (uprog )))
564
- return - EFAULT ;
582
+ if (copy_from_user (& uprog , p , sizeof (struct sock_fprog )))
583
+ return ERR_PTR (- EFAULT );
584
+ return get_filter (& uprog );
585
+ }
565
586
566
- if (!uprog .len ) {
567
- * p = NULL ;
568
- return 0 ;
569
- }
587
+ #ifdef CONFIG_COMPAT
588
+ struct sock_fprog32 {
589
+ unsigned short len ;
590
+ compat_caddr_t filter ;
591
+ };
570
592
571
- len = uprog .len * sizeof (struct sock_filter );
572
- code = memdup_user (uprog .filter , len );
573
- if (IS_ERR (code ))
574
- return PTR_ERR (code );
593
+ #define PPPIOCSPASS32 _IOW('t', 71, struct sock_fprog32)
594
+ #define PPPIOCSACTIVE32 _IOW('t', 70, struct sock_fprog32)
575
595
576
- * p = code ;
577
- return uprog .len ;
596
+ static struct bpf_prog * compat_ppp_get_filter (struct sock_fprog32 __user * p )
597
+ {
598
+ struct sock_fprog32 uprog32 ;
599
+ struct sock_fprog uprog ;
600
+
601
+ if (copy_from_user (& uprog32 , p , sizeof (struct sock_fprog32 )))
602
+ return ERR_PTR (- EFAULT );
603
+ uprog .len = uprog32 .len ;
604
+ uprog .filter = compat_ptr (uprog32 .filter );
605
+ return get_filter (& uprog );
578
606
}
579
- #endif /* CONFIG_PPP_FILTER */
607
+ #endif
608
+ #endif
580
609
581
610
static long ppp_ioctl (struct file * file , unsigned int cmd , unsigned long arg )
582
611
{
@@ -753,55 +782,25 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
753
782
754
783
#ifdef CONFIG_PPP_FILTER
755
784
case PPPIOCSPASS :
756
- {
757
- struct sock_filter * code ;
758
-
759
- err = get_filter (argp , & code );
760
- if (err >= 0 ) {
761
- struct bpf_prog * pass_filter = NULL ;
762
- struct sock_fprog_kern fprog = {
763
- .len = err ,
764
- .filter = code ,
765
- };
766
-
767
- err = 0 ;
768
- if (fprog .filter )
769
- err = bpf_prog_create (& pass_filter , & fprog );
770
- if (!err ) {
771
- ppp_lock (ppp );
772
- if (ppp -> pass_filter )
773
- bpf_prog_destroy (ppp -> pass_filter );
774
- ppp -> pass_filter = pass_filter ;
775
- ppp_unlock (ppp );
776
- }
777
- kfree (code );
778
- }
779
- break ;
780
- }
781
785
case PPPIOCSACTIVE :
782
786
{
783
- struct sock_filter * code ;
787
+ struct bpf_prog * filter = ppp_get_filter (argp );
788
+ struct bpf_prog * * which ;
784
789
785
- err = get_filter (argp , & code );
786
- if (err >= 0 ) {
787
- struct bpf_prog * active_filter = NULL ;
788
- struct sock_fprog_kern fprog = {
789
- .len = err ,
790
- .filter = code ,
791
- };
792
-
793
- err = 0 ;
794
- if (fprog .filter )
795
- err = bpf_prog_create (& active_filter , & fprog );
796
- if (!err ) {
797
- ppp_lock (ppp );
798
- if (ppp -> active_filter )
799
- bpf_prog_destroy (ppp -> active_filter );
800
- ppp -> active_filter = active_filter ;
801
- ppp_unlock (ppp );
802
- }
803
- kfree (code );
790
+ if (IS_ERR (filter )) {
791
+ err = PTR_ERR (filter );
792
+ break ;
804
793
}
794
+ if (cmd == PPPIOCSPASS )
795
+ which = & ppp -> pass_filter ;
796
+ else
797
+ which = & ppp -> active_filter ;
798
+ ppp_lock (ppp );
799
+ if (* which )
800
+ bpf_prog_destroy (* which );
801
+ * which = filter ;
802
+ ppp_unlock (ppp );
803
+ err = 0 ;
805
804
break ;
806
805
}
807
806
#endif /* CONFIG_PPP_FILTER */
@@ -827,6 +826,51 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
827
826
return err ;
828
827
}
829
828
829
+ #ifdef CONFIG_COMPAT
830
+ static long ppp_compat_ioctl (struct file * file , unsigned int cmd , unsigned long arg )
831
+ {
832
+ struct ppp_file * pf ;
833
+ int err = - ENOIOCTLCMD ;
834
+ void __user * argp = (void __user * )arg ;
835
+
836
+ mutex_lock (& ppp_mutex );
837
+
838
+ pf = file -> private_data ;
839
+ if (pf && pf -> kind == INTERFACE ) {
840
+ struct ppp * ppp = PF_TO_PPP (pf );
841
+ switch (cmd ) {
842
+ #ifdef CONFIG_PPP_FILTER
843
+ case PPPIOCSPASS32 :
844
+ case PPPIOCSACTIVE32 :
845
+ {
846
+ struct bpf_prog * filter = compat_ppp_get_filter (argp );
847
+ struct bpf_prog * * which ;
848
+
849
+ if (IS_ERR (filter )) {
850
+ err = PTR_ERR (filter );
851
+ break ;
852
+ }
853
+ if (cmd == PPPIOCSPASS32 )
854
+ which = & ppp -> pass_filter ;
855
+ else
856
+ which = & ppp -> active_filter ;
857
+ ppp_lock (ppp );
858
+ if (* which )
859
+ bpf_prog_destroy (* which );
860
+ * which = filter ;
861
+ ppp_unlock (ppp );
862
+ err = 0 ;
863
+ break ;
864
+ }
865
+ #endif /* CONFIG_PPP_FILTER */
866
+ }
867
+ }
868
+ mutex_unlock (& ppp_mutex );
869
+
870
+ return err ;
871
+ }
872
+ #endif
873
+
830
874
static int ppp_unattached_ioctl (struct net * net , struct ppp_file * pf ,
831
875
struct file * file , unsigned int cmd , unsigned long arg )
832
876
{
@@ -895,6 +939,9 @@ static const struct file_operations ppp_device_fops = {
895
939
.write = ppp_write ,
896
940
.poll = ppp_poll ,
897
941
.unlocked_ioctl = ppp_ioctl ,
942
+ #ifdef CONFIG_COMPAT
943
+ .compat_ioctl = ppp_compat_ioctl ,
944
+ #endif
898
945
.open = ppp_open ,
899
946
.release = ppp_release ,
900
947
.llseek = noop_llseek ,
0 commit comments