Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tetragon: harden actions a bit #3279

Merged
merged 7 commits into from
Feb 25, 2025
Merged

tetragon: harden actions a bit #3279

merged 7 commits into from
Feb 25, 2025

Conversation

olsajiri
Copy link
Contributor

@olsajiri olsajiri commented Jan 7, 2025

Adding new filter logic that triggers when process is not found in
execve_map (likely due to exhausted capacity).

In this case we currently exit the bpf program and that might leave
some crucial actions not executed (like sigkill).

We add new event_find_curr_probe call to gather process info in filter
context and use it to execute filters. The resulting kprobe event will
have minimal process data with 'unknown' flags field.

@olsajiri olsajiri added the release-note/minor This PR introduces a minor user-visible change label Jan 7, 2025
@olsajiri olsajiri force-pushed the pr/olsajiri/harden branch 3 times, most recently from 7b664dd to ab3513b Compare January 7, 2025 13:31
Comment on lines 109 to 110
threads := readFileDefault("/proc/sys/kernel/threads-max", 32768)
ExecveMap.SetMaxEntries(int(threads))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need this? It seems it will make the size of the execve_map even larger as threads-max is often well above 32K. This will take significant space while running threads-max threads is pretty rare nop?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried this as mitigation for https://github.com/isovalent/security/issues/88 .. I think we need some combination of this change (with some reasonable size for execve_map) and other ways mentioned in the issue

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah I see, maybe this is one of the cases where NO_PREALLOC could help so that we can dynamically size to a very large map. But I could see how this can lead to memory issues in the future. That's not an easy problem :/

@olsajiri olsajiri force-pushed the pr/olsajiri/harden branch 2 times, most recently from c64e7e4 to fcfa0a9 Compare January 13, 2025 14:28
Copy link

netlify bot commented Jan 13, 2025

Deploy Preview for tetragon ready!

Name Link
🔨 Latest commit 18aac9b
🔍 Latest deploy log https://app.netlify.com/sites/tetragon/deploys/67bd7cbd499cd400081ef1ac
😎 Deploy Preview https://deploy-preview-3279--tetragon.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

