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>
This commit is contained in:
parent
f4a1edd561
commit
5748eb8f8e
|
@ -755,24 +755,24 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||||
|
|
||||||
err = get_filter(argp, &code);
|
err = get_filter(argp, &code);
|
||||||
if (err >= 0) {
|
if (err >= 0) {
|
||||||
|
struct bpf_prog *pass_filter = NULL;
|
||||||
struct sock_fprog_kern fprog = {
|
struct sock_fprog_kern fprog = {
|
||||||
.len = err,
|
.len = err,
|
||||||
.filter = code,
|
.filter = code,
|
||||||
};
|
};
|
||||||
|
|
||||||
ppp_lock(ppp);
|
|
||||||
if (ppp->pass_filter) {
|
|
||||||
bpf_prog_destroy(ppp->pass_filter);
|
|
||||||
ppp->pass_filter = NULL;
|
|
||||||
}
|
|
||||||
if (fprog.filter != NULL)
|
|
||||||
err = bpf_prog_create(&ppp->pass_filter,
|
|
||||||
&fprog);
|
|
||||||
else
|
|
||||||
err = 0;
|
err = 0;
|
||||||
kfree(code);
|
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);
|
ppp_unlock(ppp);
|
||||||
}
|
}
|
||||||
|
kfree(code);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PPPIOCSACTIVE:
|
case PPPIOCSACTIVE:
|
||||||
|
@ -781,24 +781,24 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||||
|
|
||||||
err = get_filter(argp, &code);
|
err = get_filter(argp, &code);
|
||||||
if (err >= 0) {
|
if (err >= 0) {
|
||||||
|
struct bpf_prog *active_filter = NULL;
|
||||||
struct sock_fprog_kern fprog = {
|
struct sock_fprog_kern fprog = {
|
||||||
.len = err,
|
.len = err,
|
||||||
.filter = code,
|
.filter = code,
|
||||||
};
|
};
|
||||||
|
|
||||||
ppp_lock(ppp);
|
|
||||||
if (ppp->active_filter) {
|
|
||||||
bpf_prog_destroy(ppp->active_filter);
|
|
||||||
ppp->active_filter = NULL;
|
|
||||||
}
|
|
||||||
if (fprog.filter != NULL)
|
|
||||||
err = bpf_prog_create(&ppp->active_filter,
|
|
||||||
&fprog);
|
|
||||||
else
|
|
||||||
err = 0;
|
err = 0;
|
||||||
kfree(code);
|
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);
|
ppp_unlock(ppp);
|
||||||
}
|
}
|
||||||
|
kfree(code);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_PPP_FILTER */
|
#endif /* CONFIG_PPP_FILTER */
|
||||||
|
|
Loading…
Reference in New Issue