目录

Chdir()与Chroot()

最近在学习容器时,遇到了以下几个系统调用,遂作个记录

  • chdir:更改工作目录
  • chroot:更改root目录

chdir

1#include <unistd.h>
2int chdir(const char *path);

示例

chdir将当前目录改为当前目录下的test目录,而fork出的子程序也继承了这个目录

 1/* chdir.c */
 2
 3#include <stdio.h>
 4#include <unistd.h>
 5#include <sys/types.h>
 6int main(void)
 7{
 8  pid_t pid;
 9  
10  if(chdir("./test") != 0) {
11    printf("chdir error\n");
12  }
13  pid = fork();
14  if(pid == 0) {
15    printf("Child dir: %s\n", get_current_dir_name());
16  }else {
17    printf("Parent dir: %s\n", get_current_dir_name());
18  }
19  return 0;
20}

chroot

每一个进程都有一个根目录,一般是对应文件系统的真实根目录,且每个进程都会继承其父进程的根目录。可以通过chroot()来改变一个进程的根目录。此后,所有绝对路径的解释都将从该目录开始(即假装自己是那个/)。chroot()并不改变当前工作目录。

1#include <unistd.h>
2int chroot(const char *path);

chroot()必须与chdir()一同使用,否则程序将有可能通过使用相对路径来进行“越狱”。为避免“越狱”情况的发生,同时还应该将程序中之前打开的“狱外”文件都关闭,因为使用fchdir()可以通过之前打开的文件描述符而达到越狱的目的。

示例

 1/* chroot.c */
 2
 3#include <stdio.h>
 4#include <unistd.h>
 5
 6int main(void)
 7{
 8    FILE *f;
 9
10    /*
11     *  Or:
12     *  chdir("./jail");
13     *  chroot("./");
14     */
15
16    if(chroot("./jail") != 0) {
17        perror("chroot() error");
18    }
19
20    if(chdir("/") != 0) {
21        perror("chdir() error");
22    }
23    /* do something after chrooting */
24    f = fopen("/in_jail.txt", "r");
25
26    if(f == NULL) {
27        perror("/in_jail.txt error");
28    }else {
29        char buf[100];
30        while(fgets(buf, sizeof(buf), f)) {
31            printf("%s\n", buf);
32        }
33    }
34
35    return 0;
36}

我的目录结构:

1.
2|-- chroot.c
3|-- chroot.o
4|-- out_of_jail.txt
5`-- jail
6    `-- in_jail.txt

再看一个越狱的例子:

 1/* chroot_breaking_out_jial.c */
 2
 3#include <stdio.h>
 4#include <unistd.h>
 5#include <sys/types.h>
 6#include <sys/stat.h>
 7#include <fcntl.h>
 8int main(void)
 9{
10    int f1;
11    FILE *f2;
12    f1 = open("/", O_RDONLY);
13
14    if(chroot("./test") != 0) {
15        perror("chroot() error");
16    }
17
18    if(chdir("/") != 0) {
19        perror("chdir() error");
20    }
21    /* close(f1); */
22    /* Breaking out the jail */
23    fchdir(f1);
24    chroot(".");
25    printf("%s\n", get_current_dir_name());
26    f2 = fopen("/root/WORK/out_of_jail.txt", "r");
27    if(f2 == NULL) {
28        perror("out_of_jail_txt error");
29    }else {
30        char buf[100];
31        while(fgets(buf, sizeof(buf), f2)) {
32            printf("%s\n", buf);
33        }
34    }
35    return 0;
36}