Skip to content

Commit

Permalink
bpf: Preserve source identity for hairpin via stack
Browse files Browse the repository at this point in the history
[ upstream commit f25d8b9 ]

When Cilium is used in chaining mode with portmap, the hostPort is
translated using iptables DNAT as inserted by the portmap plugin.  When
this happens all within a node, we can preserve the source identity for
the reply traffic for correct visibility. The traffic will be allowed
anyway based on the connection tracking state.

To work with clang-7 and avoid the pattern where the ctx is read into
a register and then incremented then finally a value assigned to it,

  r1 = %[ctx]
  r1 += 8
  ...
  *(u32)(r1 +=8) = %[mark]

We wrote the code block in asm which is not the same as master branch
which was able to use C code due to use of clang-11. We attempted to
update the branch to clang-10 but that created a separate set of issue
that was causing more code churn than we wanted.

Updates: #9784

Signed-off-by: Thomas Graf <thomas@cilium.io>
Signed-off-by: John Fastabend <john.fastabend@gmail.com>
  • Loading branch information
jrfastab committed Apr 29, 2020
1 parent 9bb1770 commit 3f472a5
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 5 deletions.
45 changes: 41 additions & 4 deletions bpf/bpf_lxc.c
Expand Up @@ -64,6 +64,35 @@ static inline bool redirect_to_proxy(int verdict, __u8 dir)
(dir == CT_NEW || dir == CT_ESTABLISHED);
}
#endif
/* clang-7 workaround, the intended C code generates the following
* r1 = r6
* r1 += 8
* ... some other code r6 is ctx pointer buts it is lost after += op
* *(u32 *)(r1 +0) = r4
* resulting in verifier error,
* "dereference of modified ctx ptr R1 off=9 disallowed"
* to resolve this we use the below asm helper to force asm the
* verifier can follow.
*/
static inline void asm_set_seclabel_identity(struct __sk_buff *skb)
{
__u32 mark = MARK_MAGIC_IDENTITY;
__u32 key = MARK_MAGIC_KEY_MASK;
__u32 identity = SECLABEL;

bpf_barrier();
mark |= ((identity & 0xFFFF) << 16) | ((identity & 0xFF0000) >> 16);

asm volatile("r1 = *(u32 *)(%[ctx] +8)\n\t"
"r1 &= %[key]\n\t"
"r1 |= %[mark]\n\t"
"*(u32 *)(%[ctx] +8) = r1\n\t"
:
: [ctx]"r"(skb), [key]"i"(key), [mark]"r"(mark)
:"r1");
bpf_barrier();
}


#ifdef ENABLE_IPV6
static inline int ipv6_l3_from_lxc(struct __sk_buff *skb,
Expand Down Expand Up @@ -362,12 +391,15 @@ static inline int ipv6_l3_from_lxc(struct __sk_buff *skb,
set_encrypt_key(skb, encrypt_key);
#ifdef IP_POOLS
set_encrypt_dip(skb, tunnel_endpoint);
#else
set_identity(skb, SECLABEL);
#endif
}
#endif
#endif
/* Always encode the source identity when passing to the stack. If the
* stack hairpins the packet back to a local endpoint the source
* identity can still be derived even if SNAT is performed by a
* component such as portmap */
asm_set_seclabel_identity(skb);
return TC_ACT_OK;
}

Expand Down Expand Up @@ -697,12 +729,17 @@ static inline int handle_ipv4_from_lxc(struct __sk_buff *skb, __u32 *dstID)
set_encrypt_key(skb, encrypt_key);
#ifdef IP_POOLS
set_encrypt_dip(skb, tunnel_endpoint);
#else
set_identity(skb, SECLABEL);
#endif
}
#endif
#endif

/* Always encode the source identity when passing to the stack. If the
* stack hairpins the packet back to a local endpoint the source
* identity can still be derived even if SNAT is performed by a
* component such as portmap */
/* clang-7 workaround */
asm_set_seclabel_identity(skb);
cilium_dbg_capture(skb, DBG_CAPTURE_DELIVERY, 0);
return TC_ACT_OK;
}
Expand Down
2 changes: 1 addition & 1 deletion daemon/bpf.sha
@@ -1,2 +1,2 @@
GO_BINDATA_SHA1SUM=4c9c0828b112a3149f980f7a3d37f8a2bc68b155
GO_BINDATA_SHA1SUM=8d960d8e9b27d4db6ee23783803b118d5976d2d5
BPF_FILES=../bpf/COPYING ../bpf/Makefile ../bpf/Makefile.bpf ../bpf/bpf_alignchecker.c ../bpf/bpf_features.h ../bpf/bpf_hostdev_ingress.c ../bpf/bpf_ipsec.c ../bpf/bpf_lxc.c ../bpf/bpf_netdev.c ../bpf/bpf_network.c ../bpf/bpf_overlay.c ../bpf/bpf_sock.c ../bpf/bpf_xdp.c ../bpf/cilium-map-migrate.c ../bpf/filter_config.h ../bpf/include/bpf/api.h ../bpf/include/elf/elf.h ../bpf/include/elf/gelf.h ../bpf/include/elf/libelf.h ../bpf/include/iproute2/bpf_elf.h ../bpf/include/linux/bpf.h ../bpf/include/linux/bpf_common.h ../bpf/include/linux/byteorder.h ../bpf/include/linux/byteorder/big_endian.h ../bpf/include/linux/byteorder/little_endian.h ../bpf/include/linux/icmp.h ../bpf/include/linux/icmpv6.h ../bpf/include/linux/if_arp.h ../bpf/include/linux/if_ether.h ../bpf/include/linux/if_packet.h ../bpf/include/linux/in.h ../bpf/include/linux/in6.h ../bpf/include/linux/ioctl.h ../bpf/include/linux/ip.h ../bpf/include/linux/ipv6.h ../bpf/include/linux/perf_event.h ../bpf/include/linux/swab.h ../bpf/include/linux/tcp.h ../bpf/include/linux/type_mapper.h ../bpf/include/linux/udp.h ../bpf/init.sh ../bpf/lib/arp.h ../bpf/lib/common.h ../bpf/lib/config.h ../bpf/lib/conntrack.h ../bpf/lib/conntrack_map.h ../bpf/lib/conntrack_test.h ../bpf/lib/csum.h ../bpf/lib/dbg.h ../bpf/lib/drop.h ../bpf/lib/encap.h ../bpf/lib/eps.h ../bpf/lib/eth.h ../bpf/lib/events.h ../bpf/lib/icmp6.h ../bpf/lib/identity.h ../bpf/lib/ipv4.h ../bpf/lib/ipv6.h ../bpf/lib/ipv6_test.h ../bpf/lib/l3.h ../bpf/lib/l4.h ../bpf/lib/lb.h ../bpf/lib/lxc.h ../bpf/lib/maps.h ../bpf/lib/metrics.h ../bpf/lib/nat.h ../bpf/lib/nat46.h ../bpf/lib/nodeport.h ../bpf/lib/policy.h ../bpf/lib/signal.h ../bpf/lib/tailcall.h ../bpf/lib/trace.h ../bpf/lib/utils.h ../bpf/lib/xdp.h ../bpf/lxc_config.h ../bpf/netdev_config.h ../bpf/node_config.h ../bpf/probes/raw_change_tail.t ../bpf/probes/raw_fib_lookup.t ../bpf/probes/raw_insn.h ../bpf/probes/raw_invalidate_hash.t ../bpf/probes/raw_lpm_map.t ../bpf/probes/raw_lru_map.t ../bpf/probes/raw_main.c ../bpf/probes/raw_max_insn.t ../bpf/probes/raw_sock_cookie.t ../bpf/run_probes.sh ../bpf/sockops/Makefile ../bpf/sockops/bpf_redir.c ../bpf/sockops/bpf_sockops.c ../bpf/sockops/bpf_sockops.h ../bpf/sockops/sockops_config.h

0 comments on commit 3f472a5

Please sign in to comment.