Commit 568f194e authored by Daniel Borkmann's avatar Daniel Borkmann Committed by David S. Miller

net: ppp: use sk_unattached_filter api

For the ppp driver, there are currently two open-coded BPF filters in use,
that is, pass_filter and active_filter. Migrate both to make proper use
of sk_unattached_filter_{create,destroy} API so that the actual BPF code
is decoupled from direct access, and filters can be jited as a side-effect
by the internal filter compiler.

Joint work with Alexei Starovoitov.
Signed-off-by: default avatarDaniel Borkmann <dborkman@redhat.com>
Signed-off-by: default avatarAlexei Starovoitov <ast@plumgrid.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: linux-ppp@vger.kernel.org
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 164d8c66
...@@ -143,9 +143,8 @@ struct ppp { ...@@ -143,9 +143,8 @@ struct ppp {
struct sk_buff_head mrq; /* MP: receive reconstruction queue */ struct sk_buff_head mrq; /* MP: receive reconstruction queue */
#endif /* CONFIG_PPP_MULTILINK */ #endif /* CONFIG_PPP_MULTILINK */
#ifdef CONFIG_PPP_FILTER #ifdef CONFIG_PPP_FILTER
struct sock_filter *pass_filter; /* filter for packets to pass */ struct sk_filter *pass_filter; /* filter for packets to pass */
struct sock_filter *active_filter;/* filter for pkts to reset idle */ struct sk_filter *active_filter;/* filter for pkts to reset idle */
unsigned pass_len, active_len;
#endif /* CONFIG_PPP_FILTER */ #endif /* CONFIG_PPP_FILTER */
struct net *ppp_net; /* the net we belong to */ struct net *ppp_net; /* the net we belong to */
struct ppp_link_stats stats64; /* 64 bit network stats */ struct ppp_link_stats stats64; /* 64 bit network stats */
...@@ -755,28 +754,42 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -755,28 +754,42 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case PPPIOCSPASS: case PPPIOCSPASS:
{ {
struct sock_filter *code; struct sock_filter *code;
err = get_filter(argp, &code); err = get_filter(argp, &code);
if (err >= 0) { if (err >= 0) {
struct sock_fprog fprog = {
.len = err,
.filter = code,
};
ppp_lock(ppp); ppp_lock(ppp);
kfree(ppp->pass_filter); if (ppp->pass_filter)
ppp->pass_filter = code; sk_unattached_filter_destroy(ppp->pass_filter);
ppp->pass_len = err; err = sk_unattached_filter_create(&ppp->pass_filter,
&fprog);
kfree(code);
ppp_unlock(ppp); ppp_unlock(ppp);
err = 0;
} }
break; break;
} }
case PPPIOCSACTIVE: case PPPIOCSACTIVE:
{ {
struct sock_filter *code; struct sock_filter *code;
err = get_filter(argp, &code); err = get_filter(argp, &code);
if (err >= 0) { if (err >= 0) {
struct sock_fprog fprog = {
.len = err,
.filter = code,
};
ppp_lock(ppp); ppp_lock(ppp);
kfree(ppp->active_filter); if (ppp->active_filter)
ppp->active_filter = code; sk_unattached_filter_destroy(ppp->active_filter);
ppp->active_len = err; err = sk_unattached_filter_create(&ppp->active_filter,
&fprog);
kfree(code);
ppp_unlock(ppp); ppp_unlock(ppp);
err = 0;
} }
break; break;
} }
...@@ -1184,7 +1197,7 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb) ...@@ -1184,7 +1197,7 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb)
a four-byte PPP header on each packet */ a four-byte PPP header on each packet */
*skb_push(skb, 2) = 1; *skb_push(skb, 2) = 1;
if (ppp->pass_filter && if (ppp->pass_filter &&
sk_run_filter(skb, ppp->pass_filter) == 0) { SK_RUN_FILTER(ppp->pass_filter, skb) == 0) {
if (ppp->debug & 1) if (ppp->debug & 1)
netdev_printk(KERN_DEBUG, ppp->dev, netdev_printk(KERN_DEBUG, ppp->dev,
"PPP: outbound frame " "PPP: outbound frame "
...@@ -1194,7 +1207,7 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb) ...@@ -1194,7 +1207,7 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb)
} }
/* if this packet passes the active filter, record the time */ /* if this packet passes the active filter, record the time */
if (!(ppp->active_filter && if (!(ppp->active_filter &&
sk_run_filter(skb, ppp->active_filter) == 0)) SK_RUN_FILTER(ppp->active_filter, skb) == 0))
ppp->last_xmit = jiffies; ppp->last_xmit = jiffies;
skb_pull(skb, 2); skb_pull(skb, 2);
#else #else
...@@ -1818,7 +1831,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) ...@@ -1818,7 +1831,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
*skb_push(skb, 2) = 0; *skb_push(skb, 2) = 0;
if (ppp->pass_filter && if (ppp->pass_filter &&
sk_run_filter(skb, ppp->pass_filter) == 0) { SK_RUN_FILTER(ppp->pass_filter, skb) == 0) {
if (ppp->debug & 1) if (ppp->debug & 1)
netdev_printk(KERN_DEBUG, ppp->dev, netdev_printk(KERN_DEBUG, ppp->dev,
"PPP: inbound frame " "PPP: inbound frame "
...@@ -1827,7 +1840,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) ...@@ -1827,7 +1840,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
return; return;
} }
if (!(ppp->active_filter && if (!(ppp->active_filter &&
sk_run_filter(skb, ppp->active_filter) == 0)) SK_RUN_FILTER(ppp->active_filter, skb) == 0))
ppp->last_recv = jiffies; ppp->last_recv = jiffies;
__skb_pull(skb, 2); __skb_pull(skb, 2);
} else } else
...@@ -2672,6 +2685,10 @@ ppp_create_interface(struct net *net, int unit, int *retp) ...@@ -2672,6 +2685,10 @@ ppp_create_interface(struct net *net, int unit, int *retp)
ppp->minseq = -1; ppp->minseq = -1;
skb_queue_head_init(&ppp->mrq); skb_queue_head_init(&ppp->mrq);
#endif /* CONFIG_PPP_MULTILINK */ #endif /* CONFIG_PPP_MULTILINK */
#ifdef CONFIG_PPP_FILTER
ppp->pass_filter = NULL;
ppp->active_filter = NULL;
#endif /* CONFIG_PPP_FILTER */
/* /*
* drum roll: don't forget to set * drum roll: don't forget to set
...@@ -2802,10 +2819,15 @@ static void ppp_destroy_interface(struct ppp *ppp) ...@@ -2802,10 +2819,15 @@ static void ppp_destroy_interface(struct ppp *ppp)
skb_queue_purge(&ppp->mrq); skb_queue_purge(&ppp->mrq);
#endif /* CONFIG_PPP_MULTILINK */ #endif /* CONFIG_PPP_MULTILINK */
#ifdef CONFIG_PPP_FILTER #ifdef CONFIG_PPP_FILTER
kfree(ppp->pass_filter); if (ppp->pass_filter) {
ppp->pass_filter = NULL; sk_unattached_filter_destroy(ppp->pass_filter);
kfree(ppp->active_filter); ppp->pass_filter = NULL;
ppp->active_filter = NULL; }
if (ppp->active_filter) {
sk_unattached_filter_destroy(ppp->active_filter);
ppp->active_filter = NULL;
}
#endif /* CONFIG_PPP_FILTER */ #endif /* CONFIG_PPP_FILTER */
kfree_skb(ppp->xmit_pending); kfree_skb(ppp->xmit_pending);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment