Skip to content

Commit

Permalink
Merge branch 'udp_tunnel_sk'
Browse files Browse the repository at this point in the history
Prevent UDP tunnels from operating on garbage socket

So this should do the rest of the work such that when we encapsulate
into a UDP tunnel, the output path works on the UDP tunnel's socket
rather than skb->sk.

Part of this work is based upon changes done by Jiri Pirko some time
ago.

Basically the first step is to pass the socket through the nf_hook
okfn(), and then next we do the same for the UDP tunnel xmit routines.

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Apr 7, 2015
2 parents a3786a5 + 79b16aa commit e0e8db2
Show file tree
Hide file tree
Showing 51 changed files with 349 additions and 251 deletions.
14 changes: 8 additions & 6 deletions drivers/net/vxlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -1672,7 +1672,8 @@ static void vxlan_build_gbp_hdr(struct vxlanhdr *vxh, u32 vxflags,
}

#if IS_ENABLED(CONFIG_IPV6)
static int vxlan6_xmit_skb(struct dst_entry *dst, struct sk_buff *skb,
static int vxlan6_xmit_skb(struct dst_entry *dst, struct sock *sk,
struct sk_buff *skb,
struct net_device *dev, struct in6_addr *saddr,
struct in6_addr *daddr, __u8 prio, __u8 ttl,
__be16 src_port, __be16 dst_port,
Expand Down Expand Up @@ -1748,7 +1749,7 @@ static int vxlan6_xmit_skb(struct dst_entry *dst, struct sk_buff *skb,

skb_set_inner_protocol(skb, htons(ETH_P_TEB));

udp_tunnel6_xmit_skb(dst, skb, dev, saddr, daddr, prio,
udp_tunnel6_xmit_skb(dst, sk, skb, dev, saddr, daddr, prio,
ttl, src_port, dst_port,
!!(vxflags & VXLAN_F_UDP_ZERO_CSUM6_TX));
return 0;
Expand All @@ -1758,7 +1759,7 @@ static int vxlan6_xmit_skb(struct dst_entry *dst, struct sk_buff *skb,
}
#endif

int vxlan_xmit_skb(struct rtable *rt, struct sk_buff *skb,
int vxlan_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *skb,
__be32 src, __be32 dst, __u8 tos, __u8 ttl, __be16 df,
__be16 src_port, __be16 dst_port,
struct vxlan_metadata *md, bool xnet, u32 vxflags)
Expand Down Expand Up @@ -1827,7 +1828,7 @@ int vxlan_xmit_skb(struct rtable *rt, struct sk_buff *skb,

skb_set_inner_protocol(skb, htons(ETH_P_TEB));

return udp_tunnel_xmit_skb(rt, skb, src, dst, tos,
return udp_tunnel_xmit_skb(rt, sk, skb, src, dst, tos,
ttl, df, src_port, dst_port, xnet,
!(vxflags & VXLAN_F_UDP_CSUM));
}
Expand Down Expand Up @@ -1882,6 +1883,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
struct vxlan_rdst *rdst, bool did_rsc)
{
struct vxlan_dev *vxlan = netdev_priv(dev);
struct sock *sk = vxlan->vn_sock->sock->sk;
struct rtable *rt = NULL;
const struct iphdr *old_iph;
struct flowi4 fl4;
Expand Down Expand Up @@ -1961,7 +1963,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
md.vni = htonl(vni << 8);
md.gbp = skb->mark;

err = vxlan_xmit_skb(rt, skb, fl4.saddr,
err = vxlan_xmit_skb(rt, sk, skb, fl4.saddr,
dst->sin.sin_addr.s_addr, tos, ttl, df,
src_port, dst_port, &md,
!net_eq(vxlan->net, dev_net(vxlan->dev)),
Expand Down Expand Up @@ -2021,7 +2023,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
md.vni = htonl(vni << 8);
md.gbp = skb->mark;

err = vxlan6_xmit_skb(ndst, skb, dev, &fl6.saddr, &fl6.daddr,
err = vxlan6_xmit_skb(ndst, sk, skb, dev, &fl6.saddr, &fl6.daddr,
0, ttl, src_port, dst_port, &md,
!net_eq(vxlan->net, dev_net(vxlan->dev)),
vxlan->flags);
Expand Down
14 changes: 11 additions & 3 deletions include/linux/netdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -2165,8 +2165,12 @@ int dev_open(struct net_device *dev);
int dev_close(struct net_device *dev);
int dev_close_many(struct list_head *head, bool unlink);
void dev_disable_lro(struct net_device *dev);
int dev_loopback_xmit(struct sk_buff *newskb);
int dev_queue_xmit(struct sk_buff *skb);
int dev_loopback_xmit(struct sock *sk, struct sk_buff *newskb);
int dev_queue_xmit_sk(struct sock *sk, struct sk_buff *skb);
static inline int dev_queue_xmit(struct sk_buff *skb)
{
return dev_queue_xmit_sk(skb->sk, skb);
}
int dev_queue_xmit_accel(struct sk_buff *skb, void *accel_priv);
int register_netdevice(struct net_device *dev);
void unregister_netdevice_queue(struct net_device *dev, struct list_head *head);
Expand Down Expand Up @@ -2927,7 +2931,11 @@ static inline void dev_consume_skb_any(struct sk_buff *skb)

int netif_rx(struct sk_buff *skb);
int netif_rx_ni(struct sk_buff *skb);
int netif_receive_skb(struct sk_buff *skb);
int netif_receive_skb_sk(struct sock *sk, struct sk_buff *skb);
static inline int netif_receive_skb(struct sk_buff *skb)
{
return netif_receive_skb_sk(skb->sk, skb);
}
gro_result_t napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb);
void napi_gro_flush(struct napi_struct *napi, bool flush_old);
struct sk_buff *napi_get_frags(struct napi_struct *napi);
Expand Down
89 changes: 55 additions & 34 deletions include/linux/netfilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,35 @@ struct sk_buff;

struct nf_hook_ops;

struct sock;

struct nf_hook_state {
unsigned int hook;
int thresh;
u_int8_t pf;
struct net_device *in;
struct net_device *out;
int (*okfn)(struct sk_buff *);
struct sock *sk;
int (*okfn)(struct sock *, struct sk_buff *);
};

static inline void nf_hook_state_init(struct nf_hook_state *p,
unsigned int hook,
int thresh, u_int8_t pf,
struct net_device *indev,
struct net_device *outdev,
struct sock *sk,
int (*okfn)(struct sock *, struct sk_buff *))
{
p->hook = hook;
p->thresh = thresh;
p->pf = pf;
p->in = indev;
p->out = outdev;
p->sk = sk;
p->okfn = okfn;
}

typedef unsigned int nf_hookfn(const struct nf_hook_ops *ops,
struct sk_buff *skb,
const struct nf_hook_state *state);
Expand Down Expand Up @@ -136,31 +156,29 @@ int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state);
* value indicates the packet has been consumed by the hook.
*/
static inline int nf_hook_thresh(u_int8_t pf, unsigned int hook,
struct sock *sk,
struct sk_buff *skb,
struct net_device *indev,
struct net_device *outdev,
int (*okfn)(struct sk_buff *), int thresh)
int (*okfn)(struct sock *, struct sk_buff *),
int thresh)
{
if (nf_hooks_active(pf, hook)) {
struct nf_hook_state state = {
.hook = hook,
.thresh = thresh,
.pf = pf,
.in = indev,
.out = outdev,
.okfn = okfn
};
struct nf_hook_state state;

nf_hook_state_init(&state, hook, thresh, pf,
indev, outdev, sk, okfn);
return nf_hook_slow(skb, &state);
}
return 1;
}

static inline int nf_hook(u_int8_t pf, unsigned int hook, struct sk_buff *skb,
struct net_device *indev, struct net_device *outdev,
int (*okfn)(struct sk_buff *))
static inline int nf_hook(u_int8_t pf, unsigned int hook, struct sock *sk,
struct sk_buff *skb, struct net_device *indev,
struct net_device *outdev,
int (*okfn)(struct sock *, struct sk_buff *))
{
return nf_hook_thresh(pf, hook, skb, indev, outdev, okfn, INT_MIN);
return nf_hook_thresh(pf, hook, sk, skb, indev, outdev, okfn, INT_MIN);
}

/* Activate hook; either okfn or kfree_skb called, unless a hook
Expand All @@ -181,35 +199,36 @@ static inline int nf_hook(u_int8_t pf, unsigned int hook, struct sk_buff *skb,
*/

static inline int
NF_HOOK_THRESH(uint8_t pf, unsigned int hook, struct sk_buff *skb,
struct net_device *in, struct net_device *out,
int (*okfn)(struct sk_buff *), int thresh)
NF_HOOK_THRESH(uint8_t pf, unsigned int hook, struct sock *sk,
struct sk_buff *skb, struct net_device *in,
struct net_device *out,
int (*okfn)(struct sock *, struct sk_buff *), int thresh)
{
int ret = nf_hook_thresh(pf, hook, skb, in, out, okfn, thresh);
int ret = nf_hook_thresh(pf, hook, sk, skb, in, out, okfn, thresh);
if (ret == 1)
ret = okfn(skb);
ret = okfn(sk, skb);
return ret;
}

static inline int
NF_HOOK_COND(uint8_t pf, unsigned int hook, struct sk_buff *skb,
struct net_device *in, struct net_device *out,
int (*okfn)(struct sk_buff *), bool cond)
NF_HOOK_COND(uint8_t pf, unsigned int hook, struct sock *sk,
struct sk_buff *skb, struct net_device *in, struct net_device *out,
int (*okfn)(struct sock *, struct sk_buff *), bool cond)
{
int ret;

if (!cond ||
((ret = nf_hook_thresh(pf, hook, skb, in, out, okfn, INT_MIN)) == 1))
ret = okfn(skb);
((ret = nf_hook_thresh(pf, hook, sk, skb, in, out, okfn, INT_MIN)) == 1))
ret = okfn(sk, skb);
return ret;
}

static inline int
NF_HOOK(uint8_t pf, unsigned int hook, struct sk_buff *skb,
NF_HOOK(uint8_t pf, unsigned int hook, struct sock *sk, struct sk_buff *skb,
struct net_device *in, struct net_device *out,
int (*okfn)(struct sk_buff *))
int (*okfn)(struct sock *, struct sk_buff *))
{
return NF_HOOK_THRESH(pf, hook, skb, in, out, okfn, INT_MIN);
return NF_HOOK_THRESH(pf, hook, sk, skb, in, out, okfn, INT_MIN);
}

/* Call setsockopt() */
Expand Down Expand Up @@ -309,19 +328,21 @@ nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, u_int8_t family)
}

#else /* !CONFIG_NETFILTER */
#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb)
#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) (okfn)(skb)
#define NF_HOOK(pf, hook, sk, skb, indev, outdev, okfn) (okfn)(sk, skb)
#define NF_HOOK_COND(pf, hook, sk, skb, indev, outdev, okfn, cond) (okfn)(sk, skb)
static inline int nf_hook_thresh(u_int8_t pf, unsigned int hook,
struct sock *sk,
struct sk_buff *skb,
struct net_device *indev,
struct net_device *outdev,
int (*okfn)(struct sk_buff *), int thresh)
int (*okfn)(struct sock *sk, struct sk_buff *), int thresh)
{
return okfn(skb);
return okfn(sk, skb);
}
static inline int nf_hook(u_int8_t pf, unsigned int hook, struct sk_buff *skb,
struct net_device *indev, struct net_device *outdev,
int (*okfn)(struct sk_buff *))
static inline int nf_hook(u_int8_t pf, unsigned int hook, struct sock *sk,
struct sk_buff *skb, struct net_device *indev,
struct net_device *outdev,
int (*okfn)(struct sock *, struct sk_buff *))
{
return 1;
}
Expand Down
2 changes: 1 addition & 1 deletion include/linux/netfilter_bridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ static inline unsigned int nf_bridge_mtu_reduction(const struct sk_buff *skb)
return 0;
}

