lunatik: enforce per-CPU semantics at the registration points - #678
Merged
Conversation
lneto
force-pushed
the
claude_percpu_enforcement
branch
2 times, most recently
from
August 6, 2026 12:59
5d359c5 to
0f3cefa
Compare
lneto
force-pushed
the
claude_percpu_enforcement
branch
2 times, most recently
from
August 6, 2026 13:43
1a6eba8 to
6ee94ef
Compare
This was referenced Aug 7, 2026
lneto
force-pushed
the
claude_percpu_enforcement
branch
3 times, most recently
from
August 8, 2026 10:54
40bdd3a to
e26a81e
Compare
lneto
force-pushed
the
claude_percpu_enforcement
branch
from
August 9, 2026 13:43
e26a81e to
2786065
Compare
| int lunatik_runtime(lunatik_object_t **pruntime, const char *script, lunatik_opt_t opt) | ||
| { | ||
| return lunatik_newruntime(pruntime, NULL, script, opt); | ||
| return lunatik_newruntime(pruntime, NULL, script, opt, -1); |
Member
There was a problem hiding this comment.
Could we reuse LUNATIK_CPU_NONE here? I suppose -1 here means no cpu instance.
Contributor
Author
There was a problem hiding this comment.
Yes. That call is the one site the sweep missed when the sentinel was named. Fixed: 6b5d4e3f
Contributor
Author
There was a problem hiding this comment.
good catch, btw.. ;-) thanks!
Member
|
Hi @lneto the PR description talks about cpu affinity at dispatch but the code changes refuse percpu mode for netfilter. I think we should update the PR description just so that it remains correct if someone references it in future. |
lneto
force-pushed
the
claude_percpu_enforcement
branch
from
August 9, 2026 15:09
6b5d4e3 to
fdb5ccd
Compare
The runner passes the instance id to lunatik.runtime(), which stores it in the state's extraspace before the script is loaded, so load-time registrations can read it; lunatik.cpu() exposes it to the script, on the stub library as well since percpu scripts are usually softirq. runner.run no longer forwards its vararg tail: with cpu as the third argument of lunatik.runtime(), a stray extra would silently claim an instance id for a plain runtime. Groundwork for the registration-point enforcement (#675). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A constructor whose registration is global would be registered once per instance by a percpu script: N chardevs, N notifier callbacks, N kprobes on the same symbol. Refuse at load, with an error naming percpu, through a shared helper adopted by device, notifier, probe and hid; the eBPF attach and the per-runtime objects stay untouched (#675). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Each instance registers its own hook, so every packet is handled once per instance, and there is no per-CPU dispatch to hand an instance the packets of its own CPU. Refuse at load until there is one. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
lneto
force-pushed
the
claude_percpu_enforcement
branch
from
August 9, 2026 15:11
fdb5ccd to
9e474bc
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Resolves #675: the registration points now apply the percpu policy, instead of trusting the script.
The runtime carries its instance CPU id in the state's extraspace, stored before the script is loaded so load-time registrations can read it, and
lunatik.cpu()exposes it to the script (on the stub library as well: percpu scripts are usually softirq).runner.runno longer forwards its vararg tail, since a stray extra would silently claim an instance id for a plain runtime.With the id in place, every registration a percpu instance cannot own is refused at load, with an error naming percpu, through a shared
lunatik_checkpercpuhelper:device,notifier,probe,hid;netfilter.register, which has no per-CPU dispatch: each instance would register its own hook and every packet would be handled once per instance. An earlier version of this branch shipped affinity at dispatch instead, each hook accepting everything not on its CPU, but that is exact only where the hook runs in softirq; on the process-context paths a migration mid-chain can handle a packet twice or not at all, so it was dropped rather than merged as a half measure. The exact form, a single hook per script dispatching to the instance of the current CPU, needs group identity in the core and builds on the percpu groups work (lunatik: percpu groups, one object owning one runtime per CPU #693).syscallwas audited and left alone (address lookup only); the eBPFattachand the per-runtime objects need nothing.Tests, each validated by breaking the code and watching it fail:
lunatik.cpu()coverage in the percpu suite (every id stamped, a plain runtime seesnil), and the refusals fordevice.newandnetfilter.register, failing at load in a percpu instance with a clean rollback, with the same scripts running plain.Tested on 6.8.0-136: full suite green with clean dmesg; builds clean against 5.15 and 6.8 headers.
🤖 Generated with Claude Code