Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux...
[firefly-linux-kernel-4.4.55.git] / net / core / sock_diag.c
index a0e9cf6379de3eac8ac1182c3be73e8d140b4a1b..d7af1885932269eb9f4196fe1211a6d09e298b97 100644 (file)
@@ -52,9 +52,10 @@ EXPORT_SYMBOL_GPL(sock_diag_put_meminfo);
 int sock_diag_put_filterinfo(struct user_namespace *user_ns, struct sock *sk,
                             struct sk_buff *skb, int attrtype)
 {
-       struct nlattr *attr;
+       struct sock_fprog_kern *fprog;
        struct sk_filter *filter;
-       unsigned int len;
+       struct nlattr *attr;
+       unsigned int flen;
        int err = 0;
 
        if (!ns_capable(user_ns, CAP_NET_ADMIN)) {
@@ -63,24 +64,20 @@ int sock_diag_put_filterinfo(struct user_namespace *user_ns, struct sock *sk,
        }
 
        rcu_read_lock();
-
        filter = rcu_dereference(sk->sk_filter);
-       len = filter ? filter->len * sizeof(struct sock_filter) : 0;
+       if (!filter)
+               goto out;
 
-       attr = nla_reserve(skb, attrtype, len);
+       fprog = filter->orig_prog;
+       flen = sk_filter_proglen(fprog);
+
+       attr = nla_reserve(skb, attrtype, flen);
        if (attr == NULL) {
                err = -EMSGSIZE;
                goto out;
        }
 
-       if (filter) {
-               struct sock_filter *fb = (struct sock_filter *)nla_data(attr);
-               int i;
-
-               for (i = 0; i < filter->len; i++, fb++)
-                       sk_decode_filter(&filter->insns[i], fb);
-       }
-
+       memcpy(nla_data(attr), fprog->filter, flen);
 out:
        rcu_read_unlock();
        return err;