CreateProcess + CREATE_SUSPENDED flag equivalent in Linux? - c

I'm wondering if there's a way to start process suspended?
Similar to CreateProcess + CREATE_SUSPENDED in windows:
CreateProcessA(
NULL,
CmdLine,
NULL,
NULL,
FALSE,
CREATE_SUSPENDED,
NULL,
"C:\\Windows\\System32\\",
&si,
&pi);
ptrace seems to support PTRACE_ATTACH only, there's no way to start a process and suspend it directly, any ideas?
EDIT
I need to be able to catch process like this,
int main()
{
exit(0);
}
So the shell approach will not work, as the process quits really fast.

One possible approach would be to take process details as an input in a process, fork, and in child before exec-ing the process, send stop signal to self.
Sample code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
main()
{
int pid;
//Note: Replace argv_list with corresponding binary and arguments
//Can also get these values as command line argument from main(argc, argv)
char *argv_list[] = {"/usr/bin/ls","-lrt", "/", NULL};
if((pid=fork())==0)
{
printf("Child Executing\n");
//Send STOP signal to self to suspend
kill(getpid(), SIGSTOP);
//Sleep for stop signal handler to suspend current process
sleep(1);
//This line should start to execute only after CONT signal is sent.
execv(argv_list[0],argv_list);
}
else
{
printf("Child PID:%d, Parent continuing\n", pid);
}
printf("\n***Main - Exiting\n");
exit(0);
}

There is no one to one comparison for shell but here is which is similar in terms of spinning a process and then suspending it and then starting it again.
###to start a process:
#!/bin/bash
function_some_proc() {
echo "hi"
# if this is too fast you can always use "sleep" to add some time
}
function_some_proc &
FOO_PID=$!
echo "--"
echo $FOO_PID
echo "--"
###then to suspend
kill -STOP <PID>
#to resume
kill -CONT <PID>

The article Creating suspended processes provides an excellent answer to this question. Note that there are problems with this article. Scott Knight, the author of the article, obviously did not bother to confirm that his code examples will actually compile. The parent function refers to a mysterious pid variable.
A complete working example can be found in my StartSuspended project. My StartSuspended project compiles on Microsoft Windows and GNU/Linux. See StartSuspendedPlatformPosix.cpp for the GNU/Linux implementation.
I used the following functions in the GNU/Linux implementation.
ptrace
execvp
waitpid
fork

Related

Why is sleep in a child process blocking my program?

So I have this simple program that sleeps for 4 second if the value returned by fork is '0' meaning that the child process is executing, I've tried using sleep in child process but the program is blocked, and flushing standard output isn't working...
code:
#include <stdio.h>
#include <unistd.h>
int main(int argc, char const *argv[]) {
pid_t value = fork();
if (value == 0) {
sleep(4);
}
printf("Value returned by fork: %d\n", value);
printf("I'm the process N°%d\n", getpid());
return 0;
}
I'm running on Ubuntu 20.04.3 LTS.
Output:
Value returned by fork: 12618
I'm the process N°12617\
farouk#farouk-HP-Pavilion-Desktop-TP01-1xxx:~/sysexp$ Value returned by fork: 0
I'm the process N°12618
To allow this question to have an accepted answer.
The child process is not blocking the shell. The shell gave its prompt and the child wrote some output after the prompt, leaving the cursor at the start of a line without a shell prompt visible — because the shell prompt already appeared earlier.
There are a variety of ways around this.
The simplest is just to type a command such as ps and hit return, noting that the shell executes it, and that the ps output does not list the child process. If you type the ps command quick enough, you might see the child listed in the output before its output appears.
Another is to modify the program so that it waits for all child processes to exit before it exits — using wait() or waitpid(). The same code can be used in the child and the parent since the child will have no children of its own. The call to the wait function will return immediately with a 'no more children' status (error).
You can find extensive discussion of all this in the comments — I've chosen to make this a Community Wiki answer since there was a lot of activity in the comments that identified the gist of this answer.

Profile a process via its child and kill the child afterwards

I am trying to figure out a way to profile in C a process via its child and after a moment the parent process kills its child to stop profiling. I am using perf to profile my application. perf is going to output its result in a file when killed. It looks like this in a bash script :
./run &
perf stat -o perf.data -p <pid_run> &
kill -9 <pid_perf>
What I have done so far :
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
static pid_t perf_id;
void start() {
char *filename="test_data";
char ppid_str[24];
pid_t pid = fork();
if (pid == 0){
pid_t ppid = getppid();
sprintf(ppid_str, "%d",ppid);
char *args[] = {"/usr/bin/perf", "stat","-p",ppid_str,"-o", filename, NULL};
execvp(args[0], args);
}
else {
perf_id = pid
}
}
void stop() {
kill(perf_id,SIGKILL);
}
I have an issue getting the output of perf.
This is an example of code that could run the parent process :
int main() {
start();
int a = 0;
a+=1;
stop();
// ... // There are other instructions after the stop
return 0;
}
I am not getting any output from perf when running this code. I have to kill the parent process to get an output.
If I put a sleep call before killing the child process, then the program will output an empty file.
EDIT :
stat argument is an example in my command, I want also to use the record argument
As mentioned by Zulan, if I use SIGINT instead of SIGKILL, I will get an output, but I can get one only if the main process sleeps for 1 second.
You should send a SIGINT instead of a SIGKILL in order to allow perf to shutdown cleanly and produce a valid output file. The synchronization between the perf child process and the main process will still be imperfect - so if the main process doesn't take significant time as in your example, it is easily possible that no output file is generated at all. This also affects the accuracy of collected data. With the setup of using perf as a child process rather than vice-versa, you cannot really improve it.
the problem is that perf attaches itself to the process and then waits for process termination to print counters. try adding for example the
-I msec
option to perf like -I 1000 to print counters every 1s.
changing your args to execvp to
char *args[] = {"/usr/bin/perf", "stat", "-p",ppid_str,"-o", filename, "-I", "1000", NULL};
and your inc to a loop of something like
while (a < 10) {
a += 1;
sleep(1);
}
while yield results although the file is not properly closed() in this approach.
I would create a small binary that execs perf with a timeout and gracefully closes the file and run that from the child.

