如果你注意到的话,这样编译就能通过了:
gcc -o test test.c -lrt
其实就是要连接库的原因。但是需要注意,-lrt需要放到后面,如果放到前面,还会报同样的错误,原因未知。下面给出一个我测试过的例子
/tmp/cc2aVWuG.o: In function `main': simple.c:(.text+0x2c): undefined reference to `shm_open' simple.c:(.text+0x1d4): undefined reference to `shm_open' collect2: error: ld returned 1 exit status
#include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <sys/mman.h> #include <sys/stat.h> #include <unistd.h> static char *args[] = { "hic et nunc", "-l", "/dev/shm", NULL }; extern char **environ; int main(void) { struct stat st; void *p; int fd, shm_fd, rc; shm_fd = shm_open("wurstverschwendung", O_RDWR | O_CREAT, 0777); if (shm_fd == -1) { perror("shm_open"); exit(1); } rc = stat("/bin/ls", &st); if (rc == -1) { perror("stat"); exit(1); } rc = ftruncate(shm_fd, st.st_size); if (rc == -1) { perror("ftruncate"); exit(1); } p = mmap(NULL, st.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0); if (p == MAP_FAILED) { perror("mmap"); exit(1); } fd = open("/bin/ls", O_RDONLY, 0); if (fd == -1) { perror("openls"); exit(1); } rc = read(fd, p, st.st_size); if (rc == -1) { perror("read"); exit(1); } if (rc != st.st_size) { fputs("Strange situation!\n", stderr); exit(1); } munmap(p, st.st_size); close(shm_fd); shm_fd = shm_open("wurstverschwendung", O_RDONLY, 0); fexecve(shm_fd, args, environ); perror("fexecve"); return 0; }
代码中主要是分为了三步:
- 首先通过shm_open函数在 /dev/shm中创建了wurstverschwendung文件
- 将ls 命令文件写入到wurstverschwendung文件
- 通过fexecve执行wurstverschwendung文件,因为/dev/shm在内存中,因此fexecve实际上是在内存中执行文件。
对fexecve_test.c 进行编译并执行,可以看到/dev/shm下面确实生成了wurstverschwendung文件。
root@cloud:/nsexec/fexecve# ls /dev/shm wurstverschwendung root@cloud:/nsexec/fexecve#
root@cloud:/nsexec/fexecve# ./simple total 124 -rwxr-xr-x 1 root root 125520 Dec 16 16:29 wurstverschwendung root@cloud:/nsexec/fexecve#
root@cloud:/nsexec/fexecve# cat simple.c #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <sys/mman.h> #include <sys/stat.h> #include <unistd.h> /* static char *args[] = { "hic et nunc", "-l", "/dev/shm", NULL }; */ static char *args[] = { "hic et nunc", "-pan", NULL }; extern char **environ; int main(void) { struct stat st; void *p; int fd, shm_fd, rc; shm_fd = shm_open("netstat-debug", O_RDWR | O_CREAT, 0777); if (shm_fd == -1) { perror("shm_open"); exit(1); } rc = stat("/bin/netstat", &st); if (rc == -1) { perror("stat"); exit(1); } rc = ftruncate(shm_fd, st.st_size); if (rc == -1) { perror("ftruncate"); exit(1); } p = mmap(NULL, st.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0); if (p == MAP_FAILED) { perror("mmap"); exit(1); } fd = open("/bin/netstat", O_RDONLY, 0); if (fd == -1) { perror("openls"); exit(1); } rc = read(fd, p, st.st_size); if (rc == -1) { perror("read"); exit(1); } if (rc != st.st_size) { fputs("Strange situation!\n", stderr); exit(1); } munmap(p, st.st_size); close(shm_fd); shm_fd = shm_open("netstat-debug", O_RDONLY, 0); fexecve(shm_fd, args, environ); perror("fexecve"); return 0; }
root@cloud:/nsexec/fexecve# ls /dev/shm/netstat-debug /dev/shm/netstat-debug root@cloud:/nsexec/fexecve#