chrootコマンド
Rev.3を表示中。最新版はこちら。
chrootコマンドでrootを変更する場合、前もってbashおよび掛かるdllを、rootとなるホルダ配下に配置させる必要がありますが、これはchrootそのものの制約ではありません。[root@localhost kitamura]# pwd /home/kitamura [root@localhost kitamura]# chroot /home/ chroot: failed to run command `/bin/bash': No such file or directory [root@localhost kitamura]# ldd /bin/bash linux-gate.so.1 => (0xb77ca000) libtinfo.so.5 => /lib/libtinfo.so.5 (0x48787000) libdl.so.2 => /lib/libdl.so.2 (0x47596000) libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x475f3000) libc.so.6 => /lib/libc.so.6 (0x473e3000) /lib/ld-linux.so.2 (0x473be000)chrootコマンドの処理は、chroot("/home")とし、chdir("/")でcwdを/にで、execve("/bin/bash")としています。従ってルートとなる、/home以下にbashかかるdllが無ければなりません。なければrootが変更されたchrootコマンドプロセスは終了し、元のbashに戻るだけです。
chrootシステムコールは、呼び出しプロセスのrootを更新します。ターミナルからchrootコマンドを起動すると、bashの子プロセスとしてchrootコマンドのプロセスが起動され、そこでchrootすれば、親のbashプロセスのrootでなく、chrootコマンドプロセスのrootを変更します。そのプロセスとbashをexecv()で差し替えることで、rootを/homeとする、子プロセスとしての別bashが起動さ、exitで親のrootが変更されていない親のbashに戻るわけです。
chrootシステムコールは、current->fs->root = path(filename)とするだけで、以降このプロセスの絶対パスでのファイル検索は、current->fs->rootから走査されるということです。
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); }