diff options
author | Takashi Iwai <tiwai@suse.de> | 2014-11-10 05:50:21 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-11-11 15:15:03 -0500 |
commit | 5748eb8f8e989a9da1ac7c96dc73d68cbdedf7df (patch) | |
tree | c2543dfacb1d0904ef6f81898dbf05834d4a79aa /drivers/net/ppp | |
parent | f4a1edd56120249198073aa4a373b77e3700ac8f (diff) |
net: ppp: Don't call bpf_prog_create() in ppp_lock
In ppp_ioctl(), bpf_prog_create() is called inside ppp_lock, which
eventually calls vmalloc() and hits BUG_ON() in vmalloc.c. This patch
works around the problem by moving the allocation outside the lock.
The bug was revealed by the recent change in net/core/filter.c, as it
allocates via vmalloc() instead of kmalloc() now.
Reported-and-tested-by: Stefan Seyfried <stefan.seyfried@googlemail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ppp')
-rw-r--r-- | drivers/net/ppp/ppp_generic.c | 40 |
1 files changed, 20 insertions, 20 deletions
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c index 68c3a3f4e0ab..794a47329368 100644 --- a/drivers/net/ppp/ppp_generic.c +++ b/drivers/net/ppp/ppp_generic.c | |||
@@ -755,23 +755,23 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
755 | 755 | ||
756 | err = get_filter(argp, &code); | 756 | err = get_filter(argp, &code); |
757 | if (err >= 0) { | 757 | if (err >= 0) { |
758 | struct bpf_prog *pass_filter = NULL; | ||
758 | struct sock_fprog_kern fprog = { | 759 | struct sock_fprog_kern fprog = { |
759 | .len = err, | 760 | .len = err, |
760 | .filter = code, | 761 | .filter = code, |
761 | }; | 762 | }; |
762 | 763 | ||
763 | ppp_lock(ppp); | 764 | err = 0; |
764 | if (ppp->pass_filter) { | 765 | if (fprog.filter) |
765 | bpf_prog_destroy(ppp->pass_filter); | 766 | err = bpf_prog_create(&pass_filter, &fprog); |
766 | ppp->pass_filter = NULL; | 767 | if (!err) { |
768 | ppp_lock(ppp); | ||
769 | if (ppp->pass_filter) | ||
770 | bpf_prog_destroy(ppp->pass_filter); | ||
771 | ppp->pass_filter = pass_filter; | ||
772 | ppp_unlock(ppp); | ||
767 | } | 773 | } |
768 | if (fprog.filter != NULL) | ||
769 | err = bpf_prog_create(&ppp->pass_filter, | ||
770 | &fprog); | ||
771 | else | ||
772 | err = 0; | ||
773 | kfree(code); | 774 | kfree(code); |
774 | ppp_unlock(ppp); | ||
775 | } | 775 | } |
776 | break; | 776 | break; |
777 | } | 777 | } |
@@ -781,23 +781,23 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
781 | 781 | ||
782 | err = get_filter(argp, &code); | 782 | err = get_filter(argp, &code); |
783 | if (err >= 0) { | 783 | if (err >= 0) { |
784 | struct bpf_prog *active_filter = NULL; | ||
784 | struct sock_fprog_kern fprog = { | 785 | struct sock_fprog_kern fprog = { |
785 | .len = err, | 786 | .len = err, |
786 | .filter = code, | 787 | .filter = code, |
787 | }; | 788 | }; |
788 | 789 | ||
789 | ppp_lock(ppp); | 790 | err = 0; |
790 | if (ppp->active_filter) { | 791 | if (fprog.filter) |
791 | bpf_prog_destroy(ppp->active_filter); | 792 | err = bpf_prog_create(&active_filter, &fprog); |
792 | ppp->active_filter = NULL; | 793 | if (!err) { |
794 | ppp_lock(ppp); | ||
795 | if (ppp->active_filter) | ||
796 | bpf_prog_destroy(ppp->active_filter); | ||
797 | ppp->active_filter = active_filter; | ||
798 | ppp_unlock(ppp); | ||
793 | } | 799 | } |
794 | if (fprog.filter != NULL) | ||
795 | err = bpf_prog_create(&ppp->active_filter, | ||
796 | &fprog); | ||
797 | else | ||
798 | err = 0; | ||
799 | kfree(code); | 800 | kfree(code); |
800 | ppp_unlock(ppp); | ||
801 | } | 801 | } |
802 | break; | 802 | break; |
803 | } | 803 | } |