net: ppp: use sk_unattached_filter api
authorDaniel Borkmann <dborkman@redhat.com>
Fri, 28 Mar 2014 17:58:23 +0000 (18:58 +0100)
committerDavid S. Miller <davem@davemloft.net>
Mon, 31 Mar 2014 04:45:09 +0000 (00:45 -0400)
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: Daniel Borkmann <dborkman@redhat.com>
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: linux-ppp@vger.kernel.org
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ppp/ppp_generic.c

index 72ff14b811c621c3a6694a2e4941d2a4c41651ed..e3923ebb693fccc276db45de7c7d9551ee6bc208 100644 (file)
@@ -143,9 +143,8 @@ struct ppp {
        struct sk_buff_head mrq;        /* MP: receive reconstruction queue */
 #endif /* CONFIG_PPP_MULTILINK */
 #ifdef CONFIG_PPP_FILTER
-       struct sock_filter *pass_filter;        /* filter for packets to pass */
-       struct sock_filter *active_filter;/* filter for pkts to reset idle */
-       unsigned pass_len, active_len;
+       struct sk_filter *pass_filter;  /* filter for packets to pass */
+       struct sk_filter *active_filter;/* filter for pkts to reset idle */
 #endif /* CONFIG_PPP_FILTER */
        struct net      *ppp_net;       /* the net we belong to */
        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)
        case PPPIOCSPASS:
        {
                struct sock_filter *code;
+
                err = get_filter(argp, &code);
                if (err >= 0) {
+                       struct sock_fprog fprog = {
+                               .len = err,
+                               .filter = code,
+                       };
+
                        ppp_lock(ppp);
-                       kfree(ppp->pass_filter);
-                       ppp->pass_filter = code;
-                       ppp->pass_len = err;
+                       if (ppp->pass_filter)
+                               sk_unattached_filter_destroy(ppp->pass_filter);
+                       err = sk_unattached_filter_create(&ppp->pass_filter,
+                                                         &fprog);
+                       kfree(code);
                        ppp_unlock(ppp);
-                       err = 0;
                }
                break;
        }
        case PPPIOCSACTIVE:
        {
                struct sock_filter *code;
+
                err = get_filter(argp, &code);
                if (err >= 0) {
+                       struct sock_fprog fprog = {
+                               .len = err,
+                               .filter = code,
+                       };
+
                        ppp_lock(ppp);
-                       kfree(ppp->active_filter);
-                       ppp->active_filter = code;
-                       ppp->active_len = err;
+                       if (ppp->active_filter)
+                               sk_unattached_filter_destroy(ppp->active_filter);
+                       err = sk_unattached_filter_create(&ppp->active_filter,
+                                                         &fprog);
+                       kfree(code);
                        ppp_unlock(ppp);
-                       err = 0;
                }
                break;
        }
@@ -1184,7 +1197,7 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb)
                   a four-byte PPP header on each packet */
                *skb_push(skb, 2) = 1;
                if (ppp->pass_filter &&
-                   sk_run_filter(skb, ppp->pass_filter) == 0) {
+                   SK_RUN_FILTER(ppp->pass_filter, skb) == 0) {
                        if (ppp->debug & 1)
                                netdev_printk(KERN_DEBUG, ppp->dev,
                                              "PPP: outbound frame "
@@ -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 (!(ppp->active_filter &&
-                     sk_run_filter(skb, ppp->active_filter) == 0))
+                     SK_RUN_FILTER(ppp->active_filter, skb) == 0))
                        ppp->last_xmit = jiffies;
                skb_pull(skb, 2);
 #else
@@ -1818,7 +1831,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
 
                        *skb_push(skb, 2) = 0;
                        if (ppp->pass_filter &&
-                           sk_run_filter(skb, ppp->pass_filter) == 0) {
+                           SK_RUN_FILTER(ppp->pass_filter, skb) == 0) {
                                if (ppp->debug & 1)
                                        netdev_printk(KERN_DEBUG, ppp->dev,
                                                      "PPP: inbound frame "
@@ -1827,7 +1840,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
                                return;
                        }
                        if (!(ppp->active_filter &&
-                             sk_run_filter(skb, ppp->active_filter) == 0))
+                             SK_RUN_FILTER(ppp->active_filter, skb) == 0))
                                ppp->last_recv = jiffies;
                        __skb_pull(skb, 2);
                } else
@@ -2672,6 +2685,10 @@ ppp_create_interface(struct net *net, int unit, int *retp)
        ppp->minseq = -1;
        skb_queue_head_init(&ppp->mrq);
 #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
@@ -2802,10 +2819,15 @@ static void ppp_destroy_interface(struct ppp *ppp)
        skb_queue_purge(&ppp->mrq);
 #endif /* CONFIG_PPP_MULTILINK */
 #ifdef CONFIG_PPP_FILTER
-       kfree(ppp->pass_filter);
-       ppp->pass_filter = NULL;
-       kfree(ppp->active_filter);
-       ppp->active_filter = NULL;
+       if (ppp->pass_filter) {
+               sk_unattached_filter_destroy(ppp->pass_filter);
+               ppp->pass_filter = NULL;
+       }
+
+       if (ppp->active_filter) {
+               sk_unattached_filter_destroy(ppp->active_filter);
+               ppp->active_filter = NULL;
+       }
 #endif /* CONFIG_PPP_FILTER */
 
        kfree_skb(ppp->xmit_pending);