Skip to content

Instantly share code, notes, and snippets.

@christarazi
Last active January 7, 2022 20:38
Show Gist options
  • Save christarazi/4bb48eb623a03f25026be21856ea10fb to your computer and use it in GitHub Desktop.
Save christarazi/4bb48eb623a03f25026be21856ea10fb to your computer and use it in GitHub Desktop.
#include <linux/skbuff.h>
#include <net/flow.h>
#include <net/xfrm.h>
/*
* This script was used to debug https://github.com/cilium/cilium/issues/15826
* and create https://github.com/cilium/cilium/pull/16057.
*
* The script will attach to functions in the XFRM subsystem around XFRM
* policy lookup and evaluation. The probes are defined in the order of their
* execution when a packet arrives into the kernel.
*
* Packets are identified across the different probes by their mark.
*/
/* Optional */
/* kprobe:skb_scrub_packet */
/* { */
/* #<{(| void skb_scrub_packet(struct sk_buff *skb, bool xnet) |)}># */
/* */
/* $skb = (struct sk_buff *) arg0; */
/* $xnet = arg1; */
/* */
/* printf("scrub(skb->mark:0x%x, xnet:%d)\n", $skb->mark, $xnet); */
/* } */
kprobe:secpath_set
{
/* struct sec_path *secpath_set(struct sk_buff *skb) */
$skb = (struct sk_buff *) arg0;
printf("secpath_set(skb->mark:0x%x) ", $skb->mark);
}
kretprobe:secpath_set
{
printf("=> %d\n", retval);
}
kprobe:__xfrm_policy_check
{
/* int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
* unsigned short family)
*/
$sock = arg0;
$dir = arg1 & XFRM_POLICY_MASK;
$skb = (struct sk_buff *) arg2;
$family = arg3;
/* static inline bool skb_ext_exist(const struct sk_buff *skb, enum skb_ext_id id)
* {
* return skb->active_extensions & (1 << id);
* }
*/
$id = SKB_EXT_SEC_PATH;
if (($skb->active_extensions & (1 << $id)) != 0) {
$ext = "skb active extensions";
/* static inline void *skb_ext_find(const struct sk_buff *skb, enum skb_ext_id id)
* {
* if (skb_ext_exist(skb, id)) {
* struct skb_ext *ext = skb->extensions;
*
* return (void *)ext + (ext->offset[id] << 3);
* }
*
* return NULL;
* }
*/
$sp = (struct skb_ext *) $skb->extensions;
/* bpftrace don't allow dynamic array access, so the `1` is
*`SKB_EXT_SEC_PATH`, aka `$id`.
*
* We also must cast to a integral pointer type and dereference
* in order to do the arithmetic, otherwise bpftrace will complain.
*/
$sp = (struct skb_ext *) ((*(uint8 *) $sp) + ($sp->offset[1] << 3));
} else {
$ext = "no extensions";
}
printf("check(X, dir:%d, skb->mark:0x%x (%s [sp:%d]), family:%hu)\n",
$dir, $skb->mark, $ext, $sp, $family);
}
kretprobe:__xfrm_policy_check
{
printf("check() => %d\n", retval);
}
kprobe:xfrm_policy_lookup_bytype
{
/* static struct xfrm_policy *xfrm_policy_lookup_bytype(struct net *net, u8 type,
* const struct flowi *fl,
* u16 family, u8 dir,
* u32 if_id)
*/
$type = arg1;
$fl = (struct flowi *) arg2;
$family = arg3;
$dir = arg4;
$if_id = arg5;
if ($type == 0) {
printf(" lookup(X, flmark:0x%x, family:%u, dir:%u, if_id:%u)\n",
$fl->flowi_mark, $family, $dir, $if_id);
}
}
kretprobe:xfrm_policy_lookup_bytype
{
printf(" lookup() => %d\n", retval);
}
kprobe:xfrm_policy_match
{
/* static int xfrm_policy_match(const struct xfrm_policy *pol,
* const struct flowi *fl,
* u8 type, u16 family, int dir, u32 if_id)
*/
$pol = (struct xfrm_policy *) arg0;
$fl = (struct flowi *) arg1;
$type = arg2;
$family = arg3;
$dir = arg4;
$if_id = arg5;
if ($type == 0) {
/* if (pol->family != family ||
* pol->if_id != if_id ||
* (fl->flowi_mark & pol->mark.m) != pol->mark.v ||
* pol->type != type)
* return ret;
*/
printf(" match(X, type:%hu, X, family:%u, dir:%u, if_id:%u)\n",
$type, $family, $dir, $if_id);
printf(" pol->family: %u\n", $pol->family);
printf(" pol->if_id: %u\n", $pol->if_id);
/* (fl->flowi_mark & pol->mark.m) != pol->mark.v || */
printf(" flowi_mark:0x%x & pol->mark.m:0x%x != pol->mark.v:0x%x\n",
$fl->flowi_mark, $pol->mark.m, $pol->mark.v);
}
}
kretprobe:xfrm_policy_match
{
printf(" match() => %d\n", retval);
}
#include <linux/skbuff.h>
#include <uapi/linux/ip.h>
#include <linux/byteorder/generic.h>
kprobe:__xfrm_policy_check
{
$dir = arg1;
$skb = (struct sk_buff *) arg2;
$family = arg3;
$ip_header = (struct iphdr *) ($skb->head + $skb->network_header);
printf("check(X, dir:%d, (%u %u) mark:0x%x, family:%d)\n",
$dir, $ip_header->saddr, $ip_header->daddr, $skb->mark, $family);
}
kretprobe:__xfrm_policy_check
{
printf("check() => %d\n", retval);
}
kprobe:xfrm_policy_lookup
{
$fl = (struct flowi *) arg1;
$family = arg2;
$dir = arg3;
$if_id = arg4;
printf(" lookup(X, X, flmark:0x%x, family:%u, dir:%u, if_id:%u) ",
$fl->flowi_mark, $family, $dir, $if_id);
}
kretprobe:xfrm_policy_lookup
{
printf("=> %d\n", retval);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment