1
0
Fork 0

netfilter: avoid using skb->nf_bridge directly

This pointer is going to be removed soon, so use the existing helpers in
more places to avoid noise when the removal happens.

Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
hifive-unleashed-5.1
Florian Westphal 2018-12-18 17:15:15 +01:00 committed by David S. Miller
parent 8239d57904
commit c4b0e771f9
9 changed files with 103 additions and 66 deletions

View File

@ -17,43 +17,58 @@ static inline void br_drop_fake_rtable(struct sk_buff *skb)
skb_dst_drop(skb); skb_dst_drop(skb);
} }
static inline struct nf_bridge_info *
nf_bridge_info_get(const struct sk_buff *skb)
{
return skb->nf_bridge;
}
static inline bool nf_bridge_info_exists(const struct sk_buff *skb)
{
return skb->nf_bridge != NULL;
}
static inline int nf_bridge_get_physinif(const struct sk_buff *skb) static inline int nf_bridge_get_physinif(const struct sk_buff *skb)
{ {
struct nf_bridge_info *nf_bridge; const struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
if (skb->nf_bridge == NULL) if (!nf_bridge)
return 0; return 0;
nf_bridge = skb->nf_bridge;
return nf_bridge->physindev ? nf_bridge->physindev->ifindex : 0; return nf_bridge->physindev ? nf_bridge->physindev->ifindex : 0;
} }
static inline int nf_bridge_get_physoutif(const struct sk_buff *skb) static inline int nf_bridge_get_physoutif(const struct sk_buff *skb)
{ {
struct nf_bridge_info *nf_bridge; const struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
if (skb->nf_bridge == NULL) if (!nf_bridge)
return 0; return 0;
nf_bridge = skb->nf_bridge;
return nf_bridge->physoutdev ? nf_bridge->physoutdev->ifindex : 0; return nf_bridge->physoutdev ? nf_bridge->physoutdev->ifindex : 0;
} }
static inline struct net_device * static inline struct net_device *
nf_bridge_get_physindev(const struct sk_buff *skb) nf_bridge_get_physindev(const struct sk_buff *skb)
{ {
return skb->nf_bridge ? skb->nf_bridge->physindev : NULL; const struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
return nf_bridge ? nf_bridge->physindev : NULL;
} }
static inline struct net_device * static inline struct net_device *
nf_bridge_get_physoutdev(const struct sk_buff *skb) nf_bridge_get_physoutdev(const struct sk_buff *skb)
{ {
return skb->nf_bridge ? skb->nf_bridge->physoutdev : NULL; const struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
return nf_bridge ? nf_bridge->physoutdev : NULL;
} }
static inline bool nf_bridge_in_prerouting(const struct sk_buff *skb) static inline bool nf_bridge_in_prerouting(const struct sk_buff *skb)
{ {
return skb->nf_bridge && skb->nf_bridge->in_prerouting; const struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
return nf_bridge && nf_bridge->in_prerouting;
} }
#else #else
#define br_drop_fake_rtable(skb) do { } while (0) #define br_drop_fake_rtable(skb) do { } while (0)

View File

@ -22,12 +22,6 @@ int br_nf_hook_thresh(unsigned int hook, struct net *net, struct sock *sk,
int (*okfn)(struct net *, struct sock *, int (*okfn)(struct net *, struct sock *,
struct sk_buff *)); struct sk_buff *));
static inline struct nf_bridge_info *
nf_bridge_info_get(const struct sk_buff *skb)
{
return skb->nf_bridge;
}
unsigned int nf_bridge_encap_header_len(const struct sk_buff *skb); unsigned int nf_bridge_encap_header_len(const struct sk_buff *skb);
static inline void nf_bridge_push_encap_header(struct sk_buff *skb) static inline void nf_bridge_push_encap_header(struct sk_buff *skb)

View File

@ -247,7 +247,9 @@ drop:
void nf_bridge_update_protocol(struct sk_buff *skb) void nf_bridge_update_protocol(struct sk_buff *skb)
{ {
switch (skb->nf_bridge->orig_proto) { const struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
switch (nf_bridge->orig_proto) {
case BRNF_PROTO_8021Q: case BRNF_PROTO_8021Q:
skb->protocol = htons(ETH_P_8021Q); skb->protocol = htons(ETH_P_8021Q);
break; break;
@ -569,7 +571,8 @@ static unsigned int br_nf_forward_ip(void *priv,
struct net_device *parent; struct net_device *parent;
u_int8_t pf; u_int8_t pf;
if (!skb->nf_bridge) nf_bridge = nf_bridge_info_get(skb);
if (!nf_bridge)
return NF_ACCEPT; return NF_ACCEPT;
/* Need exclusive nf_bridge_info since we might have multiple /* Need exclusive nf_bridge_info since we might have multiple
@ -701,7 +704,9 @@ br_nf_ip_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
static unsigned int nf_bridge_mtu_reduction(const struct sk_buff *skb) static unsigned int nf_bridge_mtu_reduction(const struct sk_buff *skb)
{ {
if (skb->nf_bridge->orig_proto == BRNF_PROTO_PPPOE) const struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
if (nf_bridge->orig_proto == BRNF_PROTO_PPPOE)
return PPPOE_SES_HLEN; return PPPOE_SES_HLEN;
return 0; return 0;
} }
@ -839,7 +844,9 @@ static unsigned int ip_sabotage_in(void *priv,
struct sk_buff *skb, struct sk_buff *skb,
const struct nf_hook_state *state) const struct nf_hook_state *state)
{ {
if (skb->nf_bridge && !skb->nf_bridge->in_prerouting && struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
if (nf_bridge && !nf_bridge->in_prerouting &&
!netif_is_l3_master(skb->dev)) { !netif_is_l3_master(skb->dev)) {
state->okfn(state->net, state->sk, skb); state->okfn(state->net, state->sk, skb);
return NF_STOLEN; return NF_STOLEN;
@ -877,7 +884,9 @@ static void br_nf_pre_routing_finish_bridge_slow(struct sk_buff *skb)
static int br_nf_dev_xmit(struct sk_buff *skb) static int br_nf_dev_xmit(struct sk_buff *skb)
{ {
if (skb->nf_bridge && skb->nf_bridge->bridged_dnat) { const struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
if (nf_bridge && nf_bridge->bridged_dnat) {
br_nf_pre_routing_finish_bridge_slow(skb); br_nf_pre_routing_finish_bridge_slow(skb);
return 1; return 1;
} }

View File

@ -102,6 +102,7 @@ EXPORT_SYMBOL_GPL(nf_reject_ip_tcphdr_put);
/* Send RST reply */ /* Send RST reply */
void nf_send_reset(struct net *net, struct sk_buff *oldskb, int hook) void nf_send_reset(struct net *net, struct sk_buff *oldskb, int hook)
{ {
struct net_device *br_indev __maybe_unused;
struct sk_buff *nskb; struct sk_buff *nskb;
struct iphdr *niph; struct iphdr *niph;
const struct tcphdr *oth; const struct tcphdr *oth;
@ -147,10 +148,11 @@ void nf_send_reset(struct net *net, struct sk_buff *oldskb, int hook)
* build the eth header using the original destination's MAC as the * build the eth header using the original destination's MAC as the
* source, and send the RST packet directly. * source, and send the RST packet directly.
*/ */
if (oldskb->nf_bridge) { br_indev = nf_bridge_get_physindev(oldskb);
if (br_indev) {
struct ethhdr *oeth = eth_hdr(oldskb); struct ethhdr *oeth = eth_hdr(oldskb);
nskb->dev = nf_bridge_get_physindev(oldskb); nskb->dev = br_indev;
niph->tot_len = htons(nskb->len); niph->tot_len = htons(nskb->len);
ip_send_check(niph); ip_send_check(niph);
if (dev_hard_header(nskb, nskb->dev, ntohs(nskb->protocol), if (dev_hard_header(nskb, nskb->dev, ntohs(nskb->protocol),

View File

@ -131,6 +131,7 @@ EXPORT_SYMBOL_GPL(nf_reject_ip6_tcphdr_put);
void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook) void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook)
{ {
struct net_device *br_indev __maybe_unused;
struct sk_buff *nskb; struct sk_buff *nskb;
struct tcphdr _otcph; struct tcphdr _otcph;
const struct tcphdr *otcph; const struct tcphdr *otcph;
@ -197,15 +198,18 @@ void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook)
* build the eth header using the original destination's MAC as the * build the eth header using the original destination's MAC as the
* source, and send the RST packet directly. * source, and send the RST packet directly.
*/ */
if (oldskb->nf_bridge) { br_indev = nf_bridge_get_physindev(oldskb);
if (br_indev) {
struct ethhdr *oeth = eth_hdr(oldskb); struct ethhdr *oeth = eth_hdr(oldskb);
nskb->dev = nf_bridge_get_physindev(oldskb); nskb->dev = br_indev;
nskb->protocol = htons(ETH_P_IPV6); nskb->protocol = htons(ETH_P_IPV6);
ip6h->payload_len = htons(sizeof(struct tcphdr)); ip6h->payload_len = htons(sizeof(struct tcphdr));
if (dev_hard_header(nskb, nskb->dev, ntohs(nskb->protocol), if (dev_hard_header(nskb, nskb->dev, ntohs(nskb->protocol),
oeth->h_source, oeth->h_dest, nskb->len) < 0) oeth->h_source, oeth->h_dest, nskb->len) < 0) {
kfree_skb(nskb);
return; return;
}
dev_queue_xmit(nskb); dev_queue_xmit(nskb);
} else } else
#endif #endif

View File

@ -156,22 +156,20 @@ nf_log_dump_packet_common(struct nf_log_buf *m, u_int8_t pf,
const struct net_device *out, const struct net_device *out,
const struct nf_loginfo *loginfo, const char *prefix) const struct nf_loginfo *loginfo, const char *prefix)
{ {
const struct net_device *physoutdev __maybe_unused;
const struct net_device *physindev __maybe_unused;
nf_log_buf_add(m, KERN_SOH "%c%sIN=%s OUT=%s ", nf_log_buf_add(m, KERN_SOH "%c%sIN=%s OUT=%s ",
'0' + loginfo->u.log.level, prefix, '0' + loginfo->u.log.level, prefix,
in ? in->name : "", in ? in->name : "",
out ? out->name : ""); out ? out->name : "");
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
if (skb->nf_bridge) { physindev = nf_bridge_get_physindev(skb);
const struct net_device *physindev; if (physindev && in != physindev)
const struct net_device *physoutdev; nf_log_buf_add(m, "PHYSIN=%s ", physindev->name);
physoutdev = nf_bridge_get_physoutdev(skb);
physindev = nf_bridge_get_physindev(skb); if (physoutdev && out != physoutdev)
if (physindev && in != physindev) nf_log_buf_add(m, "PHYSOUT=%s ", physoutdev->name);
nf_log_buf_add(m, "PHYSIN=%s ", physindev->name);
physoutdev = nf_bridge_get_physoutdev(skb);
if (physoutdev && out != physoutdev)
nf_log_buf_add(m, "PHYSOUT=%s ", physoutdev->name);
}
#endif #endif
} }
EXPORT_SYMBOL_GPL(nf_log_dump_packet_common); EXPORT_SYMBOL_GPL(nf_log_dump_packet_common);

View File

@ -46,6 +46,24 @@ void nf_unregister_queue_handler(struct net *net)
} }
EXPORT_SYMBOL(nf_unregister_queue_handler); EXPORT_SYMBOL(nf_unregister_queue_handler);
static void nf_queue_entry_release_br_nf_refs(struct sk_buff *skb)
{
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
if (nf_bridge) {
struct net_device *physdev;
physdev = nf_bridge_get_physindev(skb);
if (physdev)
dev_put(physdev);
physdev = nf_bridge_get_physoutdev(skb);
if (physdev)
dev_put(physdev);
}
#endif
}
void nf_queue_entry_release_refs(struct nf_queue_entry *entry) void nf_queue_entry_release_refs(struct nf_queue_entry *entry)
{ {
struct nf_hook_state *state = &entry->state; struct nf_hook_state *state = &entry->state;
@ -57,20 +75,28 @@ void nf_queue_entry_release_refs(struct nf_queue_entry *entry)
dev_put(state->out); dev_put(state->out);
if (state->sk) if (state->sk)
sock_put(state->sk); sock_put(state->sk);
nf_queue_entry_release_br_nf_refs(entry->skb);
}
EXPORT_SYMBOL_GPL(nf_queue_entry_release_refs);
static void nf_queue_entry_get_br_nf_refs(struct sk_buff *skb)
{
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
if (entry->skb->nf_bridge) { struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
if (nf_bridge) {
struct net_device *physdev; struct net_device *physdev;
physdev = nf_bridge_get_physindev(entry->skb); physdev = nf_bridge_get_physindev(skb);
if (physdev) if (physdev)
dev_put(physdev); dev_hold(physdev);
physdev = nf_bridge_get_physoutdev(entry->skb); physdev = nf_bridge_get_physoutdev(skb);
if (physdev) if (physdev)
dev_put(physdev); dev_hold(physdev);
} }
#endif #endif
} }
EXPORT_SYMBOL_GPL(nf_queue_entry_release_refs);
/* Bump dev refs so they don't vanish while packet is out */ /* Bump dev refs so they don't vanish while packet is out */
void nf_queue_entry_get_refs(struct nf_queue_entry *entry) void nf_queue_entry_get_refs(struct nf_queue_entry *entry)
@ -83,18 +109,8 @@ void nf_queue_entry_get_refs(struct nf_queue_entry *entry)
dev_hold(state->out); dev_hold(state->out);
if (state->sk) if (state->sk)
sock_hold(state->sk); sock_hold(state->sk);
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
if (entry->skb->nf_bridge) {
struct net_device *physdev;
physdev = nf_bridge_get_physindev(entry->skb); nf_queue_entry_get_br_nf_refs(entry->skb);
if (physdev)
dev_hold(physdev);
physdev = nf_bridge_get_physoutdev(entry->skb);
if (physdev)
dev_hold(physdev);
}
#endif
} }
EXPORT_SYMBOL_GPL(nf_queue_entry_get_refs); EXPORT_SYMBOL_GPL(nf_queue_entry_get_refs);

View File

@ -727,13 +727,13 @@ nf_queue_entry_dup(struct nf_queue_entry *e)
*/ */
static void nf_bridge_adjust_skb_data(struct sk_buff *skb) static void nf_bridge_adjust_skb_data(struct sk_buff *skb)
{ {
if (skb->nf_bridge) if (nf_bridge_info_get(skb))
__skb_push(skb, skb->network_header - skb->mac_header); __skb_push(skb, skb->network_header - skb->mac_header);
} }
static void nf_bridge_adjust_segmented_data(struct sk_buff *skb) static void nf_bridge_adjust_segmented_data(struct sk_buff *skb)
{ {
if (skb->nf_bridge) if (nf_bridge_info_get(skb))
__skb_pull(skb, skb->network_header - skb->mac_header); __skb_pull(skb, skb->network_header - skb->mac_header);
} }
#else #else
@ -904,23 +904,22 @@ nfqnl_set_mode(struct nfqnl_instance *queue,
static int static int
dev_cmp(struct nf_queue_entry *entry, unsigned long ifindex) dev_cmp(struct nf_queue_entry *entry, unsigned long ifindex)
{ {
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
int physinif, physoutif;
physinif = nf_bridge_get_physinif(entry->skb);
physoutif = nf_bridge_get_physoutif(entry->skb);
if (physinif == ifindex || physoutif == ifindex)
return 1;
#endif
if (entry->state.in) if (entry->state.in)
if (entry->state.in->ifindex == ifindex) if (entry->state.in->ifindex == ifindex)
return 1; return 1;
if (entry->state.out) if (entry->state.out)
if (entry->state.out->ifindex == ifindex) if (entry->state.out->ifindex == ifindex)
return 1; return 1;
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
if (entry->skb->nf_bridge) {
int physinif, physoutif;
physinif = nf_bridge_get_physinif(entry->skb);
physoutif = nf_bridge_get_physoutif(entry->skb);
if (physinif == ifindex || physoutif == ifindex)
return 1;
}
#endif
return 0; return 0;
} }

View File

@ -33,7 +33,7 @@ physdev_mt(const struct sk_buff *skb, struct xt_action_param *par)
/* Not a bridged IP packet or no info available yet: /* Not a bridged IP packet or no info available yet:
* LOCAL_OUT/mangle and LOCAL_OUT/nat don't know if * LOCAL_OUT/mangle and LOCAL_OUT/nat don't know if
* the destination device will be a bridge. */ * the destination device will be a bridge. */
if (!skb->nf_bridge) { if (!nf_bridge_info_exists(skb)) {
/* Return MATCH if the invert flags of the used options are on */ /* Return MATCH if the invert flags of the used options are on */
if ((info->bitmask & XT_PHYSDEV_OP_BRIDGED) && if ((info->bitmask & XT_PHYSDEV_OP_BRIDGED) &&
!(info->invert & XT_PHYSDEV_OP_BRIDGED)) !(info->invert & XT_PHYSDEV_OP_BRIDGED))