Ptrace or waitpid gets stuck in C on macOS - c

I'd like to write a mini-debugger with ptrace on OS X.
I want the parent process to make the child process run step by step.
This is what I tried, but the program gets stuck sometimes, it seems to be in an infinite loop or to be frozen.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/user.h>
#include <sys/types.h>
#include <sys/ptrace.h>
int main(void)
{
pid_t id = fork();
if (id < 0)
return 1;
else if (id == 0)
{
ptrace(PT_TRACE_ME, 0, 0, 0);
printf("Point 1\n");
kill(getpid(), SIGSTOP);
printf("Point 2\n");
exit(1);
}
else
{
while (1)
{
int status = 0;
pid_t retpid = waitpid(id, &status, WUNTRACED);
if (retpid < 0)
{
printf("Waitpid error\n");
exit(3);
}
if (WIFSTOPPED(status))
{
int ret = ptrace(PT_STEP, id, (caddr_t)1, 0);
if (ret < 0)
{
printf("Ptrace error\n");
exit(2);
}
}
else
{
printf("Program has terminated\n");
exit(0);
}
}
}
}
Compile with cc bug.c, run with while true; do ./a.out; done, wait 30 seconds and it will freeze.
When it freezes, the last lines are:
Point 1
Point 2
I can't figure out what I'm doing wrong.
Running on macOS Sierra 10.12.6 with Apple LLVM version 8.1.0 (clang-802.0.42)

Related

How to send a signal from the child process to parent process through kill command

I am trying to create a child process through fork() system call, then trying to send a signal to parent and print out something on the screen.
Here is my code:-
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
void func1(int signum) {
if(signum == SIGUSR2) {
printf("Received sig from child\n");
}
}
int main() {
signal(SIGUSR2, func1);
int c = fork();
if(c > 0) {
printf("parent\n");
}
else if(c == -1) {
printf("No child");
}
else {
kill(getppid(), SIGUSR2);
printf("child\n");
}
}
When I execute my program all I get is:-
child
Segmentation fault (core dumped)
I am a novice to C language system calls, and don't get why this is happening, and how to get the desired output, which would be printing of all the three printf statements. Any help for the same would be appreciated.
Your code has a number of minor issues and certainly has undefined behaviour i.e., you can't call printf or other async-signal unsafe functions from a signal handler.
This is the code with fixes (see comments in code). This should work as expected (with no particular order of print statements) and see if still get a segfault with this code.
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
void func1(int signum)
{
/* write is asyc-signal-safe */
write(1, "Received sig from child\n", sizeof "Received sig from child\n" - 1);
}
int main()
{
signal(SIGUSR2, func1);
/* fork returns a pid_t */
pid_t c = fork();
if(c > 0) {
printf("parent\n");
/* Wait for the child to exit; otherwise, you may not receive the signal */
if (wait(NULL) == -1) {
printf("wait(2) failed\n");
exit(1);
}
} else if (c == -1) {
printf("fork(2) error\n");
exit(1);
} else {
if (kill(getppid(), SIGUSR2) == -1) {
/* In case kill fails to send signal... */
printf("kill(2) failed\n");
exit(1);
}
printf("child\n");
}
}

Can't get execvp to execute file

I am trying to write a program that will fork, then open a file and execute it. The file it should execute is called child and it has been compiled. When I type ./child, it runs. However, when I run this program it does not execute the child program and I am prompted with the error message I put in "Execution failed". What I am doing wrong?
This is my parent class
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
int main (int argc, char **argv)
{
pid_t parent = getpid();
pid_t pid = fork();
if (pid == -1)
{
// error, failed to fork()
}
else if (pid > 0)
{
int status;
waitpid(pid, &status, 0);
}
else
{
int var = execvp("./child", NULL);
if(var < 0)
{
printf("Execution failed");
}
}
exit(0); // exec never returns
}
This is the child
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (int argc, char **argv)
{
printf ("Im the child");
exit (0);
}
I actually don't know what you are doing wrong. After a copy and a compilation (and several warning complains) your code runs fine (GCC 7.2).
Obviously, child must be in the same working directory in which you run your main executable (the one that forks).
But probably I would write that code in this way, but I'm not an expert in forking:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <errno.h>
extern int errno;
int main () {
pid_t pid = fork();
if (pid < 0) {
fprintf(stderr, "%s\n", strerror(errno));
return 1;
}
if (pid == 0) {
int ret = execl("./child", "", (char *)NULL);
if(ret < 0) {
fprintf(stderr, "%s\n", strerror(errno));
return 1;
}
} else {
wait(NULL);
}
return 0;
}
At least it tells you which error execl has encountered.

Using ptrace to detect debugger

I am trying to detect on Linux if a debugger is attached to my binary. I have found two solutions. One simpler:
#include <stdio.h>
#include <sys/ptrace.h>
int main()
{
if (ptrace(PTRACE_TRACEME, 0, 1, 0) == -1)
{
printf("don't trace me !!\n");
return 1;
}
// normal execution
return 0;
}
and another one:
#include <sys/types.h>
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
int spc_detect_ptrace(void) {
int status, waitrc;
pid_t child, parent;
parent = getpid();
if (!(child = fork())) {
/* this is the child process */
if (ptrace(PT_ATTACH, parent, 0, 0)) exit(1);
do {
waitrc = waitpid(parent, &status, 0);
} while (waitrc == -1 && errno == EINTR);
ptrace(PT_DETACH, parent, (caddr_t)1, SIGCONT);
exit(0);
}
if (child == -1) return -1;
do {
waitrc = waitpid(child, &status, 0);
} while (waitrc == -1 && errno == EINTR);
return WEXITSTATUS(status);
}
Is the second method better than the first, simpler one? If yes, why?
As well as the ptrace() method, it's also possible to signal SIGTRAP (
How to detect if the current process is being run by GDB? )
I'd say that your first method is better (and better than SIGTRAP), since forking is terribly inefficient for such a check, and there will be many circumstances (like multithreaded code) that forking is undesirable.