int br_handle_frame_finish(struct sk_buff *skb);
int br_handle_frame_finish(struct sock *sk, struct sk_buff *skb);

static inline void br_drop_fake_rtable(struct sk_buff *skb)
{
Expand Down
6 changes: 3 additions & 3 deletions include/net/dn_neigh.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ struct dn_neigh {

void dn_neigh_init(void);
void dn_neigh_cleanup(void);
int dn_neigh_router_hello(struct sk_buff *skb);
int dn_neigh_endnode_hello(struct sk_buff *skb);
int dn_neigh_router_hello(struct sock *sk, struct sk_buff *skb);
int dn_neigh_endnode_hello(struct sock *sk, struct sk_buff *skb);
void dn_neigh_pointopoint_hello(struct sk_buff *skb);
int dn_neigh_elist(struct net_device *dev, unsigned char *ptr, int n);
int dn_to_neigh_output(struct sk_buff *skb);
int dn_to_neigh_output(struct sock *sk, struct sk_buff *skb);

extern struct neigh_table dn_neigh_table;

Expand Down
3 changes: 2 additions & 1 deletion include/net/ip.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,8 @@ int ip_local_deliver(struct sk_buff *skb);
int ip_mr_input(struct sk_buff *skb);
int ip_output(struct sock *sk, struct sk_buff *skb);
int ip_mc_output(struct sock *sk, struct sk_buff *skb);
int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *));
int ip_fragment(struct sock *sk, struct sk_buff *skb,
int (*output)(struct sock *, struct sk_buff *));
int ip_do_nat(struct sk_buff *skb);
void ip_send_check(struct iphdr *ip);
int __ip_local_out(struct sk_buff *skb);
Expand Down
3 changes: 2 additions & 1 deletion include/net/ip6_route.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,8 @@ static inline bool ipv6_anycast_destination(const struct sk_buff *skb)
return rt->rt6i_flags & RTF_ANYCAST;
}

