netfilter: nftables: Fix a memleak from userdata error path in new objects
[linux-2.6-microblaze.git] / net / netfilter / nfnetlink_acct.c
index 6895f31..3c8cf87 100644 (file)
@@ -56,15 +56,13 @@ static inline struct nfnl_acct_net *nfnl_acct_pernet(struct net *net)
 #define NFACCT_F_QUOTA (NFACCT_F_QUOTA_PKTS | NFACCT_F_QUOTA_BYTES)
 #define NFACCT_OVERQUOTA_BIT   2       /* NFACCT_F_OVERQUOTA */
 
-static int nfnl_acct_new(struct net *net, struct sock *nfnl,
-                        struct sk_buff *skb, const struct nlmsghdr *nlh,
-                        const struct nlattr * const tb[],
-                        struct netlink_ext_ack *extack)
+static int nfnl_acct_new(struct sk_buff *skb, const struct nfnl_info *info,
+                        const struct nlattr * const tb[])
 {
-       struct nfnl_acct_net *nfnl_acct_net = nfnl_acct_pernet(net);
+       struct nfnl_acct_net *nfnl_acct_net = nfnl_acct_pernet(info->net);
        struct nf_acct *nfacct, *matching = NULL;
-       char *acct_name;
        unsigned int size = 0;
+       char *acct_name;
        u32 flags = 0;
 
        if (!tb[NFACCT_NAME])
@@ -78,7 +76,7 @@ static int nfnl_acct_new(struct net *net, struct sock *nfnl,
                if (strncmp(nfacct->name, acct_name, NFACCT_NAME_MAX) != 0)
                        continue;
 
-                if (nlh->nlmsg_flags & NLM_F_EXCL)
+                if (info->nlh->nlmsg_flags & NLM_F_EXCL)
                        return -EEXIST;
 
                matching = nfacct;
@@ -86,7 +84,7 @@ static int nfnl_acct_new(struct net *net, struct sock *nfnl,
         }
 
        if (matching) {
-               if (nlh->nlmsg_flags & NLM_F_REPLACE) {
+               if (info->nlh->nlmsg_flags & NLM_F_REPLACE) {
                        /* reset counters if you request a replacement. */
                        atomic64_set(&matching->pkts, 0);
                        atomic64_set(&matching->bytes, 0);
@@ -273,17 +271,15 @@ static int nfnl_acct_start(struct netlink_callback *cb)
        return 0;
 }
 
-static int nfnl_acct_get(struct net *net, struct sock *nfnl,
-                        struct sk_buff *skb, const struct nlmsghdr *nlh,
-                        const struct nlattr * const tb[],
-                        struct netlink_ext_ack *extack)
+static int nfnl_acct_get(struct sk_buff *skb, const struct nfnl_info *info,
+                        const struct nlattr * const tb[])
 {
-       struct nfnl_acct_net *nfnl_acct_net = nfnl_acct_pernet(net);
+       struct nfnl_acct_net *nfnl_acct_net = nfnl_acct_pernet(info->net);
        int ret = -ENOENT;
        struct nf_acct *cur;
        char *acct_name;
 
-       if (nlh->nlmsg_flags & NLM_F_DUMP) {
+       if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
                struct netlink_dump_control c = {
                        .dump = nfnl_acct_dump,
                        .start = nfnl_acct_start,
@@ -291,7 +287,7 @@ static int nfnl_acct_get(struct net *net, struct sock *nfnl,
                        .data = (void *)tb[NFACCT_FILTER],
                };
 
-               return netlink_dump_start(nfnl, skb, nlh, &c);
+               return netlink_dump_start(info->sk, skb, info->nlh, &c);
        }
 
        if (!tb[NFACCT_NAME])
@@ -311,15 +307,15 @@ static int nfnl_acct_get(struct net *net, struct sock *nfnl,
                }
 
                ret = nfnl_acct_fill_info(skb2, NETLINK_CB(skb).portid,
-                                        nlh->nlmsg_seq,
-                                        NFNL_MSG_TYPE(nlh->nlmsg_type),
-                                        NFNL_MSG_ACCT_NEW, cur);
+                                         info->nlh->nlmsg_seq,
+                                         NFNL_MSG_TYPE(info->nlh->nlmsg_type),
+                                         NFNL_MSG_ACCT_NEW, cur);
                if (ret <= 0) {
                        kfree_skb(skb2);
                        break;
                }
-               ret = netlink_unicast(nfnl, skb2, NETLINK_CB(skb).portid,
-                                       MSG_DONTWAIT);
+               ret = netlink_unicast(info->sk, skb2, NETLINK_CB(skb).portid,
+                                     MSG_DONTWAIT);
                if (ret > 0)
                        ret = 0;
 
@@ -347,12 +343,10 @@ static int nfnl_acct_try_del(struct nf_acct *cur)
        return ret;
 }
 
-static int nfnl_acct_del(struct net *net, struct sock *nfnl,
-                        struct sk_buff *skb, const struct nlmsghdr *nlh,
-                        const struct nlattr * const tb[],
-                        struct netlink_ext_ack *extack)
+static int nfnl_acct_del(struct sk_buff *skb, const struct nfnl_info *info,
+                        const struct nlattr * const tb[])
 {
-       struct nfnl_acct_net *nfnl_acct_net = nfnl_acct_pernet(net);
+       struct nfnl_acct_net *nfnl_acct_net = nfnl_acct_pernet(info->net);
        struct nf_acct *cur, *tmp;
        int ret = -ENOENT;
        char *acct_name;
@@ -388,18 +382,30 @@ static const struct nla_policy nfnl_acct_policy[NFACCT_MAX+1] = {
 };
 
 static const struct nfnl_callback nfnl_acct_cb[NFNL_MSG_ACCT_MAX] = {
-       [NFNL_MSG_ACCT_NEW]             = { .call = nfnl_acct_new,
-                                           .attr_count = NFACCT_MAX,
-                                           .policy = nfnl_acct_policy },
-       [NFNL_MSG_ACCT_GET]             = { .call = nfnl_acct_get,
-                                           .attr_count = NFACCT_MAX,
-                                           .policy = nfnl_acct_policy },
-       [NFNL_MSG_ACCT_GET_CTRZERO]     = { .call = nfnl_acct_get,
-                                           .attr_count = NFACCT_MAX,
-                                           .policy = nfnl_acct_policy },
-       [NFNL_MSG_ACCT_DEL]             = { .call = nfnl_acct_del,
-                                           .attr_count = NFACCT_MAX,
-                                           .policy = nfnl_acct_policy },
+       [NFNL_MSG_ACCT_NEW] = {
+               .call           = nfnl_acct_new,
+               .type           = NFNL_CB_MUTEX,
+               .attr_count     = NFACCT_MAX,
+               .policy         = nfnl_acct_policy
+       },
+       [NFNL_MSG_ACCT_GET] = {
+               .call           = nfnl_acct_get,
+               .type           = NFNL_CB_MUTEX,
+               .attr_count     = NFACCT_MAX,
+               .policy         = nfnl_acct_policy
+       },
+       [NFNL_MSG_ACCT_GET_CTRZERO] = {
+               .call           = nfnl_acct_get,
+               .type           = NFNL_CB_MUTEX,
+               .attr_count     = NFACCT_MAX,
+               .policy         = nfnl_acct_policy
+       },
+       [NFNL_MSG_ACCT_DEL] = {
+               .call           = nfnl_acct_del,
+               .type           = NFNL_CB_MUTEX,
+               .attr_count     = NFACCT_MAX,
+               .policy         = nfnl_acct_policy
+       },
 };
 
 static const struct nfnetlink_subsystem nfnl_acct_subsys = {