<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Audit Archives - Linuxcent</title>
	<atom:link href="https://linuxcent.com/tag/audit/feed/" rel="self" type="application/rss+xml" />
	<link>https://linuxcent.com/tag/audit/</link>
	<description>Infrastructure security, from the kernel up.</description>
	<lastBuildDate>Tue, 07 Jul 2026 03:13:25 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0.4</generator>

<image>
	<url>https://linuxcent.com/wp-content/uploads/2026/04/favicon-512x512-1-150x150.png</url>
	<title>Audit Archives - Linuxcent</title>
	<link>https://linuxcent.com/tag/audit/</link>
	<width>32</width>
	<height>32</height>
</image> 
<site xmlns="com-wordpress:feed-additions:1">211632295</site>	<item>
		<title>The Audit Playbook — Four Commands to See Any Cluster</title>
		<link>https://linuxcent.com/the-audit-playbook-four-commands-to-see-any-cluster/</link>
					<comments>https://linuxcent.com/the-audit-playbook-four-commands-to-see-any-cluster/#respond</comments>
		
		<dc:creator><![CDATA[Vamshi Krishna Santhapuri]]></dc:creator>
		<pubDate>Tue, 14 Jul 2026 02:00:00 +0000</pubDate>
				<category><![CDATA[eBPF]]></category>
		<category><![CDATA[Audit]]></category>
		<category><![CDATA[bpftool]]></category>
		<category><![CDATA[Kubernetes]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[SRE]]></category>
		<guid isPermaLink="false">https://linuxcent.com/?p=2228</guid>

					<description><![CDATA[<p><span class="span-reading-time rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Reading Time: </span> <span class="rt-time"> 8</span> <span class="rt-label rt-postfix">minutes</span></span>eBPF: From Kernel to Cloud, Episode 14 What Is eBPF? · The BPF Verifier · eBPF vs Kernel Modules · eBPF Program Types · eBPF Maps · CO-RE and libbpf · XDP · TC eBPF · bpftrace · Network Flow Observability · DNS Observability · LSM and Tetragon · Process Lineage · The Audit Playbook ... <a title="The Audit Playbook — Four Commands to See Any Cluster" class="read-more" href="https://linuxcent.com/the-audit-playbook-four-commands-to-see-any-cluster/" aria-label="Read more about The Audit Playbook — Four Commands to See Any Cluster">Read more</a></p>
<p>The post <a href="https://linuxcent.com/the-audit-playbook-four-commands-to-see-any-cluster/">The Audit Playbook — Four Commands to See Any Cluster</a> appeared first on <a href="https://linuxcent.com">Linuxcent</a>.</p>
]]></description>
										<content:encoded><![CDATA[<span class="span-reading-time rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Reading Time: </span> <span class="rt-time"> 8</span> <span class="rt-label rt-postfix">minutes</span></span><style>
pre{position:relative;background:#1e1e1e;color:#d4d4d4;
    padding:16px 16px 16px 20px;border-radius:6px;overflow-x:auto;
    font-family:'JetBrains Mono','Fira Code','Cascadia Code',Consolas,'Courier New',monospace;
    font-size:.88em;line-height:1.6;border-left:4px solid #555}
code{background:#f4f4f4;padding:2px 5px;border-radius:3px;font-size:.9em}
pre code{background:transparent;padding:0;color:inherit}
pre[data-lang="bash"],pre[data-lang="sh"],
pre[data-lang="shell"],pre[data-lang="zsh"]{border-left-color:#4ec9b0}
pre[data-lang="yaml"],pre[data-lang="json"],
pre[data-lang="toml"],pre[data-lang="xml"]{border-left-color:#569cd6}
pre[data-lang="python"],pre[data-lang="go"],pre[data-lang="rust"],
pre[data-lang="java"],pre[data-lang="c"],pre[data-lang="cpp"]{border-left-color:#c586c0}
pre[data-lang="text"],pre[data-lang="output"],
pre[data-lang="console"]{border-left-color:#888}
.lc-copy-btn{position:absolute;top:8px;right:8px;background:#2d2d2d;color:#ccc;
    border:1px solid #444;border-radius:4px;padding:3px 9px;font-size:.75em;
    font-family:system-ui,sans-serif;cursor:pointer;opacity:0;
    transition:opacity .15s,background .15s;line-height:1.6}
pre:hover .lc-copy-btn{opacity:1}
.lc-copy-btn:hover{background:#3a3a3a;color:#fff}
.lc-copy-btn.copied{color:#4ec9b0;border-color:#4ec9b0}
.lc-lang-badge{position:absolute;top:8px;left:20px;font-family:system-ui,sans-serif;
    font-size:.7em;color:#666;text-transform:uppercase;letter-spacing:.04em;
    line-height:1;pointer-events:none;opacity:0;transition:opacity .15s}
pre:hover .lc-lang-badge{opacity:1}
table{border-collapse:collapse;width:100%;margin:16px 0}
th,td{border:1px solid #ddd;padding:10px 14px;text-align:left}
th{background:#f0f0f0;font-weight:600}
tr:nth-child(even){background:#fafafa}
</style>
<p><script>
(function(){
  if(window.__lcCodeEnhanced)return;
  window.__lcCodeEnhanced=true;
  function enhance(){
    document.querySelectorAll('pre').forEach(function(pre){
      var code=pre.querySelector('code');
      var lang='';
      if(code){var m=(code.className||'').match(/language-(\S+)/);if(m)lang=m[1].toLowerCase();}
      if(lang)pre.setAttribute('data-lang',lang);
      if(lang){var badge=document.createElement('span');badge.className='lc-lang-badge';badge.textContent=lang;pre.insertBefore(badge,pre.firstChild);}
      var btn=document.createElement('button');
      btn.className='lc-copy-btn';btn.textContent='Copy';btn.setAttribute('aria-label','Copy code to clipboard');
      pre.appendChild(btn);
      btn.addEventListener('click',function(){
        var text=code?code.innerText:pre.innerText;
        if(navigator.clipboard&&window.isSecureContext){
          navigator.clipboard.writeText(text).then(function(){ok(btn);}).catch(function(){fb(text,btn);});
        }else{fb(text,btn);}
      });
    });
  }
  function ok(btn){btn.textContent='Copied!';btn.classList.add('copied');setTimeout(function(){btn.textContent='Copy';btn.classList.remove('copied');},2000);}
  function fb(text,btn){
    try{var ta=document.createElement('textarea');ta.value=text;ta.style.cssText='position:fixed;left:-9999px;top:-9999px;opacity:0';document.body.appendChild(ta);ta.select();document.execCommand('copy');document.body.removeChild(ta);ok(btn);}
    catch(e){btn.textContent='✗ Failed';setTimeout(function(){btn.textContent='Copy';},2000);}
  }
  if(document.readyState==='loading'){document.addEventListener('DOMContentLoaded',enhance);}else{enhance();}
})();
</script></p>
<p><em>eBPF: From Kernel to Cloud, Episode 14</em><br />
<a href="/what-is-ebpf-linux-kubernetes/">What Is eBPF?</a> · <a href="/bpf-verifier-kubernetes-safety/">The BPF Verifier</a> · <a href="/ebpf-vs-kernel-modules-kubernetes/">eBPF vs Kernel Modules</a> · <a href="/ebpf-program-types-kubernetes/">eBPF Program Types</a> · <a href="/ebpf-maps-explained/">eBPF Maps</a> · <a href="/ebpf-co-re-libbpf-portable-programs/">CO-RE and libbpf</a> · <a href="/ebpf-xdp-kubernetes-networking/">XDP</a> · <a href="/tc-ebpf-kubernetes-network-policy/">TC eBPF</a> · <a href="/bpftrace-kernel-observability/">bpftrace</a> · <a href="/ebpf-network-flow-observability/">Network Flow Observability</a> · <a href="/ebpf-dns-observability-kubernetes/">DNS Observability</a> · <a href="/ebpf-lsm-tetragon-runtime-security/">LSM and Tetragon</a> · <a href="/ebpf-process-lineage-incident-response/">Process Lineage</a> · <strong>The Audit Playbook</strong></p>
<hr />
<h2 id="tldr">TL;DR</h2>
<ul>
<li>You can audit eBPF programs on any Kubernetes cluster with four <code class="" data-line="">bpftool</code> commands, regardless of which vendor&#8217;s tool loaded them — <code class="" data-line="">prog show</code>, <code class="" data-line="">map show</code>, <code class="" data-line="">net show</code> (plus <code class="" data-line="">cgroup tree</code>), and <code class="" data-line="">prog dump xlated</code><br />
  <em>(bpftool = the kernel-shipped CLI for inspecting loaded eBPF programs and maps directly, independent of any userspace agent or vendor tooling)</em></li>
<li><code class="" data-line="">bpftool prog show</code> gives you the inventory: every loaded program, its type, and — via its pinned path — usually which tool owns it</li>
<li><code class="" data-line="">bpftool map show</code> gives you the state: what data each program is reading or writing, cross-referenced by the <code class="" data-line="">map_ids</code> from the first command</li>
<li><code class="" data-line="">bpftool net show</code> and <code class="" data-line="">bpftool cgroup tree</code> give you the attachment points: which interface, which qdisc, which cgroup hook — where enforcement actually happens</li>
<li><code class="" data-line="">bpftool prog dump xlated</code> gives you the behavior: what the program does at the instruction level, for the cases where the pinned path doesn&#8217;t tell you enough</li>
<li>This sequence works whether the cluster is running Cilium, Falco, Tetragon, a hand-rolled XDP filter, or something with no documentation at all — the kernel doesn&#8217;t care who loaded the program</li>
</ul>
<hr />
<p>You inherit a cluster with no runbook, no README, and no answer to &#8220;what&#8217;s making the policy decisions.&#8221; Something on these nodes is dropping packets, or blocking execs, or both — and you have about ten minutes before the incident call starts. <code class="" data-line="">kubectl get pods -A</code> tells you nothing; whatever this is doesn&#8217;t run as a normal pod workload you can just describe.</p>
<h2 id="quick-check-is-anything-actually-loaded-on-this-node">Quick Check: Is Anything Actually Loaded on This Node?</h2>
<pre><code class="" data-line=""># On any cluster node — count loaded eBPF programs
bpftool prog show | wc -l

# Expected output (a cluster running Cilium + Tetragon):
# 47
</code></pre>
<pre><code class="" data-line=""># Break it down by program type
bpftool prog show | grep -oE &#039;^\S+:\s+\K\S+&#039; 2&gt;/dev/null || \
bpftool prog show -j | jq -r &#039;.[].type&#039; | sort | uniq -c

#   12 cgroup_skb      ← Cilium&#039;s per-cgroup socket filtering
#    8 sched_cls       ← TC programs (Cilium&#039;s netdev enforcement, from EP08)
#    6 kprobe          ← Tetragon&#039;s syscall hooks (from EP12)
#    4 tracepoint      ← process/exec tracing (from EP13)
#    2 xdp             ← XDP fast-path filtering (from EP07)
</code></pre>
<blockquote>
<p><strong>Not running Cilium or Tetragon? On EKS or GKE?</strong> The count won&#8217;t be zero even on a &#8220;vanilla&#8221; managed cluster — kube-proxy&#8217;s eBPF mode (if enabled), the CNI&#8217;s own eBPF datapath, and any sidecar-less service mesh all load programs. A count of zero on a production node is itself worth investigating; it usually means you&#8217;re looking at a node pool that hasn&#8217;t finished bootstrapping, or <code class="" data-line="">bpftool</code> is running in a mount namespace that can&#8217;t see the host&#8217;s BPF filesystem.</p>
</blockquote>
<p>Forty-seven loaded programs and no idea which ones matter. That&#8217;s the audit playbook&#8217;s job: turn &#8220;something is loaded&#8221; into &#8220;here is exactly what it is, what it holds, where it enforces, and what it does&#8221; — four commands, in order, no vendor documentation required.</p>
<h2 id="command-1-inventory-whats-loaded-and-who-owns-it">Command 1: Inventory — What&#8217;s Loaded, and Who Owns It</h2>
<p><code class="" data-line="">bpftool prog show</code> lists every eBPF program currently loaded into the kernel on that node, regardless of which process or tool loaded it. The kernel tracks programs independently of the userspace agent that created them — the program keeps running even if that agent&#8217;s pod is deleted.</p>
<pre><code class="" data-line="">bpftool prog show
</code></pre>
<pre><code class="" data-line="">6: cgroup_skb  tag 6deef7357e7b4530  gpl
    loaded_at 2026-06-02T03:14:22+0000  uid 0
    xlated 296B  jited 187B  memlock 4096B  map_ids 4,5
142: sched_cls  name cil_from_netdev  tag a04f5eef06a7f555  gpl
    loaded_at 2026-06-02T03:15:01+0000  uid 0
    xlated 12664B  jited 7532B  memlock 16384B  map_ids 9,10,11,14
    pinned /sys/fs/bpf/tc/globals/cil_from_netdev
201: kprobe  name generic_kprobe_e  tag 88df3d0a1c9e2b41  gpl
    loaded_at 2026-06-02T04:02:18+0000  uid 0
    xlated 3184B  jited 1980B  memlock 8192B  map_ids 22,23
    pinned /sys/fs/bpf/tetragon/generic_kprobe_e
</code></pre>
<blockquote>
<p><strong>Program <code class="" data-line="">tag</code></strong> — a SHA hash of the program&#8217;s instruction stream, computed by the kernel at load time. Two programs with the same tag are running byte-identical bytecode, even if they were loaded by different processes or have different names. It&#8217;s how you confirm two clusters are actually running the same version of a security tool without comparing source.</p>
<p><strong>Pinned path</strong> — a program pinned to <code class="" data-line="">/sys/fs/bpf/...</code> survives after the process that loaded it exits, because the reference is held by a file in the in-kernel BPF filesystem instead of by an open file descriptor in a running process. Most production tools pin their programs; ad hoc programs loaded by a one-off script usually don&#8217;t, and disappear the moment that script&#8217;s process exits.</p>
</blockquote>
<p>The <code class="" data-line="">pinned</code> field is doing most of the audit work here. <code class="" data-line="">/sys/fs/bpf/tc/globals/...</code> is Cilium&#8217;s convention. <code class="" data-line="">/sys/fs/bpf/tetragon/...</code> is Tetragon&#8217;s. Falco&#8217;s kernel-module and eBPF probe modes typically pin under <code class="" data-line="">/sys/fs/bpf/falco*</code>. A program with no <code class="" data-line="">pinned</code> line at all was loaded without a persistent reference — worth asking what process is holding its file descriptor open, because if that process dies, the program unloads.</p>
<blockquote>
<p><strong>For operators (not writing eBPF):</strong> if a security tool&#8217;s DaemonSet pod restarts and its programs <em>don&#8217;t</em> reappear in <code class="" data-line="">bpftool prog show</code> after the container comes back up, that&#8217;s a real signal — the tool failed to re-pin or re-attach, and you&#8217;re running with a gap in coverage even though the pod shows <code class="" data-line="">Running</code>. This is a more reliable health check than the pod&#8217;s own readiness probe, which usually only checks that the userspace agent process is alive.</p>
</blockquote>
<h2 id="command-2-state-what-data-these-programs-are-keeping">Command 2: State — What Data These Programs Are Keeping</h2>
<p>Every <code class="" data-line="">map_ids</code> value in the <code class="" data-line="">prog show</code> output points at a BPF map — the persistent, kernel-resident data structure the program reads or writes on every invocation (see <a href="/ebpf-maps-explained/">eBPF Maps</a> for how these work). <code class="" data-line="">bpftool map show</code> inventories them the same way.</p>
<pre><code class="" data-line="">bpftool map show id 9
</code></pre>
<pre><code class="" data-line="">9: hash  name cilium_lb4_service  flags 0x0
    key 8B  value 24B  max_entries 65536  memlock 6291456B
</code></pre>
<pre><code class="" data-line="">bpftool map show id 22
</code></pre>
<pre><code class="" data-line="">22: lru_hash  name tg_execve_map  flags 0x0
    key 4B  value 128B  max_entries 32768  memlock 12582912B
    pinned /sys/fs/bpf/tetragon/tg_execve_map
</code></pre>
<p>Map ID 9 is a service load-balancer table — 65,536 entries, keyed by a service identifier. Map ID 22 is Tetragon&#8217;s exec cache (the same process-tracking structure covered in <a href="/ebpf-process-lineage-incident-response/">process lineage reconstruction</a>), an LRU hash that evicts its oldest entries once 32,768 processes have been tracked.</p>
<p>The name field alone often tells you what the map is for — <code class="" data-line="">cilium_lb4_service</code>, <code class="" data-line="">tg_execve_map</code> — because most production tools name their maps descriptively rather than leaving them anonymous. When a map has no descriptive name, dump a few entries and read the shape of the data:</p>
<pre><code class="" data-line="">bpftool map dump id 9 | head -5
</code></pre>
<pre><code class="" data-line="">key: 0a 00 00 01 00 00 00 50  value: c0 a8 01 0a 00 00 00 50 00 00 00 01 ...
</code></pre>
<p>Raw bytes without a BTF type description are harder to read, but the sizes still tell you something: an 8-byte key and 24-byte value, repeated 65,536 times, is a fixed-size lookup table — consistent with a service or connection map, not a log or event buffer.</p>
<h2 id="command-3-attachment-where-enforcement-actually-happens">Command 3: Attachment — Where Enforcement Actually Happens</h2>
<p>Inventory and state tell you what&#8217;s loaded and what it remembers. They don&#8217;t tell you where in the packet or syscall path the program actually runs. <code class="" data-line="">bpftool net show</code> answers that for network-attached programs (XDP and TC, from <a href="/ebpf-xdp-kubernetes-networking/">EP07</a> and <a href="/tc-ebpf-kubernetes-network-policy/">EP08</a>); <code class="" data-line="">bpftool cgroup tree</code> answers it for cgroup-attached programs (socket and syscall hooks).</p>
<pre><code class="" data-line="">bpftool net show
</code></pre>
<pre><code class="" data-line="">xdp:
eth0(2) driver id 88 tag 3b185187f1855c4c

tc:
eth0(2) clsact/ingress cil_from_netdev id 142
eth0(2) clsact/egress cil_to_netdev id 143
</code></pre>
<pre><code class="" data-line="">bpftool cgroup tree
</code></pre>
<pre><code class="" data-line="">CgroupPath
ID       AttachType      AttachFlags     Name
/sys/fs/cgroup
         6        cgroup_skb      multi
        18        cgroup_sock_addr multi           cil_sock4_connect
</code></pre>
<p>Program ID 142 — the same <code class="" data-line="">cil_from_netdev</code> you saw in the <code class="" data-line="">prog show</code> output — is attached to <code class="" data-line="">eth0</code>&#8216;s ingress <code class="" data-line="">clsact</code> qdisc. That&#8217;s a direct answer to &#8220;is something making kernel-level policy decisions on this interface&#8221;: yes, at TC ingress, before the packet reaches any userspace process. Program ID 6 (<code class="" data-line="">cgroup_skb</code>) is attached at the root cgroup with <code class="" data-line="">multi</code> flags, meaning it stacks with other programs there rather than replacing them — the enforcement isn&#8217;t exclusive to one tool.</p>
<blockquote>
<p><strong><code class="" data-line="">multi</code> vs exclusive attach flags:</strong> cgroup and TC attachments can either replace whatever was attached before (exclusive) or stack alongside it (<code class="" data-line="">multi</code>/<code class="" data-line="">BPF_F_ALLOW_MULTI</code>). A cluster running more than one eBPF-based tool at the same hook point relies on <code class="" data-line="">multi</code> attachment; if you see an exclusive attach where you expected two tools to coexist, one of them silently lost its hook.</p>
</blockquote>
<h2 id="command-4-behavior-what-it-actually-does">Command 4: Behavior — What It Actually Does</h2>
<p>The first three commands answer what&#8217;s loaded, what it remembers, and where it runs. They don&#8217;t answer what it <em>does</em> — and that matters when the pinned path is missing, unfamiliar, or you don&#8217;t trust it. <code class="" data-line="">bpftool prog dump xlated</code> shows the program&#8217;s instructions after the verifier&#8217;s transformations, in a readable pseudo-assembly.</p>
<pre><code class="" data-line="">bpftool prog dump xlated id 142 | head -12
</code></pre>
<pre><code class="" data-line="">   0: (b7) r0 = 0
   1: (61) r2 = *(u32 *)(r1 +76)
   2: (61) r3 = *(u32 *)(r1 +80)
   3: (bf) r1 = r6
   4: (85) call bpf_skb_load_bytes#26
   5: (16) if w0 == 0x8 goto pc+3
   6: (05) goto pc+9
   7: (61) r1 = *(u32 *)(r6 +0)
   8: (55) r1 != 0x800 goto pc+7
</code></pre>
<p>You don&#8217;t need to hand-trace every instruction to get value out of this. Look for the helper calls — <code class="" data-line="">bpf_skb_load_bytes</code>, <code class="" data-line="">bpf_map_lookup_elem</code>, <code class="" data-line="">bpf_redirect</code>, <code class="" data-line="">bpf_ktime_get_ns</code> — because they name the kernel facilities the program actually touches. A program whose xlated dump is full of <code class="" data-line="">bpf_map_lookup_elem</code> and comparison instructions against <code class="" data-line="">0x800</code> (IPv4&#8217;s EtherType) is doing packet classification. One full of <code class="" data-line="">bpf_probe_read</code> and <code class="" data-line="">bpf_get_current_task</code> is reading process or memory state, not packets — a strong signal you&#8217;re looking at an observability or enforcement hook, not a network one, whatever its pinned path claims.</p>
<blockquote>
<p><strong>For operators (not writing eBPF):</strong> you will not read xlated dumps line by line during an incident. What you&#8217;re checking for is much narrower — does the helper call list match what the tool&#8217;s marketing says it does? A program that claims to be &#8220;read-only observability&#8221; but calls <code class="" data-line="">bpf_skb_store_bytes</code> (which <em>writes</em> packet data) is not read-only. That mismatch is worth escalating before you trust the tool&#8217;s own dashboard.</p>
</blockquote>
<hr />
<h2 id="production-gotchas"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/26a0.png" alt="⚠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Production Gotchas</h2>
<p><strong><code class="" data-line="">bpftool</code> needs <code class="" data-line="">CAP_BPF</code> or root, and managed nodes don&#8217;t hand that out by default.</strong> On EKS and GKE, you typically can&#8217;t SSH to a node directly. Use <code class="" data-line="">kubectl debug node/&lt;node-name&gt; --image=&lt;image-with-bpftool&gt; -it -- chroot /host</code> to get a privileged shell with host PID and network namespace access, or the cloud provider&#8217;s session-manager equivalent (AWS SSM, <code class="" data-line="">gcloud compute ssh</code>). Confirm the debug image actually ships <code class="" data-line="">bpftool</code> — it&#8217;s not in most minimal base images.</p>
<p><strong>Program IDs are node-local and not stable across restarts.</strong> ID 142 today may be ID 89 after the node reboots and the DaemonSet reloads its programs. Don&#8217;t hardcode IDs in runbooks; always start from <code class="" data-line="">bpftool prog show</code> on the specific node and re-derive the ID for that session.</p>
<p><strong><code class="" data-line="">xlated</code> and <code class="" data-line="">jited</code> dumps require the kernel to have kept the debug info.</strong> Some hardened kernel configs strip <code class="" data-line="">CONFIG_BPF_JIT_ALWAYS_ON</code> debug metadata or disable <code class="" data-line="">kernel.bpf_stats_enabled</code>, in which case <code class="" data-line="">prog dump</code> returns less than shown here. If dumps come back empty, check <code class="" data-line="">sysctl kernel.bpf_stats_enabled</code> before assuming the program itself is hiding something.</p>
<p><strong><code class="" data-line="">bpftool cgroup tree</code> only shows attachments below the cgroup you run it from.</strong> On a Kubernetes node, run it from the root of the host&#8217;s cgroup filesystem (typically after the <code class="" data-line="">chroot /host</code> from the debug pod above), not from inside a container&#8217;s own cgroup namespace, or you&#8217;ll only see a fraction of the attachments.</p>
<p><strong>Pinned paths are a convention, not a guarantee.</strong> Nothing stops a tool from pinning under an unexpected path, or not pinning at all. Treat the pinned-path-to-vendor mapping as a strong hint that narrows your investigation, not as ground truth — confirm ownership with the <code class="" data-line="">tag</code> (command 1) against the vendor&#8217;s published program hashes when it matters for an incident, not just a routine audit.</p>
<hr />
<h2 id="quick-reference">Quick Reference</h2>
<table>
<thead>
<tr>
<th>What you want to know</th>
<th>Command</th>
</tr>
</thead>
<tbody>
<tr>
<td>What&#8217;s loaded</td>
<td><code class="" data-line="">bpftool prog show</code></td>
</tr>
<tr>
<td>Program count by type</td>
<td><code class="" data-line="">bpftool prog show -j \| jq -r &#039;.[].type&#039; \| sort \| uniq -c</code></td>
</tr>
<tr>
<td>What state a program keeps</td>
<td><code class="" data-line="">bpftool map show id &lt;N&gt;</code> (from <code class="" data-line="">map_ids</code> in prog show)</td>
</tr>
<tr>
<td>Sample map contents</td>
<td><code class="" data-line="">bpftool map dump id &lt;N&gt; \| head</code></td>
</tr>
<tr>
<td>Where it&#8217;s attached (network)</td>
<td><code class="" data-line="">bpftool net show</code></td>
</tr>
<tr>
<td>Where it&#8217;s attached (cgroup)</td>
<td><code class="" data-line="">bpftool cgroup tree</code></td>
</tr>
<tr>
<td>What it actually does</td>
<td><code class="" data-line="">bpftool prog dump xlated id &lt;N&gt;</code></td>
</tr>
<tr>
<td>Confirm identical bytecode across nodes</td>
<td>Compare <code class="" data-line="">tag</code> values from <code class="" data-line="">prog show</code></td>
</tr>
<tr>
<td>Privileged shell on a managed node</td>
<td><code class="" data-line="">kubectl debug node/&lt;name&gt; --image=&lt;img&gt; -it -- chroot /host</code></td>
</tr>
</tbody>
</table>
<hr />
<h2 id="key-takeaways">Key Takeaways</h2>
<ul>
<li>Four <code class="" data-line="">bpftool</code> commands audit any eBPF-based tool on any Kubernetes cluster, regardless of vendor: <code class="" data-line="">prog show</code> (inventory), <code class="" data-line="">map show</code> (state), <code class="" data-line="">net show</code>/<code class="" data-line="">cgroup tree</code> (attachment), <code class="" data-line="">prog dump xlated</code> (behavior)</li>
<li>The kernel tracks loaded programs independently of the userspace agent that loaded them — a program&#8217;s pinned path under <code class="" data-line="">/sys/fs/bpf/...</code> usually identifies its owning tool by convention, but that convention is not enforced by the kernel</li>
<li>A program&#8217;s <code class="" data-line="">tag</code> is a hash of its bytecode; matching tags across nodes confirm identical program versions without comparing source or vendor documentation</li>
<li><code class="" data-line="">map_ids</code> in <code class="" data-line="">prog show</code> output link directly to <code class="" data-line="">bpftool map show</code>, letting you trace from &#8220;a program is loaded&#8221; to &#8220;here&#8217;s exactly what data it reads and writes&#8221;</li>
<li><code class="" data-line="">bpftool net show</code> and <code class="" data-line="">cgroup tree</code> answer where enforcement happens in the packet or syscall path — the same question the opening incident needed answered in ten minutes</li>
<li>When the pinned path and tag aren&#8217;t enough, <code class="" data-line="">bpftool prog dump xlated</code> shows the actual kernel helper calls the program makes, which is the only way to confirm behavior when there&#8217;s no documentation to trust</li>
</ul>
<hr />
<h2 id="whats-next">What&#8217;s Next</h2>
<p>EP14 is the audit playbook — the four commands you run in the first ten minutes on any cluster you&#8217;ve inherited, before you trust anything its existing tools tell you about themselves. EP15 goes deeper on one specific case where this matters most: Cilium&#8217;s own policy engine telling you traffic is allowed while packets keep dropping. <code class="" data-line="">bpftool map dump</code> on the right map — not <code class="" data-line="">cilium policy get</code> — is what shows you what&#8217;s actually being enforced.</p>
<p><em>Next: <a href="/cilium-policy-verification-bpftool/">Cilium policy verification — what bpftool shows that cilium policy get doesn&#8217;t</a></em></p>
<p>Get EP15 in your inbox when it publishes → <a href="https://linuxcent.com/subscribe">linuxcent.com/subscribe</a></p>
<p><a class="a2a_button_mastodon" href="https://www.addtoany.com/add_to/mastodon?linkurl=https%3A%2F%2Flinuxcent.com%2Fthe-audit-playbook-four-commands-to-see-any-cluster%2F&amp;linkname=The%20Audit%20Playbook%20%E2%80%94%20Four%20Commands%20to%20See%20Any%20Cluster" title="Mastodon" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_email" href="https://www.addtoany.com/add_to/email?linkurl=https%3A%2F%2Flinuxcent.com%2Fthe-audit-playbook-four-commands-to-see-any-cluster%2F&amp;linkname=The%20Audit%20Playbook%20%E2%80%94%20Four%20Commands%20to%20See%20Any%20Cluster" title="Email" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_whatsapp" href="https://www.addtoany.com/add_to/whatsapp?linkurl=https%3A%2F%2Flinuxcent.com%2Fthe-audit-playbook-four-commands-to-see-any-cluster%2F&amp;linkname=The%20Audit%20Playbook%20%E2%80%94%20Four%20Commands%20to%20See%20Any%20Cluster" title="WhatsApp" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_reddit" href="https://www.addtoany.com/add_to/reddit?linkurl=https%3A%2F%2Flinuxcent.com%2Fthe-audit-playbook-four-commands-to-see-any-cluster%2F&amp;linkname=The%20Audit%20Playbook%20%E2%80%94%20Four%20Commands%20to%20See%20Any%20Cluster" title="Reddit" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_x" href="https://www.addtoany.com/add_to/x?linkurl=https%3A%2F%2Flinuxcent.com%2Fthe-audit-playbook-four-commands-to-see-any-cluster%2F&amp;linkname=The%20Audit%20Playbook%20%E2%80%94%20Four%20Commands%20to%20See%20Any%20Cluster" title="X" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_linkedin" href="https://www.addtoany.com/add_to/linkedin?linkurl=https%3A%2F%2Flinuxcent.com%2Fthe-audit-playbook-four-commands-to-see-any-cluster%2F&amp;linkname=The%20Audit%20Playbook%20%E2%80%94%20Four%20Commands%20to%20See%20Any%20Cluster" title="LinkedIn" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_copy_link" href="https://www.addtoany.com/add_to/copy_link?linkurl=https%3A%2F%2Flinuxcent.com%2Fthe-audit-playbook-four-commands-to-see-any-cluster%2F&amp;linkname=The%20Audit%20Playbook%20%E2%80%94%20Four%20Commands%20to%20See%20Any%20Cluster" title="Copy Link" rel="nofollow noopener" target="_blank"></a><a class="a2a_dd addtoany_share_save addtoany_share" href="https://www.addtoany.com/share#url=https%3A%2F%2Flinuxcent.com%2Fthe-audit-playbook-four-commands-to-see-any-cluster%2F&#038;title=The%20Audit%20Playbook%20%E2%80%94%20Four%20Commands%20to%20See%20Any%20Cluster" data-a2a-url="https://linuxcent.com/the-audit-playbook-four-commands-to-see-any-cluster/" data-a2a-title="The Audit Playbook — Four Commands to See Any Cluster"></a></p><p>The post <a href="https://linuxcent.com/the-audit-playbook-four-commands-to-see-any-cluster/">The Audit Playbook — Four Commands to See Any Cluster</a> appeared first on <a href="https://linuxcent.com">Linuxcent</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://linuxcent.com/the-audit-playbook-four-commands-to-see-any-cluster/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2228</post-id>	</item>
	</channel>
</rss>

<!--
Performance optimized by W3 Total Cache. Learn more: https://www.boldgrid.com/w3-total-cache/?utm_source=w3tc&utm_medium=footer_comment&utm_campaign=free_plugin

Page Caching using Disk: Enhanced 

Served from: linuxcent.com @ 2026-08-23 02:44:35 by W3 Total Cache
-->