c - 在 fork 进程中调用 Execve 的问题

标签 c pipe fork exec dup2

我正在尝试创建一个非常基本的 telnet 服务器来练习内存损坏攻击。当我尝试发出命令时,在第一次迭代中没有任何反应。第二次迭代我在服务器端打印了多个错误的文件描述符错误。在客户端,一切似乎都很好。我得到了所有必需的提示。这是我的相关代码:

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);
                        }
                    }
                }
            }

如果我在我的客户端中输入 /bin/ls,我会在我的服务器上输出以下内容:

I am child 26748

我第二次这样做时,我将以下内容输出到我的服务器:

Failed to pipe in parent process: Bad file descriptor

0I am child 26749

Failed to pipe in child process: Bad file descriptor

最佳答案

有可能在子进程中关闭管道也会在父进程中关闭它。考虑在 while 循环的开头移动你的 piper(pipe)。为了安全起见,在文件循环结束时关闭管道,不要忘记测试关闭的返回值。

实际上 read 会在输入的末尾放置一个换行符,因此您的命令可能是例如 testprog 但实际上,当使用 read(),它是 testprog\n,因此您必须去掉添加的换行符,否则 execve() 将期望程序名称中包含换行符。

#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);

关于c - 在 fork 进程中调用 Execve 的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55661438/

相关文章:

在 CLion 中找不到 Conio.h

linux - 如果一个 fd 正在关闭而其他函数正在阻塞它怎么办?

c++ - 使用 C++ 中的 gnuplot 绘制几何图形

c - 使用 fork() 运行多个任务

c - fork 进程中 bin/sh -i 的问题,错误 : 'can' t access tty, 作业控制已关闭'

c - fork 并返回两次

c - 使用 "NA"将 R 数组传递给 C 函数

c - c中的静态矩阵乘法到动态矩阵

c - 如何将最高有效位(第 23 位)填充或扩展到第 24 位到第 31 位

javascript - Angular2 - 从变量分配管道