[PATCH v2] bpf: fix check of allowed specifiers in bpf_trace_printk

2018-11-23 Thread Martynas Pumputis
A format string consisting of "%p" or "%s" followed by an invalid
specifier (e.g. "%p%\n" or "%s%") could pass the check which
would make format_decode (lib/vsprintf.c) to warn.

Reported-by: syzbot+1ec5c5ec949c4adaa...@syzkaller.appspotmail.com
Signed-off-by: Martynas Pumputis 
---
 kernel/trace/bpf_trace.c | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index 08fcfe440c63..9864a35c8bb5 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -196,11 +196,13 @@ BPF_CALL_5(bpf_trace_printk, char *, fmt, u32, fmt_size, 
u64, arg1,
i++;
} else if (fmt[i] == 'p' || fmt[i] == 's') {
mod[fmt_cnt]++;
-   i++;
-   if (!isspace(fmt[i]) && !ispunct(fmt[i]) && fmt[i] != 0)
+   /* disallow any further format extensions */
+   if (fmt[i + 1] != 0 &&
+   !isspace(fmt[i + 1]) &&
+   !ispunct(fmt[i + 1]))
return -EINVAL;
fmt_cnt++;
-   if (fmt[i - 1] == 's') {
+   if (fmt[i] == 's') {
if (str_seen)
/* allow only one '%s' per fmt string */
return -EINVAL;
-- 
2.19.1



[PATCH] bpf: fix check of allowed specifiers in bpf_trace_printk

2018-11-22 Thread Martynas Pumputis
A format string consisting of "%p" or "%s" followed by an invalid
specifier (e.g. "%p%\n" or "%s%") could pass the check which
would make format_decode (lib/vsprintf.c) to warn.

Reported-by: syzbot+1ec5c5ec949c4adaa...@syzkaller.appspotmail.com
Signed-off-by: Martynas Pumputis 
---
 kernel/trace/bpf_trace.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index 08fcfe440c63..9ab05736e1a1 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -225,6 +225,8 @@ BPF_CALL_5(bpf_trace_printk, char *, fmt, u32, fmt_size, 
u64, arg1,
(void *) (long) unsafe_addr,
sizeof(buf));
}
+   if (fmt[i] == '%')
+   i--;
continue;
}
 
-- 
2.19.1



[PATCH v2] vxlan: Set ports in flow key when doing route lookups

2017-01-11 Thread Martynas Pumputis
Otherwise, a xfrm policy with sport/dport being set cannot be matched.

Signed-off-by: Martynas Pumputis <martynas@weave.works>
---
Changes in v2:
- Set the source port in the flow key.

 drivers/net/vxlan.c | 13 ++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index bb70dd5..ca7196c 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -1798,7 +1798,7 @@ static int vxlan_build_skb(struct sk_buff *skb, struct 
dst_entry *dst,
 static struct rtable *vxlan_get_route(struct vxlan_dev *vxlan, struct 
net_device *dev,
  struct vxlan_sock *sock4,
  struct sk_buff *skb, int oif, u8 tos,
- __be32 daddr, __be32 *saddr,
+ __be32 daddr, __be32 *saddr, __be16 
dport, __be16 sport,
  struct dst_cache *dst_cache,
  const struct ip_tunnel_info *info)
 {
@@ -1824,6 +1824,8 @@ static struct rtable *vxlan_get_route(struct vxlan_dev 
*vxlan, struct net_device
fl4.flowi4_proto = IPPROTO_UDP;
fl4.daddr = daddr;
fl4.saddr = *saddr;
+   fl4.fl4_dport = dport;
+   fl4.fl4_sport = sport;
 
rt = ip_route_output_key(vxlan->net, );
if (likely(!IS_ERR(rt))) {
@@ -1851,6 +1853,7 @@ static struct dst_entry *vxlan6_get_route(struct 
vxlan_dev *vxlan,
  __be32 label,
  const struct in6_addr *daddr,
  struct in6_addr *saddr,
+ __be16 dport, __be16 sport,
  struct dst_cache *dst_cache,
  const struct ip_tunnel_info *info)
 {
@@ -1877,6 +1880,8 @@ static struct dst_entry *vxlan6_get_route(struct 
vxlan_dev *vxlan,
fl6.flowlabel = ip6_make_flowinfo(RT_TOS(tos), label);
fl6.flowi6_mark = skb->mark;
fl6.flowi6_proto = IPPROTO_UDP;
+   fl6.fl6_dport = dport;
+   fl6.fl6_sport = sport;
 
err = ipv6_stub->ipv6_dst_lookup(vxlan->net,
 sock6->sock->sk,
@@ -2068,6 +2073,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct 
net_device *dev,
 rdst ? rdst->remote_ifindex : 0, tos,
 dst->sin.sin_addr.s_addr,
 >sin.sin_addr.s_addr,
+dst_port, src_port,
 dst_cache, info);
if (IS_ERR(rt)) {
err = PTR_ERR(rt);
@@ -2104,6 +2110,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct 
net_device *dev,
rdst ? rdst->remote_ifindex : 0, tos,
label, >sin6.sin6_addr,
>sin6.sin6_addr,
+   dst_port, src_port,
dst_cache, info);
if (IS_ERR(ndst)) {
err = PTR_ERR(ndst);
@@ -2430,7 +2437,7 @@ static int vxlan_fill_metadata_dst(struct net_device 
*dev, struct sk_buff *skb)
 
rt = vxlan_get_route(vxlan, dev, sock4, skb, 0, info->key.tos,
 info->key.u.ipv4.dst,
->key.u.ipv4.src, NULL, info);
+>key.u.ipv4.src, dport, sport, NULL, 
info);
if (IS_ERR(rt))
return PTR_ERR(rt);
ip_rt_put(rt);
@@ -2441,7 +2448,7 @@ static int vxlan_fill_metadata_dst(struct net_device 
*dev, struct sk_buff *skb)
 
ndst = vxlan6_get_route(vxlan, dev, sock6, skb, 0, 
info->key.tos,
info->key.label, >key.u.ipv6.dst,
-   >key.u.ipv6.src, NULL, info);
+   >key.u.ipv6.src, dport, sport, 
NULL, info);
if (IS_ERR(ndst))
return PTR_ERR(ndst);
dst_release(ndst);
-- 
2.10.2



[PATCH] vxlan: Set flow*_dport when doing route lookups

2017-01-10 Thread Martynas Pumputis
Otherwise, no xfrm policy with dport being set can be matched.

Signed-off-by: Martynas Pumputis <martynas@weave.works>
---
 drivers/net/vxlan.c | 11 ---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index bb70dd5..fcfe786 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -1798,7 +1798,7 @@ static int vxlan_build_skb(struct sk_buff *skb, struct 
dst_entry *dst,
 static struct rtable *vxlan_get_route(struct vxlan_dev *vxlan, struct 
net_device *dev,
  struct vxlan_sock *sock4,
  struct sk_buff *skb, int oif, u8 tos,
- __be32 daddr, __be32 *saddr,
+ __be32 daddr, __be32 *saddr, __be16 dport,
  struct dst_cache *dst_cache,
  const struct ip_tunnel_info *info)
 {
@@ -1824,6 +1824,7 @@ static struct rtable *vxlan_get_route(struct vxlan_dev 
*vxlan, struct net_device
fl4.flowi4_proto = IPPROTO_UDP;
fl4.daddr = daddr;
fl4.saddr = *saddr;
+   fl4.fl4_dport = dport;
 
rt = ip_route_output_key(vxlan->net, );
if (likely(!IS_ERR(rt))) {
@@ -1851,6 +1852,7 @@ static struct dst_entry *vxlan6_get_route(struct 
vxlan_dev *vxlan,
  __be32 label,
  const struct in6_addr *daddr,
  struct in6_addr *saddr,
+ __be16 dport,
  struct dst_cache *dst_cache,
  const struct ip_tunnel_info *info)
 {
@@ -1877,6 +1879,7 @@ static struct dst_entry *vxlan6_get_route(struct 
vxlan_dev *vxlan,
fl6.flowlabel = ip6_make_flowinfo(RT_TOS(tos), label);
fl6.flowi6_mark = skb->mark;
fl6.flowi6_proto = IPPROTO_UDP;
+   fl6.fl6_dport = dport;
 
err = ipv6_stub->ipv6_dst_lookup(vxlan->net,
 sock6->sock->sk,
@@ -2068,6 +2071,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct 
net_device *dev,
 rdst ? rdst->remote_ifindex : 0, tos,
 dst->sin.sin_addr.s_addr,
 >sin.sin_addr.s_addr,
+dst_port,
 dst_cache, info);
if (IS_ERR(rt)) {
err = PTR_ERR(rt);
@@ -2104,6 +2108,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct 
net_device *dev,
rdst ? rdst->remote_ifindex : 0, tos,
label, >sin6.sin6_addr,
>sin6.sin6_addr,
+   dst_port,
dst_cache, info);
if (IS_ERR(ndst)) {
err = PTR_ERR(ndst);
@@ -2430,7 +2435,7 @@ static int vxlan_fill_metadata_dst(struct net_device 
*dev, struct sk_buff *skb)
 
rt = vxlan_get_route(vxlan, dev, sock4, skb, 0, info->key.tos,
 info->key.u.ipv4.dst,
->key.u.ipv4.src, NULL, info);
+>key.u.ipv4.src, dport, NULL, info);
if (IS_ERR(rt))
return PTR_ERR(rt);
ip_rt_put(rt);
@@ -2441,7 +2446,7 @@ static int vxlan_fill_metadata_dst(struct net_device 
*dev, struct sk_buff *skb)
 
ndst = vxlan6_get_route(vxlan, dev, sock6, skb, 0, 
info->key.tos,
info->key.label, >key.u.ipv6.dst,
-   >key.u.ipv6.src, NULL, info);
+   >key.u.ipv6.src, dport, NULL, 
info);
if (IS_ERR(ndst))
return PTR_ERR(ndst);
dst_release(ndst);
-- 
2.10.2



[PATCH] openvswitch: do not ignore netdev errors when creating tunnel vports

2016-08-09 Thread Martynas Pumputis
The creation of a tunnel vport (geneve, gre, vxlan) brings up a
corresponding netdev, a multi-step operation which can fail.

For example, changing a vxlan vport's netdev state to 'up' binds the
vport's socket to a UDP port - if the binding fails (e.g. due to the
port being in use), the error is currently ignored giving the
appearance that the tunnel vport creation completed successfully.

Signed-off-by: Martynas Pumputis <martynas@weave.works>
---
 net/openvswitch/vport-geneve.c |  9 -
 net/openvswitch/vport-gre.c| 11 +--
 net/openvswitch/vport-vxlan.c  |  9 -
 3 files changed, 25 insertions(+), 4 deletions(-)

diff --git a/net/openvswitch/vport-geneve.c b/net/openvswitch/vport-geneve.c
index 1a1fcec..5aaf3ba 100644
--- a/net/openvswitch/vport-geneve.c
+++ b/net/openvswitch/vport-geneve.c
@@ -93,7 +93,14 @@ static struct vport *geneve_tnl_create(const struct 
vport_parms *parms)
return ERR_CAST(dev);
}
 
-   dev_change_flags(dev, dev->flags | IFF_UP);
+   err = dev_change_flags(dev, dev->flags | IFF_UP);
+   if (err < 0) {
+   rtnl_delete_link(dev);
+   rtnl_unlock();
+   ovs_vport_free(vport);
+   goto error;
+   }
+
rtnl_unlock();
return vport;
 error:
diff --git a/net/openvswitch/vport-gre.c b/net/openvswitch/vport-gre.c
index 7f8897f..0e72d95 100644
--- a/net/openvswitch/vport-gre.c
+++ b/net/openvswitch/vport-gre.c
@@ -54,6 +54,7 @@ static struct vport *gre_tnl_create(const struct vport_parms 
*parms)
struct net *net = ovs_dp_get_net(parms->dp);
struct net_device *dev;
struct vport *vport;
+   int err;
 
vport = ovs_vport_alloc(0, _gre_vport_ops, parms);
if (IS_ERR(vport))
@@ -67,9 +68,15 @@ static struct vport *gre_tnl_create(const struct vport_parms 
*parms)
return ERR_CAST(dev);
}
 
-   dev_change_flags(dev, dev->flags | IFF_UP);
-   rtnl_unlock();
+   err = dev_change_flags(dev, dev->flags | IFF_UP);
+   if (err < 0) {
+   rtnl_delete_link(dev);
+   rtnl_unlock();
+   ovs_vport_free(vport);
+   return ERR_PTR(err);
+   }
 
+   rtnl_unlock();
return vport;
 }
 
diff --git a/net/openvswitch/vport-vxlan.c b/net/openvswitch/vport-vxlan.c
index 5eb7694..7eb955e 100644
--- a/net/openvswitch/vport-vxlan.c
+++ b/net/openvswitch/vport-vxlan.c
@@ -130,7 +130,14 @@ static struct vport *vxlan_tnl_create(const struct 
vport_parms *parms)
return ERR_CAST(dev);
}
 
-   dev_change_flags(dev, dev->flags | IFF_UP);
+   err = dev_change_flags(dev, dev->flags | IFF_UP);
+   if (err < 0) {
+   rtnl_delete_link(dev);
+   rtnl_unlock();
+   ovs_vport_free(vport);
+   goto error;
+   }
+
rtnl_unlock();
return vport;
 error:
-- 
2.9.0