How to Check If a Process Is Still Running from the Kernel in C

Kernel: Right way to check if process is running in c

You can use pid_task() or get_pid_task() to get a pointer to the struct task_struct of the process. If the call returns NULL then the process does not exist.

Note that you may need to be careful as the pid might have been recycled and is now used by a different process.

How can I check if a process is still running from the kernel in c?

Does this help:

struct task_struct { 
volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */
...
}

Is there a way to check whether a given pid matches any process in kernel space?

Checking the return value of find_task_by_vpid() should be enough to ensure the pid is valid. If it wasn't, it wouldn't have had an associated task_struct in the first place. If you need a confirmation, this is exactly how the getsid syscall handles the PID passed from userspace:

// ...
retval = -ESRCH;
p = find_task_by_vpid(pid);
if (!p)
goto out;
// ...
out:
rcu_read_unlock();
return retval;
}

There's a different problem in your code though: as far as I can tell, you aren't handling the task_struct properly. You should use find_get_task_by_vpid() instead of find_task_by_vpid(). This function will call get_task_struct() for you, incrementing the task_struct refcount to avoid race conditions (since as it seems from your code, your syscall can sleep). After that, you can use put_task_struct() to decrement the refcount.

Something like this:

SYSCALL_DEFINE2(set_wrr_weight, pid_t, pid, int, weight) {
struct sched_wrr_entity *wrr_se;
struct task_struct *tsk;

tsk = find_get_task_by_vpid(pid);
if (!tsk)
return -ESRCH;

wrr_se = &tsk->wrr;
wrr_se->wrr_weight = weight;

put_task_struct(tsk);
return 0;
}

By the way, I don't know if you are doing wrr_se = &tsk->wrr; because you need it somewhere else in the code, but if you don't, then you should be able to set the weight directly doing tsk->wrr.weight = weight;.

Check if process exists given its pid

Issue a kill(2) system call with 0 as the signal. If the call succeeds, it means that a process with this pid exists.

If the call fails and errno is set to ESRCH, a process with such a pid does not exist.

Quoting the POSIX standard:

If sig is 0 (the null signal), error checking is performed but no
signal is actually sent. The null signal can be used to check the
validity of pid.

Note that you are not safe from race conditions: it is possible that the target process has exited and another process with the same pid has been started in the meantime. Or the process may exit very quickly after you check it, and you could do a decision based on outdated information.

Only if the given pid is of a child process (fork'ed from the current one), you can use waitpid(2) with the WNOHANG option, or try to catch SIGCHLD signals. These are safe from race conditions, but are only relevant to child processes.

Detect whether a process is being debugged; in kernel land

exist (from xp) undocumented api

extern "C"
NTKERNELAPI
BOOLEAN
PsIsProcessBeingDebugged(PEPROCESS Process);

which return Process->DebugPort != NULL very simply and reliable api, can be used at any irql (because Process object in not paged memory).

  • Library: NtosKrnl.lib
  • IRQL: Any level

determine if a process is dead or not - by PID

A call to GetExitCodeProcess should return STILL_ACTIVE for active processes. After a call to TerminateProcess, the process will be dead, and a different value will be returned.

Another way to check if a process is alive is WaitForSingleObject. If you call this on the process handle with a timeout of 0, it will immediately return WAIT_TIMEOUT if the process is still running.



Related Topics



Leave a reply



Submit