@@ -416,4 +419,6 @@ func AddFlags(flags *pflag.FlagSet) {
flags.Int(KeyEventCacheRetryDelay, defaults.DefaultEventCacheRetryDelay, "Delay in seconds between event cache retries")

flags.Bool(KeyCompatibilitySyscall64SizeType, false, "syscall64 type will produce output of type size (compatibility flag, will be removed in v1.4)")

flags.String(KeyExecveMapEntries, "", "Set entries for execve_map table (default 32768)")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we have the default from the actual default value here? If we ever change it, the change should be reflected in help.

@olsajiri olsajiri force-pushed the pr/olsajiri/harden branch 7 times, most recently from db51eba to 44fdaa4 Compare January 21, 2025 11:17
@olsajiri olsajiri changed the title tetragon: Setup execve_map max entries tetragon: harden actions a bit Feb 3, 2025
@olsajiri olsajiri force-pushed the pr/olsajiri/harden branch 5 times, most recently from b8b9d4e to bafb514 Compare February 16, 2025 14:15
@olsajiri olsajiri force-pushed the pr/olsajiri/harden branch 3 times, most recently from 6132585 to f6e5835 Compare February 18, 2025 22:05
@olsajiri olsajiri marked this pull request as ready for review February 19, 2025 09:13
@olsajiri olsajiri requested a review from a team as a code owner February 19, 2025 09:13
@olsajiri olsajiri requested a review from jrfastab February 19, 2025 09:13
@olsajiri
Copy link
Contributor Author

note the checkpatch fails on container_of macro which is false alarm

@olsajiri olsajiri requested review from kkourt and mtardy February 24, 2025 10:50
Copy link
Member

@mtardy mtardy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, there are a few things I didn't understand though.

Comment on lines -582 to +595
e->common.flags |= MSG_COMMON_FLAG_RETURN;
e->common.flags = MSG_COMMON_FLAG_RETURN;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure to follow why we want this change?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

setting flags early in the processing so in following changes the filter tail call can change it (which is executed before current flags setup code) (from commit changelog)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hum for that specific line we need to initialize the flags for return kprobe, I guess it could have probably went to separate patch

Comment on lines +292 to +317
#ifdef __LARGE_BPF_PROG
FUNC_INLINE struct execve_map_value *
event_find_curr_probe(struct msg_generic_kprobe *msg)
{
struct task_struct *task = (struct task_struct *)get_current_task();
struct execve_map_value *curr;

curr = &msg->curr;
curr->key.pid = BPF_CORE_READ(task, tgid);
curr->key.ktime = ktime_get_ns();
curr->nspid = get_task_pid_vnr_by_task(task);

get_current_subj_caps(&curr->caps, task);
get_namespaces(&curr->ns, task);
set_in_init_tree(curr, NULL);

read_exe((struct task_struct *)get_current_task(), &msg->exe);
return curr;
}
#else
FUNC_INLINE struct execve_map_value *
event_find_curr_probe(struct msg_generic_kprobe *msg)
{
return NULL;
}
#endif
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what's the benefit of doing this instead of writing the function unconditionally and making the calling conditional to LARGE PROGS? Wouldn't that be more explicit that non large prog do not support that?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well I think it's logically isolated piece of code which should be in function and is different for __LARGE_BPF_PROG define, so it makes sense to me to do the above

also I think it's better/readable/more manageble than having ifdefs inside the code

if (!enter) {
enter = event_find_curr_probe(msg);
if (!enter)
return PFILTER_CURR_NOT_FOUND;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it okay that this function always return PFILTER_CURR_NOT_FOUND on !__LARGE_BPF_PROG kernels? I guess this related to my other comment, there's something I don't understand I think

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hum, not sure I understand, even current code returns PFILTER_CURR_NOT_FOUND

t.Skip("sigkill requires at least 5.3.0 version")
}

// makeSpecFile creates a new spec file bsed on the template, and the provided arguments
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: we don't really care but since I saw it, little typo here bsed to based


option.Config.ExecveMapEntries = 1
testSigkill(t, makeSpecFile, checker)
option.Config.ExecveMapEntries = 0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why the set to 0 here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIUC option.Config is global, so we need to reset option.Config.ExecveMapEntries so other tests will get default value

Adding new 'unknown' value for flags field in the message Process.
It will be used in following changes for process without details.

Signed-off-by: Jiri Olsa <[email protected]>
Moving d_path into bpf_d_path.h header so it can be easily used in
following changes from other places.

Signed-off-by: Jiri Olsa <[email protected]>
Moving read_exe into process.h header so it can be easily used in
following changes from other places.

Signed-off-by: Jiri Olsa <[email protected]>
Setting flags early in the processing so in following changes the
filter tail call can change it (which is executed before current
flags setup code).

Signed-off-by: Jiri Olsa <[email protected]>
Adding new filter logic that triggers when process is not found in
execve_map (likely due to exhausted capacity).

In this case we currently exit the bpf program and that might leave
some crucial actions not executed (like sigkill).

We add new event_find_curr_probe call to gather process info in filter
context and use it to execute filters. The resulting kprobe event will
have minimal process data with 'unknown' flags field.

Signed-off-by: Jiri Olsa <[email protected]>
Adding test for unknown process kprobe kill.

Signed-off-by: Jiri Olsa <[email protected]>
Adding test for unknown process tracepoint kill.

Signed-off-by: Jiri Olsa <[email protected]>
Copy link
Contributor

@kkourt kkourt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks

@olsajiri olsajiri merged commit 48c5066 into main Feb 25, 2025
51 of 52 checks passed
@olsajiri olsajiri deleted the pr/olsajiri/harden branch February 25, 2025 09:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
release-note/minor This PR introduces a minor user-visible change
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants