Revert "netfilter: xt_qtaguid: fix crash on non-full sks"
[firefly-linux-kernel-4.4.55.git] / net / netfilter / xt_qtaguid.c
index e33be3aaf09401b5dd6cd755064773096321def7..e1442bfb668dbaf9ecd3f7f425cc70a49b500a1a 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/file.h>
 #include <linux/inetdevice.h>
 #include <linux/module.h>
+#include <linux/miscdevice.h>
 #include <linux/netfilter/x_tables.h>
 #include <linux/netfilter/xt_qtaguid.h>
 #include <linux/ratelimit.h>
@@ -1290,11 +1291,12 @@ static void if_tag_stat_update(const char *ifname, uid_t uid,
                "uid=%u sk=%p dir=%d proto=%d bytes=%d)\n",
                 ifname, uid, sk, direction, proto, bytes);
 
-
+       spin_lock_bh(&iface_stat_list_lock);
        iface_entry = get_iface_entry(ifname);
        if (!iface_entry) {
                pr_err_ratelimited("qtaguid: iface_stat: stat_update() "
                                   "%s not found\n", ifname);
+               spin_unlock_bh(&iface_stat_list_lock);
                return;
        }
        /* It is ok to process data when an iface_entry is inactive */
@@ -1330,8 +1332,7 @@ static void if_tag_stat_update(const char *ifname, uid_t uid,
                 * {0, uid_tag} will also get updated.
                 */
                tag_stat_update(tag_stat_entry, direction, proto, bytes);
-               spin_unlock_bh(&iface_entry->tag_stat_list_lock);
-               return;
+               goto unlock;
        }
 
        /* Loop over tag list under this interface for {0,uid_tag} */
@@ -1371,6 +1372,7 @@ static void if_tag_stat_update(const char *ifname, uid_t uid,
        tag_stat_update(new_tag_stat, direction, proto, bytes);
 unlock:
        spin_unlock_bh(&iface_entry->tag_stat_list_lock);
+       spin_unlock_bh(&iface_stat_list_lock);
 }
 
 static int iface_netdev_event_handler(struct notifier_block *nb,
@@ -1588,10 +1590,10 @@ static struct sock *qtaguid_find_sk(const struct sk_buff *skb,
 
        switch (par->family) {
        case NFPROTO_IPV6:
-               sk = xt_socket_get6_sk(skb, par);
+               sk = xt_socket_lookup_slow_v6(dev_net(skb->dev), skb, par->in);
                break;
        case NFPROTO_IPV4:
-               sk = xt_socket_get4_sk(skb, par);
+               sk = xt_socket_lookup_slow_v4(dev_net(skb->dev), skb, par->in);
                break;
        default:
                return NULL;
@@ -1605,7 +1607,7 @@ static struct sock *qtaguid_find_sk(const struct sk_buff *skb,
                 * "struct inet_timewait_sock" which is missing fields.
                 */
                if (sk->sk_state  == TCP_TIME_WAIT) {
-                       xt_socket_put_sk(sk);
+                       sock_gen_put(sk);
                        sk = NULL;
                }
        }
@@ -1803,7 +1805,7 @@ static bool qtaguid_mt(const struct sk_buff *skb, struct xt_action_param *par)
 
 put_sock_ret_res:
        if (got_sock)
-               xt_socket_put_sk(sk);
+               sock_gen_put(sk);
        if (set_sk_callback_lock)
                read_unlock_bh(&sk->sk_callback_lock);
 ret_res:
@@ -2541,7 +2543,6 @@ static void pp_stats_header(struct seq_file *m)
 static int pp_stats_line(struct seq_file *m, struct tag_stat *ts_entry,
                         int cnt_set)
 {
-       int ret;
        struct data_counters *cnts;
        tag_t tag = ts_entry->tn.tag;
        uid_t stat_uid = get_uid_from_tag(tag);
@@ -2560,7 +2561,7 @@ static int pp_stats_line(struct seq_file *m, struct tag_stat *ts_entry,
        }
        ppi->item_index++;
        cnts = &ts_entry->counters;
-       ret = seq_printf(m, "%d %s 0x%llx %u %u "
+       seq_printf(m, "%d %s 0x%llx %u %u "
                "%llu %llu "
                "%llu %llu "
                "%llu %llu "
@@ -2590,7 +2591,7 @@ static int pp_stats_line(struct seq_file *m, struct tag_stat *ts_entry,
                cnts->bpc[cnt_set][IFS_TX][IFS_UDP].packets,
                cnts->bpc[cnt_set][IFS_TX][IFS_PROTO_OTHER].bytes,
                cnts->bpc[cnt_set][IFS_TX][IFS_PROTO_OTHER].packets);
-       return ret ?: 1;
+       return seq_has_overflowed(m) ? -ENOSPC : 1;
 }
 
 static bool pp_sets(struct seq_file *m, struct tag_stat *ts_entry)