chrootコマンド
[root@localhost north]# cat chroot.c
[root@localhost north]# mkdir lib
[root@localhost north]# cp /lib/* lib/
[root@localhost north]# pwd
#include <stdio.h> #include <unistd.h> #include <sys/syscall.h> void main(int argc, char *argv[]) { int pid, status, ret, fd; char buf[64], exename[64]; if (argc == 1) { printf("----------\n"); ret = syscall(SYS_getcwd, buf, 64); printf("%s cwd is %s\n", argv[0], buf); } else { ret = syscall(SYS_getcwd, buf, 64); printf("%s cwd is %s\n", argv[0], buf); pid = fork(); if (!pid) { printf("%s/a.out try to exec by /a.out\n", argv[1]); chroot(argv[1]); execl("/a.out", "/a.out", NULL); } else { waitpid(pid, &status, 0); } } }
[root@localhost north]# mkdir lib
[root@localhost north]# cp /lib/* lib/
[root@localhost north]# pwd
/home/north[root@localhost north]# ./a.out /home/north
./a.out cwd is /home/north /home/north/a.out try to exec by /a.out ---------- /a.out cwd is /パス検索はcurrent->fs->rootから走査され、chrootはcurrent->fs->root = path(filename)となり、動的ライブラリの実行モジュール等プロセスのパス走査の掛かる実装に影響されます。
SYSCALL_DEFINE1(chroot, const char __user *, filename) { struct path path; int error; error = user_path_dir(filename, &path); if (error) goto out; error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_CHDIR); if (error) goto dput_and_out; error = -EPERM; if (!capable(CAP_SYS_CHROOT)) goto dput_and_out; error = security_path_chroot(&path); if (error) goto dput_and_out; set_fs_root(current->fs, &path); error = 0; dput_and_out: path_put(&path); out: return error; } void set_fs_root(struct fs_struct *fs, struct path *path) { struct path old_root; spin_lock(&fs->lock); write_seqcount_begin(&fs->seq); old_root = fs->root; fs->root = *path; path_get_longterm(path); write_seqcount_end(&fs->seq); spin_unlock(&fs->lock); if (old_root.dentry) path_put_longterm(&old_root); }