How does ptrace work with 2 different processes? - linux

I was reading about ptrace on the net and found that a process can request to trace another process by using PTRACE_ATTACH but apparently all the examples available involve the use of fork().
What I want is to have 2 programs - prg1.c and prg2.c where prg2.c should trace prg1.c. I tried using PTRACE_ATTACH in prg2.c but it seems that the call failed - prg2.c couldn't trace prg1.c . How does ptrace work ? Can anybody explain ?
Code for prg1.c :
#include <stdio.h>
#include <sys/ptrace.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
printf("Hello world\n");
sleep(20);
execl("/bin/ls", "ls", NULL);
return 0;
}
Code for prg2.c :
#include <stdio.h>
#include <sys/ptrace.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc , char **argv)
{
int pid = atoi(argv[1]);
int status;
if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) == -1) {
printf("ptrace attach failed!");
return 0;
}
wait(&status);
sleep(5);
ptrace(PTRACE_DETACH, pid, NULL, NULL);
return 0;
}
I have included a sleep() to get the pid of prg1's executable(during that time) using ps -af and give it as an input to the executable of prg2.

Related

Inter process communication using FIFO

Client server must pass to the Server process a filename and the Server process must return the number of lines in the file. My problem is that the received variable only contains 6 characters of the filename and it ends up by throwing segmentation fault dump core error. Do you know why this happens? This is my code:
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
int main(){
int fd1,fd2;
const char *fifo1="./fifo1Channel";
const char *fifo2="./fifo2Channel";
mkfifo(fifo1,0666);
mkfifo(fifo2,0666);
char filename[30];
printf("Give me a filename:\n");
fgets(filename,30,stdin);
strtok(filename,"\n");
int pid=fork();
if(pid>0){
char received[30], ch;
FILE *fp;
fd1=open(fifo1, O_RDONLY);
read(fd1,received,strlen(received));
close(fd1);
printf("From server process:%s\n",received);
fp=fopen(received,"r");
int nrOfLines=0;
for(ch=getc(fp);ch!=EOF;ch=getc(fp))
if(ch=='\n')
nrOfLines++;
fd2=open(fifo2, O_WRONLY);
write(fd2,&nrOfLines,sizeof(nrOfLines));
close(fd2);
return 0;
}
if(pid==0){
int receivedNumber;
fd1=open(fifo1,O_WRONLY);
write(fd1,filename,strlen(filename));
close(fd1);
fd2=open(fifo2,O_RDONLY);
read(fd2,&receivedNumber,sizeof(receivedNumber));
close(fd2);
printf("From client process: %d\n",receivedNumber);
return 0;
}
return 0;
}
I think the problem was in server process. I replaced strlen(received) with 30, the maximum number of characters of filename, in function read and it works now!

setsockopt IPT_SO_SET_REPLACE flag return error (linux)

I try to use setsockopt with the flag IPT_SO_SET_REPLACE but i keep getting the wired error from errno Protocol not available this is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sched.h>
#include <linux/sched.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#include <unistd.h>
#include <sys/ptrace.h>
#include <netinet/in.h>
#include <net/if.h>
#include <linux/netfilter_ipv4/ip_tables.h>
#include <fcntl.h>
int main(void) {
int sock;
int ret;
void *data;
size_t size;
struct ipt_replace *repl;
sock = socket(PF_INET, SOCK_RAW, IPPROTO_RAW);
if (sock == -1) {
perror("socket");
return -1;
}
size = sizeof(struct ipt_replace);
data = malloc(size); Protocol not available
if (data == NULL) {
perror("malloc");
return -1;
}
memset(data, 0, size);
repl = (struct ipt_replace *) data;
repl->num_counters = 0x1;
repl->size = 0xffffffff;
repl->valid_hooks = 0x1;
repl->num_entries = 0x1;
ret = setsockopt(sock, SOL_IP, IPT_SO_SET_REPLACE, (void *) data, size);
printf("\ndone %d\n", ret);
perror("error: ");
return 0;
}
this is the output :
sock:3
data:
size:92
done -1
error: : Protocol not available
Looking briefly at the kernel code, this would seem to indicate that the IP tables module isn't available (i.e. the kernel wasn't built with it configured, or it can't be found or loaded).
It appears to me that for a socket of the kind you created, the code flow is:
enter raw_setsockopt: level != SOL_RAW so...
call ip_setsockopt: level == SOL_IP but option isn't any of the IP_xxx options so...
call nf_setsockopt: Search loaded netfilter modules for one that has registered IPT_SO_SET_REPLACE.
I think the last must have failed, so you get ENOPROTOOPT back (== Protocol not available)

Why the program didn't execute some sentences in this C programming or unix programming(execvp() System calls)?

I have the following program, when I run the program, I feel really confused that why my program didn't excute
int num=i;
printf("it is No.%d !",num);
printf("hello , I will excute execvp!");
My program basically create 6 child processes to excute executionbode() function, and then use execvp to overload original program. However, everytime when I run the program, the string "hello, I will execute execvp" never shows up! Also I think those three sentences above also didn't execute in the running program? can someone tell me why? Here is my program
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include "makeargv.h"
#include "redirection.h"
#include <sys/wait.h>
int executionnode(int i);
int main(){
pid_t childpid;
int i;
int row=6;
for(i=0;i<row;i++)
{ childpid=fork();
if(childpid==0)
continue;
else if (childpid>0)
executionnode(i);
else {
perror("something wrong");
exit(1);
}
}
}
int executionnode(int i){
sleep(i);
printf("hello, I am process:%ld\n",(long)getpid());
wait(NULL);
char *execArgs[] = { "echo", "Hello, World!", NULL };
int num=i;
printf("it is No.%d !",num);
printf("hello , I will excute execvp!");
execvp("echo", execArgs);
}
Can someone tell me why? and how to fix it? I feel it is really strange? Is it because of execvp() functions? I just began to learn operating system,so I am really confused about it! Thank you for helping me!
As user3629249 said you have some confusion. You'll get many children of children of children... and that wait(NULL) is useless :).
I used this structure to got your goal in my OS subject excercises.
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#define N 5
int main(int argc, char const *argv[])
{
pid_t pid,pids[N];
int i, num_pids = 0;
int state = 0;
int prior[]={1,3,5,2,4};
pid_t parent_pid = getpid();
printf("Parent pid is %i\n",father_pid);
// This for loop is the key
for (i = 0; i < N && getppid() != parent_pid; i++)
{
if ((pid = fork()) < 0)
{
printf ("fork error\n");
exit(-1);
}
pids[num_pids++] = pid;
}
if (pid == 0) // Child processes
{
printf("I am the child %i\n",getpid());
}
else // Parent process
{
for (i = 0; i < N; i++)
{
int pid_index = prior[i]-1; // Array starts with 0
pid = waitpid(pids[pid_index]);
printf("Children %i ended\n",pids[indice_pid]);
printf("%i alive children\n",N-1-i);
}
}
return 0;
}
This structure works because you save the parent's pid in parent_pid variable and compare the parent of each process pid with getppid(). If this pid is different that parent_pid, this proccess is the parent. In another case the process is a child so it has to stop (these processes don't have to fork). With this way you can get only the forks you need.
The rest of the code is the same: Pid==0 is child process and any other is the parent. You can call executionnode(int i) in child processes block (remember, pid==0 !!! you have a mistake). i variable should have the right value in each call I think.
Good luck!

Linux: unable to retrieve process name from pid via ioctl

I'm trying to retrieve retrieve process name from pid via ioctl, this is the C code:
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/signal.h>
#include <sys/syscall.h>
#include <sys/procfs.h>
#include <stdio.h>
#include <signal.h>
#include <elf.h>
#include <stdlib.h>
#include <errno.h>
int main(int argc, char **argv) {
char ProcID[50]="/proc/";
int fd;
prpsinfo_t ProcessInfo;
int ioctlResult;
if ( argc != 2 ) {
printf("usage: %s <pid>\n", argv[0]);
return 0;
}
strcat(ProcID,argv[1]);
fd = open(ProcID, O_RDONLY, 0);
if (fd == -1) {
printf("open error: [%d] [%s]\n",errno, strerror(errno));
return 0;
}
ioctlResult = ioctl(fd, NT_PRPSINFO, &ProcessInfo);
if (ioctlResult == -1)
{
printf("Error ioctl: [%d] [%s]\n",errno, strerror(errno));
} else {
printf("Process name: %s\n",ProcessInfo.pr_fname);
}
close(fd);
return 0;
}
When I try to execute it I obtain errno 25 (Inappropriate ioctl for device). I think the file descriptor open on "/proc/" isn't correct; is there another path to consider ?

UDP Server giving Segmentation Fault

Ive written the following echo server using UDP but i have no idea that why it is giving me Segmentation Fault in sendto function, it receives fine but has problem sending data back to client. Ive been trying to find the problem for a few hours now but got no where. Can somebody please point out the fault or what i may be doing wrong.
Thanks
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define true 1
#define false 0
int main(int argc,char **args)
{
int BUF_LENGTH=101;
int port_no=1800;
struct sockaddr_in serv_addr,rmt_addr;
//rmt_addr=malloc(sizeof(struct sockaddr_in));
char *buffer=malloc(BUF_LENGTH);
int byte_recv=0;
int rmt_length=0;
int sock_id;
sock_id=socket(AF_INET,SOCK_DGRAM,0);
if(sock_id<0)
{
printf("Error creating socket : %d",sock_id);
return -1;
}
serv_addr.sin_family=AF_INET;
serv_addr.sin_port=htons(port_no);
serv_addr.sin_addr.s_addr=inet_addr("127.0.0.1");
bind(sock_id,(struct sockaddr*)&serv_addr,sizeof(serv_addr));
printf("Created\n");
while(true)
{
printf("Waiting\n");
byte_recv=recvfrom(sock_id,buffer,BUF_LENGTH,0,(struct sockaddr*)&rmt_addr,&rmt_length);
printf("%s\n",buffer);
if(byte_recv<0)
{
printf("Error receiving: %d",byte_recv);
error("recvfrom");
return -2;
}
printf("%d:%d %s\n",rmt_length,rmt_addr.sin_port,inet_ntoa(rmt_addr.sin_addr));
byte_recv=sendto(sock_id,buffer,BUF_LENGTH,0,(struct sockaddr*)&rmt_addr,rmt_length); //The segmentation fault comes here
printf("Bytes sent: %d \n",byte_recv);
if(byte_recv<0)
error("sendto");
}
free(buffer);
return 0;
}
These lines:
error("recvfrom");
error("sendto");
don't do what you think they do. You probably meant to say perror.
Additionally, you aren't initializing rmt_length correctly. Try this:
int rmt_length=sizeof(rmt_addr);
Finally, you are echoing more bytes back than the server receives. Try this:
byte_recv=sendto(sock_id,buffer,byte_recv,0,(struct sockaddr*)&rmt_addr,rmt_length);

Resources