int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *));
int ip6_fragment(struct sock *sk, struct sk_buff *skb,
int (*output)(struct sock *, struct sk_buff *));

static inline int ip6_skb_dst_mtu(struct sk_buff *skb)
{
Expand Down
5 changes: 3 additions & 2 deletions include/net/ip6_tunnel.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,14 @@ __u32 ip6_tnl_get_cap(struct ip6_tnl *t, const struct in6_addr *laddr,
struct net *ip6_tnl_get_link_net(const struct net_device *dev);
int ip6_tnl_get_iflink(const struct net_device *dev);

static inline void ip6tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
static inline void ip6tunnel_xmit(struct sock *sk, struct sk_buff *skb,
struct net_device *dev)
{
struct net_device_stats *stats = &dev->stats;
int pkt_len, err;

pkt_len = skb->len;
err = ip6_local_out(skb);
err = ip6_local_out_sk(sk, skb);

if (net_xmit_eval(err) == 0) {
struct pcpu_sw_netstats *tstats = this_cpu_ptr(dev->tstats);
Expand Down
3 changes: 2 additions & 1 deletion include/net/ipv6.h
Original file line number Diff line number Diff line change
Expand Up @@ -769,7 +769,7 @@ static inline u8 ip6_tclass(__be32 flowinfo)
int ipv6_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt, struct net_device *orig_dev);

int ip6_rcv_finish(struct sk_buff *skb);
int ip6_rcv_finish(struct sock *sk, struct sk_buff *skb);

/*
* upper-layer output functions
Expand Down Expand Up @@ -827,6 +827,7 @@ int ip6_input(struct sk_buff *skb);
int ip6_mc_input(struct sk_buff *skb);

int __ip6_local_out(struct sk_buff *skb);
int ip6_local_out_sk(struct sock *sk, struct sk_buff *skb);
int ip6_local_out(struct sk_buff *skb);

/*
Expand Down
5 changes: 3 additions & 2 deletions include/net/udp_tunnel.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,14 @@ void setup_udp_tunnel_sock(struct net *net, struct socket *sock,
struct udp_tunnel_sock_cfg *sock_cfg);

/* Transmit the skb using UDP encapsulation. */
int udp_tunnel_xmit_skb(struct rtable *rt, struct sk_buff *skb,
int udp_tunnel_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *skb,
__be32 src, __be32 dst, __u8 tos, __u8 ttl,
__be16 df, __be16 src_port, __be16 dst_port,
bool xnet, bool nocheck);

#if IS_ENABLED(CONFIG_IPV6)
int udp_tunnel6_xmit_skb(struct dst_entry *dst, struct sk_buff *skb,
int udp_tunnel6_xmit_skb(struct dst_entry *dst, struct sock *sk,
struct sk_buff *skb,
struct net_device *dev, struct in6_addr *saddr,
struct in6_addr *daddr,
__u8 prio, __u8 ttl, __be16 src_port,
Expand Down
2 changes: 1 addition & 1 deletion include/net/vxlan.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ struct vxlan_sock *vxlan_sock_add(struct net *net, __be16 port,

void vxlan_sock_release(struct vxlan_sock *vs);

int vxlan_xmit_skb(struct rtable *rt, struct sk_buff *skb,
int vxlan_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *skb,
__be32 src, __be32 dst, __u8 tos, __u8 ttl, __be16 df,
__be16 src_port, __be16 dst_port, struct vxlan_metadata *md,
bool xnet, u32 vxflags);
Expand Down
8 changes: 4 additions & 4 deletions include/net/xfrm.h
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ struct xfrm_state_afinfo {
int (*tmpl_sort)(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n);
int (*state_sort)(struct xfrm_state **dst, struct xfrm_state **src, int n);
int (*output)(struct sock *sk, struct sk_buff *skb);
int (*output_finish)(struct sk_buff *skb);
int (*output_finish)(struct sock *sk, struct sk_buff *skb);
int (*extract_input)(struct xfrm_state *x,
struct sk_buff *skb);
int (*extract_output)(struct xfrm_state *x,
Expand Down Expand Up @@ -1503,7 +1503,7 @@ int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb);
int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type);
int xfrm_input_resume(struct sk_buff *skb, int nexthdr);
int xfrm_output_resume(struct sk_buff *skb, int err);
int xfrm_output(struct sk_buff *skb);
int xfrm_output(struct sock *sk, struct sk_buff *skb);
int xfrm_inner_extract_output(struct xfrm_state *x, struct sk_buff *skb);
void xfrm_local_error(struct sk_buff *skb, int mtu);
int xfrm4_extract_header(struct sk_buff *skb);
Expand All @@ -1524,7 +1524,7 @@ static inline int xfrm4_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi)
int xfrm4_extract_output(struct xfrm_state *x, struct sk_buff *skb);
int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb);
int xfrm4_output(struct sock *sk, struct sk_buff *skb);
int xfrm4_output_finish(struct sk_buff *skb);
int xfrm4_output_finish(struct sock *sk, struct sk_buff *skb);
int xfrm4_rcv_cb(struct sk_buff *skb, u8 protocol, int err);
int xfrm4_protocol_register(struct xfrm4_protocol *handler, unsigned char protocol);
int xfrm4_protocol_deregister(struct xfrm4_protocol *handler, unsigned char protocol);
Expand All @@ -1549,7 +1549,7 @@ __be32 xfrm6_tunnel_spi_lookup(struct net *net, const xfrm_address_t *saddr);
int xfrm6_extract_output(struct xfrm_state *x, struct sk_buff *skb);
int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb);
int xfrm6_output(struct sock *sk, struct sk_buff *skb);
int xfrm6_output_finish(struct sk_buff *skb);
int xfrm6_output_finish(struct sock *sk, struct sk_buff *skb);
int xfrm6_find_1stfragopt(struct xfrm_state *x, struct sk_buff *skb,
u8 **prevhdr);

Expand Down
Loading

0 comments on commit e0e8db2

Please sign in to comment.