nfnetlink_log: Stop using NLA_PUT*().
authorDavid S. Miller <davem@davemloft.net>
Fri, 30 Mar 2012 03:31:16 +0000 (23:31 -0400)
committerDavid S. Miller <davem@davemloft.net>
Sun, 1 Apr 2012 22:43:44 +0000 (18:43 -0400)
These macros contain a hidden goto, and are thus extremely error
prone and make code hard to audit.

Signed-off-by: David S. Miller <davem@davemloft.net>
net/netfilter/nfnetlink_log.c

index 66b2c54c544f6bbf87c20500d97452122f2b2fcf..3c3cfc0cc9b5a7495e89c838a06f9bf520605cf0 100644 (file)
@@ -391,67 +391,78 @@ __build_packet_message(struct nfulnl_instance *inst,
        pmsg.hw_protocol        = skb->protocol;
        pmsg.hook               = hooknum;
 
-       NLA_PUT(inst->skb, NFULA_PACKET_HDR, sizeof(pmsg), &pmsg);
+       if (nla_put(inst->skb, NFULA_PACKET_HDR, sizeof(pmsg), &pmsg))
+               goto nla_put_failure;
 
-       if (prefix)
-               NLA_PUT(inst->skb, NFULA_PREFIX, plen, prefix);
+       if (prefix &&
+           nla_put(inst->skb, NFULA_PREFIX, plen, prefix))
+               goto nla_put_failure;
 
        if (indev) {
 #ifndef CONFIG_BRIDGE_NETFILTER
-               NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_INDEV,
-                            htonl(indev->ifindex));
+               if (nla_put_be32(inst->skb, NFULA_IFINDEX_INDEV,
+                                htonl(indev->ifindex)))
+                       goto nla_put_failure;
 #else
                if (pf == PF_BRIDGE) {
                        /* Case 1: outdev is physical input device, we need to
                         * look for bridge group (when called from
                         * netfilter_bridge) */
-                       NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_PHYSINDEV,
-                                    htonl(indev->ifindex));
+                       if (nla_put_be32(inst->skb, NFULA_IFINDEX_PHYSINDEV,
+                                        htonl(indev->ifindex)) ||
                        /* this is the bridge group "brX" */
                        /* rcu_read_lock()ed by nf_hook_slow or nf_log_packet */
-                       NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_INDEV,
-                                    htonl(br_port_get_rcu(indev)->br->dev->ifindex));
+                           nla_put_be32(inst->skb, NFULA_IFINDEX_INDEV,
+                                        htonl(br_port_get_rcu(indev)->br->dev->ifindex)))
+                               goto nla_put_failure;
                } else {
                        /* Case 2: indev is bridge group, we need to look for
                         * physical device (when called from ipv4) */
-                       NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_INDEV,
-                                    htonl(indev->ifindex));
-                       if (skb->nf_bridge && skb->nf_bridge->physindev)
-                               NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_PHYSINDEV,
-                                            htonl(skb->nf_bridge->physindev->ifindex));
+                       if (nla_put_be32(inst->skb, NFULA_IFINDEX_INDEV,
+                                        htonl(indev->ifindex)))
+                               goto nla_put_failure;
+                       if (skb->nf_bridge && skb->nf_bridge->physindev &&
+                           nla_put_be32(inst->skb, NFULA_IFINDEX_PHYSINDEV,
+                                        htonl(skb->nf_bridge->physindev->ifindex)))
+                               goto nla_put_failure;
                }
 #endif
        }
 
        if (outdev) {
 #ifndef CONFIG_BRIDGE_NETFILTER
-               NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_OUTDEV,
-                            htonl(outdev->ifindex));
+               if (nla_put_be32(inst->skb, NFULA_IFINDEX_OUTDEV,
+                                htonl(outdev->ifindex)))
+                       goto nla_put_failure;
 #else
                if (pf == PF_BRIDGE) {
                        /* Case 1: outdev is physical output device, we need to
                         * look for bridge group (when called from
                         * netfilter_bridge) */
-                       NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_PHYSOUTDEV,
-                                    htonl(outdev->ifindex));
+                       if (nla_put_be32(inst->skb, NFULA_IFINDEX_PHYSOUTDEV,
+                                        htonl(outdev->ifindex)) ||
                        /* this is the bridge group "brX" */
                        /* rcu_read_lock()ed by nf_hook_slow or nf_log_packet */
-                       NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_OUTDEV,
-                                    htonl(br_port_get_rcu(outdev)->br->dev->ifindex));
+                           nla_put_be32(inst->skb, NFULA_IFINDEX_OUTDEV,
+                                        htonl(br_port_get_rcu(outdev)->br->dev->ifindex)))
+                               goto nla_put_failure;
                } else {
                        /* Case 2: indev is a bridge group, we need to look
                         * for physical device (when called from ipv4) */
-                       NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_OUTDEV,
-                                    htonl(outdev->ifindex));
-                       if (skb->nf_bridge && skb->nf_bridge->physoutdev)
-                               NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_PHYSOUTDEV,
-                                            htonl(skb->nf_bridge->physoutdev->ifindex));
+                       if (nla_put_be32(inst->skb, NFULA_IFINDEX_OUTDEV,
+                                        htonl(outdev->ifindex)))
+                               goto nla_put_failure;
+                       if (skb->nf_bridge && skb->nf_bridge->physoutdev &&
+                           nla_put_be32(inst->skb, NFULA_IFINDEX_PHYSOUTDEV,
+                                        htonl(skb->nf_bridge->physoutdev->ifindex)))
+                               goto nla_put_failure;
                }
 #endif
        }
 
-       if (skb->mark)
-               NLA_PUT_BE32(inst->skb, NFULA_MARK, htonl(skb->mark));
+       if (skb->mark &&
+           nla_put_be32(inst->skb, NFULA_MARK, htonl(skb->mark)))
+               goto nla_put_failure;
 
        if (indev && skb->dev &&
            skb->mac_header != skb->network_header) {
@@ -459,16 +470,18 @@ __build_packet_message(struct nfulnl_instance *inst,
                int len = dev_parse_header(skb, phw.hw_addr);
                if (len > 0) {
                        phw.hw_addrlen = htons(len);
-                       NLA_PUT(inst->skb, NFULA_HWADDR, sizeof(phw), &phw);
+                       if (nla_put(inst->skb, NFULA_HWADDR, sizeof(phw), &phw))
+                               goto nla_put_failure;
                }
        }
 
        if (indev && skb_mac_header_was_set(skb)) {
-               NLA_PUT_BE16(inst->skb, NFULA_HWTYPE, htons(skb->dev->type));
-               NLA_PUT_BE16(inst->skb, NFULA_HWLEN,
-                            htons(skb->dev->hard_header_len));
-               NLA_PUT(inst->skb, NFULA_HWHEADER, skb->dev->hard_header_len,
-                       skb_mac_header(skb));
+               if (nla_put_be32(inst->skb, NFULA_HWTYPE, htons(skb->dev->type)) ||
+                   nla_put_be16(inst->skb, NFULA_HWLEN,
+                                htons(skb->dev->hard_header_len)) ||
+                   nla_put(inst->skb, NFULA_HWHEADER, skb->dev->hard_header_len,
+                           skb_mac_header(skb)))
+                       goto nla_put_failure;
        }
 
        if (skb->tstamp.tv64) {
@@ -477,7 +490,8 @@ __build_packet_message(struct nfulnl_instance *inst,
                ts.sec = cpu_to_be64(tv.tv_sec);
                ts.usec = cpu_to_be64(tv.tv_usec);
 
-               NLA_PUT(inst->skb, NFULA_TIMESTAMP, sizeof(ts), &ts);
+               if (nla_put(inst->skb, NFULA_TIMESTAMP, sizeof(ts), &ts))
+                       goto nla_put_failure;
        }
 
        /* UID */
@@ -487,22 +501,24 @@ __build_packet_message(struct nfulnl_instance *inst,
                        struct file *file = skb->sk->sk_socket->file;
                        __be32 uid = htonl(file->f_cred->fsuid);
                        __be32 gid = htonl(file->f_cred->fsgid);
-                       /* need to unlock here since NLA_PUT may goto */
                        read_unlock_bh(&skb->sk->sk_callback_lock);
-                       NLA_PUT_BE32(inst->skb, NFULA_UID, uid);
-                       NLA_PUT_BE32(inst->skb, NFULA_GID, gid);
+                       if (nla_put_be32(inst->skb, NFULA_UID, uid) ||
+                           nla_put_be32(inst->skb, NFULA_GID, gid))
+                               goto nla_put_failure;
                } else
                        read_unlock_bh(&skb->sk->sk_callback_lock);
        }
 
        /* local sequence number */
-       if (inst->flags & NFULNL_CFG_F_SEQ)
-               NLA_PUT_BE32(inst->skb, NFULA_SEQ, htonl(inst->seq++));
+       if ((inst->flags & NFULNL_CFG_F_SEQ) &&
+           nla_put_be32(inst->skb, NFULA_SEQ, htonl(inst->seq++)))
+               goto nla_put_failure;
 
        /* global sequence number */
-       if (inst->flags & NFULNL_CFG_F_SEQ_GLOBAL)
-               NLA_PUT_BE32(inst->skb, NFULA_SEQ_GLOBAL,
-                            htonl(atomic_inc_return(&global_seq)));
+       if ((inst->flags & NFULNL_CFG_F_SEQ_GLOBAL) &&
+           nla_put_be32(inst->skb, NFULA_SEQ_GLOBAL,
+                        htonl(atomic_inc_return(&global_seq))))
+               goto nla_put_failure;
 
        if (data_len) {
                struct nlattr *nla;