pstat_getproc returns an error for pid 1 in hp-ux itanium

I'm trying to run a test program that will display the process of a requested pid. If the pid is not inserted, it's suppose to get the process for pid 1 which is init. Somehow when I run it on hp-ux itanium, it cannot display the process. This only happens on hp-ux itanium for pid 1. For other pid and platform, it works just fine. Here are the code that I think is related:
This is the test file
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "procname.h"
int main(int argc, char **argv)
{
pid_t pid;
char proc[PROCNAME_SZ];
if (argc==2) {
pid = atoi(argv[1]);
if (pid<1) {
printf("Invalid pid\n");
exit(1);
}
} else {
pid = 1;
}
if (get_procname(pid, proc, sizeof(proc))!=0) {
printf("Error retrieving process name: %s\n", strerror(errno));
printf("proc = %s\n",proc);
printf("pid is = %d\n",pid);
exit(1);
}
if (argc==2) {
printf("Process name = %s\n", proc);
} else {
printf("Checking if procname(1) have init...");
if (strstr(proc, "init")) {
printf("OK (%s)\n", proc);
exit(0);
} else {
printf("Failed (%s)\n", proc);
exit(1);
}
}
return 0;
}
This is the .c file
#include <errno.h>
#include "procname.h"
#include "log.h"
#ifdef HPUX
# include <sys/param.h>
# include <sys/pstat.h>
# include <sys/unistd.h>
#endif
int get_procname(pid_t pid, char *buf, size_t n)
{
#ifdef HPUX
struct pst_status pst;
if (pstat_getproc(&pst, sizeof(pst), (size_t)0, pid) != -1) {
memcpy(buf, pst.pst_cmd, n - 1);
buf[n-1] = 0;
} else {
return -1;
}
#endif
return 0;
}
This is the output that I got on hp-ux itanium:
./test_procname 1
Error retrieving process name: Value too large to be stored in data type
proc =
pid is = 1
This is the result that I got on hp-uxmp
./test_procname 1
Process name = init
The pid are just the same, but somehow it cannot recognized the init on hp-ux itanium. The size for printing the string are more than enough to just print init.

Wait for a Forked Process when using a Semaphore

I'm trying to code an exercise in C Linux where I have one semaphore with 2 spots and "n" processes entered by argument. I need that the first 2 processes use the semaphore using the 2 spots for 5 secs each and then leave the semaphore for the other remaining processes to do their stuff. The problem is that not all the other processes wait for the semaphore to be free and some of them show a semaphore error (look at the results at the bottom). I believe the problem is on the waits for the child processes, because I have a waitipid and a wait function, but I need that if there's a free spot in the semaphore, any child process running could use it. Here's the code:
//gcc SemaphoreExample.c -o s
//./s 5
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/sem.h>
void semaphoreTask(int semid, int semnum, int semBusy)
{
struct sembuf data;
data.sem_num = semnum;
data.sem_flg = 0;
data.sem_op = semBusy;
if(semop(semid,&data,1) == -1)
{
printf("\nSemaphore Error\n");
exit(-1);
}
}
int main(int argc, char *argv[])
{
int i, fdSemaphore, quantity, fdsemctl, j;
pid_t pid[15];
system("clear");
if(argc-1 < 1)
{
printf("Some arguments are missing\n");
return EXIT_FAILURE;
}
printf("Number of arguments entered:\n\nargc: %d\n\nValues from the arguments:\n\n",argc-1);
for(i=0;i<argc;i++)
{
printf("argv[%d]: %s\n",i,argv[i]);
}
printf("\n\n");
fdSemaphore = semget(1234,1,IPC_CREAT|0777);
if(fdSemaphore == -1)
{
printf("\nError creating the Semaphore\n");
return EXIT_FAILURE;
}
fdsemctl = semctl(fdSemaphore,0,SETVAL,2);
if(fdsemctl == -1)
{
printf("\nError opening the Semaphore\n");
return EXIT_FAILURE;
}
quantity = atoi(argv[1]);
for(i=0;i<quantity;i++)
{
pid[i] = fork();
if(pid[i] == -1)
{
printf("\nError creating the Child Process\n");
return EXIT_FAILURE;
}
if(pid[i] == 0)
{
semaphoreTask(fdSemaphore,0,-1);
printf("\n[%d] I go to sleep\n",getpid());
sleep(5);
printf("\n[%d] I wake up\n",getpid());
semaphoreTask(fdSemaphore,0,1);
}
else
{
//printf("\nJust wait\n");
waitpid(pid[i],NULL,WNOHANG);
}
}
for(j=0;j<quantity;j++)
{
wait(NULL);
}
semctl(fdSemaphore,0,IPC_RMID);
return EXIT_SUCCESS;
}
This is the result I got:
Result:
Number of arguments entered:
argc: 1
Values from the arguments:
argv[0]: ./s
argv[1]: 5
[2845] I go to sleep
[2844] I go to sleep
[2845] I wake up
[2844] I wake up
Semaphore Error
[2843] I go to sleep
Semaphore Error
Semaphore Error
[2843] I wake up
Semaphore Error
Should I use wait or waitpid only?
The problem is semaphores are getting removed by forked children.
After line
semaphoreTask(fdSemaphore,0,1);
add
exit(0);
It is much simpler to implement what you want if you use sem_post and sem_wait calls. I am on a OpenBSD system and I am assuming that Linux has the same thing.

Resources