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

cukinia_kprocess #67

Closed
wants to merge 5 commits into from
Closed

cukinia_kprocess #67

wants to merge 5 commits into from

Conversation

P-D-G
Copy link
Contributor

@P-D-G P-D-G commented Jan 17, 2024

As explained in issue #59, cukinia_process allows checking that a user process is running, however it explicitly doesn't allow testing kernel processes:

        # skip kernel threads
        [ -x $procdir/exe ] || continue

It can be legitimate to verify that some key kernel threads are running, for instance [watchdogd].

This pull-request implements the suggested cukinia_kprocess command.

@P-D-G P-D-G marked this pull request as draft January 17, 2024 13:04
P-D-G added 3 commits January 17, 2024 14:35
The current implementation of cukinia_process skips kernel processes.
However, in some cases it can be useful to check if some kernel
processes are running, e.g. watchdogd.
This commit adds the cukinia_kprocess command to check if such a process
is running. No user check is done.
`pgrep -x` is used instead of `pidof` as some versions of `pidof` do
not check kernel processes and do not have the '-w' option do to so.
The differenciation between user and kernel processes is done by
checking if `/proc/pid/cmdline` is empty or not, as is done by `ps`.

SFL: #9476
Add documentation for the cukinia_kprocess command.

SFL: #9476
Add tests for cukinia_kprocess.
The test verifies that user processes are not detected as kernel
processes.

SFL: #9476
@P-D-G P-D-G force-pushed the pdgleonec/cukinia_kprocess branch from 98a8ad8 to 1c45934 Compare January 17, 2024 13:36
@P-D-G P-D-G marked this pull request as ready for review January 17, 2024 13:38
Copy link
Member

@deribaucourt deribaucourt left a comment

Choose a reason for hiding this comment

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

LGTM

cukinia Outdated
for pid in $(pgrep -x "$pname"); do
# check that it is a kernel threads
# null byte is removed from thread cmdline to avoid bash warning
[ -z "$(tr -d '\0' < /proc/$pid/cmdline)" ] && return 0
Copy link
Contributor

@joufellasfl joufellasfl Mar 4, 2024

Choose a reason for hiding this comment

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

Some userspace processes rewrite their cmdline (by changing their argv[0]) which could result in passing this test. What about testing that readlink proc/$pid/exe is empty, a userspace process will always be started from a non-null executable

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'm not sure which is better. I just tried with readlink and systemd looks has a bit of a weird behavior:

  • its cmdline in /sbin/initsplash and detected as a user process
  • its exe is empty and detected as a kernel thread

ps looks like it detects it as a user process too. Which one is correct ?

Copy link
Contributor

@joufellasfl joufellasfl Mar 19, 2024

Choose a reason for hiding this comment

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

This is not ideal as non-determinstic (sometimes we'll grab false-positive user processes, sometimes not). Maybe a few other deterministic differentiators in /proc/${pid} ? eg. "maps" will be empty for kernel threads, but shall not be for user processes (whether static or dynamic).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

"maps" is only readable by root or in sudo, so would break some tests.
I'll be looking at alternatives and update this PR when I find something deterministic and correct.

Copy link
Member

Choose a reason for hiding this comment

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

procps-ng uses the cmdline attribute to provide brakcets for kernel threads.

    // This routine reads a 'cmdline' for the designated proc_t, "escapes"
    // the result into a single string while guaranteeing the caller a
    // valid proc_t.cmdline pointer.
static int fill_cmdline_cvt (const char *directory, proc_t *restrict p) {
 #define uFLG ( ESC_BRACKETS | ESC_DEFUNCT )
    if (read_unvectored(src_buffer, MAX_BUFSZ, directory, "cmdline", ' '))
        escape_str(dst_buffer, src_buffer, MAX_BUFSZ);
    else
        escape_command(dst_buffer, p, MAX_BUFSZ, uFLG);
    p->cmdline = strdup(dst_buffer[0] ? dst_buffer : "?");
    if (!p->cmdline)
        return 1;
    return 0;
 #undef uFLG
}

Copy link
Member

Choose a reason for hiding this comment

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

The more accurate alternative that seems the easiest to test from cukinia is the presence of a VmSize attribute in the status file. Kernel threads do not have a VMSize obviously. Pushing a commit for that.

cukinia Outdated
local procdir
local pid

_cukinia_prepare "Checking kernel process \"$pname\" ${__not:+NOT }running"
Copy link
Contributor

Choose a reason for hiding this comment

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

I think the term used by Linux is "kernel thread", started by the kthread API.

Copy link
Contributor

Choose a reason for hiding this comment

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

(ditto for the test name)

Copy link
Member

Choose a reason for hiding this comment

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

Converted terminology to kernel thread

@joufellasfl
Copy link
Contributor

joufellasfl commented Apr 5, 2024

Adding relevant thread on SO: https://stackoverflow.com/questions/12213445/identifying-kernel-threads

EDIT: important points:

  • Some apps like tweaking their cmdline, which could end up empty
  • Check the output of readlink(exe) rather than dereferencing. On kernel threads, the link is empty, while user process readlink to a file path (which could be nonexistent and return an error)
  • Kernel threads (pid > 1) have a parent process == 0 in /proc/$pid/stat

This more accurately the official API name in the kernel.
@deribaucourt deribaucourt requested a review from joufellasfl April 8, 2024 13:07
Even though procps-ng uses an empty cmdline as a detection of a kernel
thread, it is not a reliable method because applications can change
their cmdline to empty.

The status file is more reliable. Only user processes will have a VmSize
attribute.
@deribaucourt deribaucourt force-pushed the pdgleonec/cukinia_kprocess branch from 921f140 to 82b9cb2 Compare April 8, 2024 13:26
@deribaucourt
Copy link
Member

@P-D-G I implemented the recommendations. Let me know if you have any remarks on my commits. Cheers!

@P-D-G
Copy link
Contributor Author

P-D-G commented Apr 9, 2024

@P-D-G I implemented the recommendations. Let me know if you have any remarks on my commits. Cheers!

This looks good to me @deribaucourt. Thanks for this, I wouldn't have had time before end of the week :)

@joufellasfl
Copy link
Contributor

Merged, thanks!

@joufellasfl joufellasfl closed this Apr 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants