Search code examples
cpipeforkexecdup2

Issues Calling Execve In Forked Process


I'm trying to create a very basic telnet server to practice memory corruption exploits. When I try to issue a command, in the first iteration, nothing happens. Second iteration I am getting multiple bad file descriptor errors printing on my server side. On the client side, everything seems ok. I get all the required prompts. Here's my relevant code:

int piper[2];
pipe(piper);

...

     while (1) {
        n = write(newsockfd,"Enter a command...\n",21);
                if (n < 0) error("ERROR writing to socket");
                bzero(buffer,4096);
                n = read(newsockfd,buffer,4095);
                strcpy(command, buffer);
                pid_t childpid;
                childpid = fork();
                if(childpid == -1) {
                    perror("Failed to fork");
                    return 1;
                }
                if(childpid == 0) { //child
                    printf("I am child %ld\n", (long)getpid());
                    if(dup2(piper[1], 1) < 0) {
                        perror("Failed to pipe in child process");
                    }
                    else {
                        close(piper[0]);
                        close(piper[1]);
                        char *args[] = {command, NULL};
                        execve(command, args, NULL);
                    }
                }
                else { // parent
                    if(dup2(piper[0], 0) < 0) {
                        perror("Failed to pipe in parent process");
                    }
                    else {
                        // read command output from child
                        while(fgets(command_out, sizeof(command_out), stdin)) {
                            printf("%s", command_out);
                        }
                    }
                }
            }

If I enter /bin/ls into my client, I get the following outputted onto my server:

I am child 26748

2nd time I do it, I get the following outputted to my server:

Failed to pipe in parent process: Bad file descriptor

0I am child 26749

Failed to pipe in child process: Bad file descriptor

Solution

  • There's a possibility that closing the pipe in the child process closes it in the parent process also. Consider moving your piper(pipe) in the beginning of the while loop. And to be safe, close the pipe at the end of the file loop not forgetting to test the return value of close.

    Actually read puts a newline character at the end of input so your command could be for example testprog but in reality, when using read(), it is testprog\n so you have to get rid of the newline added or execve() will expect a program name with a newline in it.

    #define STDIN 0
    int n = read(STDIN, command, 4096);
    command[n - 1] = '\0';   // get rid of newline
    
    char *args = { command, NULL };
    execve(buf, &args[0], NULL);