Detect death of parent process from `setuid` process

I write C application that calls fork() to create child processes. The application runs as root. In the parent process, I use wait() for waiting terminated child processes. In child processes, I use prctl() with PR_SET_PDEATHSIG option to detect the death of the parent. It works fine. To reduce the risk of security issues, child processes call setuid() to change UID. The problem is: child processes can not detect the death of the parent one any more.
I have searched around to find the answer and found some useful links, but it does not help:
Detect death of parent process
Enforcing process hierarchies (prctl related) : although this link contains a clear answer, there is no solution.
How to do that correctly?
I just stumbled upon the same issue, the kernel resets the PDEATH signal on credential change:
https://github.com/torvalds/linux/blob/master/kernel/cred.c#L450
This can be verified with the following code and strace -f:
#include <sys/prctl.h>
#include <unistd.h>
#include <signal.h>
int main(int argc, char *argv[])
{
if (fork() == 0) {
// This works as expected
setgid(1000);
setuid(1000);
prctl(PR_SET_PDEATHSIG, SIGTERM);
// This doesn't work since pdeath_signal will be reset
// setgid(1000);
// setuid(1000);
pause();
}
sleep(1);
kill(getpid(), SIGTERM);
return (0);
}

to get pid of command executed by system api call

I'm using system api in linux to achieve shell command operations. Sometimes while executing the command, a system call gets blocked and never returns. So if I know the process id of command which got executed, I will kill that process and call system api again.
eg:
system("ftpget -u<> -p<> ip remote-file local-file");
sometimes ftpget blocks and the system call never returns. So I don't want system call to be blocked indefinitely. Is there any solution other than killing ftpget process?
If not, then how do I get the process id of ftpget?
If you don't have concurrent ftpget instances running then you might forgo obtaining the pid by using a system() to killall, and kill the process by name.
system("killall ftpget");
You should consider using something like execv() however if you really need to kill an isolated instance.
Unfortunately system() provides no mechanism to tell the caller the child processes' pid. You can use fork()/exec() to start the child process directly and keep the pid for your own use.
Note that the thus started process might spawn child processes by itself, that will again have pids you don't know.
Example (untested):
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main() {
pid_t pid = fork();
if (pid == 0) {
// child
execlp("ftpget", "ftpget", "-u<>", "-p<>", "ip",
"remote-file", "local-file", (char*)NULL);
exit(-1); // this will only ever happen when exec fails
}
else if (pid > 0) {
// parent
std::cout << "pid of child process is " << pid << "\n";
waitpid(pid, 0, 0);
}
else {
// error
}
}
For reference:
http://linux.die.net/man/3/system
http://linux.die.net/man/3/fork
http://linux.die.net/man/3/exec
http://linux.die.net/man/3/waitpid
https://github.com/m-labs/uclibc-lm32/blob/master/libc/stdlib/system.c

Monitoring and restarting child process when fails/exits

I've created a rudimentary example of monitoring a child process and restarting it when it fails or exits. What is the preferred/more robust method of doing this? Is it good practice to continuously poll for a change in status? My understanding is that I should utilize something like SIGCHLDbut have been unable to find any good examples.
I'm an embedded C coder mainly and this is my first attempt at trying to understand fork().The purpose of this code will eventually be to monitor a call to another program using exec() and restart this program if and when it fails or finishes.
Edit:
After comments from #cnicutar I have rewritten the example below in a way I think makes more sense in the hope that it is of use to somebody later. I would like the parent to monitor a child process whilst foing other things and make a new call to exec on a new fork when the child process fails/finishes. I want to try and use unix signals to achieve this
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
int main(int argc, char *argv[])
{
pid_t cpid;
int status;
cpid = fork();
for (;;)
{
switch (cpid)
{
case -1 : //Fork failure
exit(EXIT_FAILURE);
break;
case 0 : //Child Process
exec(some function);
return 0; //exit child process
break;
default : //Parent process
if (waitpid(-1, &status, WNOHANG) != 1) cpid = fork(); //restart
//Do parent stuff here...
break;
}
}
}
Adding a SIGCHLD handler won't buy you much since you already wait all the time and only do that - there's nothing else to "interrupt".
One thing I would suggest is a threshold such that the process doesn't die/start too often.
My understanding is that I should utilize something like SIGCHLD but
have been unable to find any good examples
You use SIGCHLD to know when to wait. A typical SIGCHLD handler just does waitpid in a loop until no children are left. In your case you don't need that since your main code is a loop stopped on waitpid.
EDIT
You can find plenty of examples for SIGCHLD handling. One such example is How can I handle sigchld in C. In that code, after the while you can just fork:
while((pid = waitpid(-1, &status, WNOHANG)) > 0)
;
pid = fork();
switch (pid)
...
To reiterate, if you do this SIGCHLD will be called every time a child dies and after you properly wait for it you can just fork another. This only makes sense if the parent has better stuff to do in the meantime than to just block on waitpid.
Word to the wise. There are certain functions that must not be called from a signal handler lest you add difficult bugs to your program. Look up "async signal safe" functions: these and only these can be called from a signal handler. Some of the most common functions (like printf and malloc) cannot be called from a signal handler.

Resources