Commit 1db20a52 authored by David S. Miller's avatar David S. Miller

nfnetlink_log: Stop using NLA_PUT*().

These macros contain a hidden goto, and are thus extremely error
prone and make code hard to audit.
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a447189e
...@@ -391,67 +391,78 @@ __build_packet_message(struct nfulnl_instance *inst, ...@@ -391,67 +391,78 @@ __build_packet_message(struct nfulnl_instance *inst,
pmsg.hw_protocol = skb->protocol; pmsg.hw_protocol = skb->protocol;
pmsg.hook = hooknum; 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) if (prefix &&
NLA_PUT(inst->skb, NFULA_PREFIX, plen, prefix); nla_put(inst->skb, NFULA_PREFIX, plen, prefix))
goto nla_put_failure;
if (indev) { if (indev) {
#ifndef CONFIG_BRIDGE_NETFILTER #ifndef CONFIG_BRIDGE_NETFILTER
NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_INDEV, if (nla_put_be32(inst->skb, NFULA_IFINDEX_INDEV,
htonl(indev->ifindex)); htonl(indev->ifindex)))
goto nla_put_failure;
#else #else
if (pf == PF_BRIDGE) { if (pf == PF_BRIDGE) {
/* Case 1: outdev is physical input device, we need to /* Case 1: outdev is physical input device, we need to
* look for bridge group (when called from * look for bridge group (when called from
* netfilter_bridge) */ * netfilter_bridge) */
NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_PHYSINDEV, if (nla_put_be32(inst->skb, NFULA_IFINDEX_PHYSINDEV,
htonl(indev->ifindex)); htonl(indev->ifindex)) ||
/* this is the bridge group "brX" */ /* this is the bridge group "brX" */
/* rcu_read_lock()ed by nf_hook_slow or nf_log_packet */ /* rcu_read_lock()ed by nf_hook_slow or nf_log_packet */
NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_INDEV, nla_put_be32(inst->skb, NFULA_IFINDEX_INDEV,
htonl(br_port_get_rcu(indev)->br->dev->ifindex)); htonl(br_port_get_rcu(indev)->br->dev->ifindex)))
goto nla_put_failure;
} else { } else {
/* Case 2: indev is bridge group, we need to look for /* Case 2: indev is bridge group, we need to look for
* physical device (when called from ipv4) */ * physical device (when called from ipv4) */
NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_INDEV, if (nla_put_be32(inst->skb, NFULA_IFINDEX_INDEV,
htonl(indev->ifindex)); htonl(indev->ifindex)))
if (skb->nf_bridge && skb->nf_bridge->physindev) goto nla_put_failure;
NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_PHYSINDEV, if (skb->nf_bridge && skb->nf_bridge->physindev &&
htonl(skb->nf_bridge->physindev->ifindex)); nla_put_be32(inst->skb, NFULA_IFINDEX_PHYSINDEV,
htonl(skb->nf_bridge->physindev->ifindex)))
goto nla_put_failure;
} }
#endif #endif
} }
if (outdev) { if (outdev) {
#ifndef CONFIG_BRIDGE_NETFILTER #ifndef CONFIG_BRIDGE_NETFILTER
NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_OUTDEV, if (nla_put_be32(inst->skb, NFULA_IFINDEX_OUTDEV,
htonl(outdev->ifindex)); htonl(outdev->ifindex)))
goto nla_put_failure;
#else #else
if (pf == PF_BRIDGE) { if (pf == PF_BRIDGE) {
/* Case 1: outdev is physical output device, we need to /* Case 1: outdev is physical output device, we need to
* look for bridge group (when called from * look for bridge group (when called from
* netfilter_bridge) */ * netfilter_bridge) */
NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_PHYSOUTDEV, if (nla_put_be32(inst->skb, NFULA_IFINDEX_PHYSOUTDEV,
htonl(outdev->ifindex)); htonl(outdev->ifindex)) ||
/* this is the bridge group "brX" */ /* this is the bridge group "brX" */
/* rcu_read_lock()ed by nf_hook_slow or nf_log_packet */ /* rcu_read_lock()ed by nf_hook_slow or nf_log_packet */
NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_OUTDEV, nla_put_be32(inst->skb, NFULA_IFINDEX_OUTDEV,
htonl(br_port_get_rcu(outdev)->br->dev->ifindex)); htonl(br_port_get_rcu(outdev)->br->dev->ifindex)))
goto nla_put_failure;
} else { } else {
/* Case 2: indev is a bridge group, we need to look /* Case 2: indev is a bridge group, we need to look
* for physical device (when called from ipv4) */ * for physical device (when called from ipv4) */
NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_OUTDEV, if (nla_put_be32(inst->skb, NFULA_IFINDEX_OUTDEV,
htonl(outdev->ifindex)); htonl(outdev->ifindex)))
if (skb->nf_bridge && skb->nf_bridge->physoutdev) goto nla_put_failure;
NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_PHYSOUTDEV, if (skb->nf_bridge && skb->nf_bridge->physoutdev &&
htonl(skb->nf_bridge->physoutdev->ifindex)); nla_put_be32(inst->skb, NFULA_IFINDEX_PHYSOUTDEV,
htonl(skb->nf_bridge->physoutdev->ifindex)))
goto nla_put_failure;
} }
#endif #endif
} }
if (skb->mark) if (skb->mark &&
NLA_PUT_BE32(inst->skb, NFULA_MARK, htonl(skb->mark)); nla_put_be32(inst->skb, NFULA_MARK, htonl(skb->mark)))
goto nla_put_failure;
if (indev && skb->dev && if (indev && skb->dev &&
skb->mac_header != skb->network_header) { skb->mac_header != skb->network_header) {
...@@ -459,16 +470,18 @@ __build_packet_message(struct nfulnl_instance *inst, ...@@ -459,16 +470,18 @@ __build_packet_message(struct nfulnl_instance *inst,
int len = dev_parse_header(skb, phw.hw_addr); int len = dev_parse_header(skb, phw.hw_addr);
if (len > 0) { if (len > 0) {
phw.hw_addrlen = htons(len); 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)) { if (indev && skb_mac_header_was_set(skb)) {
NLA_PUT_BE16(inst->skb, NFULA_HWTYPE, htons(skb->dev->type)); if (nla_put_be32(inst->skb, NFULA_HWTYPE, htons(skb->dev->type)) ||
NLA_PUT_BE16(inst->skb, NFULA_HWLEN, nla_put_be16(inst->skb, NFULA_HWLEN,
htons(skb->dev->hard_header_len)); htons(skb->dev->hard_header_len)) ||
NLA_PUT(inst->skb, NFULA_HWHEADER, skb->dev->hard_header_len, nla_put(inst->skb, NFULA_HWHEADER, skb->dev->hard_header_len,
skb_mac_header(skb)); skb_mac_header(skb)))
goto nla_put_failure;
} }
if (skb->tstamp.tv64) { if (skb->tstamp.tv64) {
...@@ -477,7 +490,8 @@ __build_packet_message(struct nfulnl_instance *inst, ...@@ -477,7 +490,8 @@ __build_packet_message(struct nfulnl_instance *inst,
ts.sec = cpu_to_be64(tv.tv_sec); ts.sec = cpu_to_be64(tv.tv_sec);
ts.usec = cpu_to_be64(tv.tv_usec); 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 */ /* UID */
...@@ -487,22 +501,24 @@ __build_packet_message(struct nfulnl_instance *inst, ...@@ -487,22 +501,24 @@ __build_packet_message(struct nfulnl_instance *inst,
struct file *file = skb->sk->sk_socket->file; struct file *file = skb->sk->sk_socket->file;
__be32 uid = htonl(file->f_cred->fsuid); __be32 uid = htonl(file->f_cred->fsuid);
__be32 gid = htonl(file->f_cred->fsgid); __be32 gid = htonl(file->f_cred->fsgid);
/* need to unlock here since NLA_PUT may goto */
read_unlock_bh(&skb->sk->sk_callback_lock); read_unlock_bh(&skb->sk->sk_callback_lock);
NLA_PUT_BE32(inst->skb, NFULA_UID, uid); if (nla_put_be32(inst->skb, NFULA_UID, uid) ||
NLA_PUT_BE32(inst->skb, NFULA_GID, gid); nla_put_be32(inst->skb, NFULA_GID, gid))
goto nla_put_failure;
} else } else
read_unlock_bh(&skb->sk->sk_callback_lock); read_unlock_bh(&skb->sk->sk_callback_lock);
} }
/* local sequence number */ /* local sequence number */
if (inst->flags & NFULNL_CFG_F_SEQ) if ((inst->flags & NFULNL_CFG_F_SEQ) &&
NLA_PUT_BE32(inst->skb, NFULA_SEQ, htonl(inst->seq++)); nla_put_be32(inst->skb, NFULA_SEQ, htonl(inst->seq++)))
goto nla_put_failure;
/* global sequence number */ /* global sequence number */
if (inst->flags & NFULNL_CFG_F_SEQ_GLOBAL) if ((inst->flags & NFULNL_CFG_F_SEQ_GLOBAL) &&
NLA_PUT_BE32(inst->skb, NFULA_SEQ_GLOBAL, nla_put_be32(inst->skb, NFULA_SEQ_GLOBAL,
htonl(atomic_inc_return(&global_seq))); htonl(atomic_inc_return(&global_seq))))
goto nla_put_failure;
if (data_len) { if (data_len) {
struct nlattr *nla; struct nlattr *nla;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment