• chroot


    http://www.ibm.com/developerworks/cn/linux/l-cn-chroot/

    理解 chroot

    通过编写 chroot 来认识 chroot 发挥的作用和它带来的好处

    王 华东 (wstoneh@126.com), 自由职业者

    简介: chroot 在 Linux 系统中发挥了根目录的切换工作,同时带来了系统的安全性等好处。本文通过编写 chroot 来理解 chroot 的作用和好处,这不仅有助于更好的使用 chroot,同时加深了对 Linix 系统初始 RAM 磁盘工作的认识。

    发布日期: 2009 年 7 月 09 日 
    级别: 初级 
    访问情况 : 31588 次浏览 
    评论:  (查看 | 添加评论 - 登录)

    平均分 5 星 共 61 个评分 平均分 (61个评分)
    为本文评分

    什么是 chroot

    chroot,即 change root directory (更改 root 目录)。在 linux 系统中,系统默认的目录结构都是以 `/`,即是以根 (root) 开始的。而在使用 chroot 之后,系统的目录结构将以指定的位置作为 `/` 位置。


    图 1. Linux 系统的目录结构
    Linux 系统的目录结构 
     

    为何使用 chroot

    在经过 chroot 之后,系统读取到的目录和文件将不在是旧系统根下的而是新根下(即被指定的新的位置)的目录结构和文件,因此它带来的好处大致有以下3个:

    1. 增加了系统的安全性,限制了用户的权力;

      在经过 chroot 之后,在新根下将访问不到旧系统的根目录结构和文件,这样就增强了系统的安全性。这个一般是在登录 (login) 前使用 chroot,以此达到用户不能访问一些特定的文件。

    2. 建立一个与原系统隔离的系统目录结构,方便用户的开发;

      使用 chroot 后,系统读取的是新根下的目录和文件,这是一个与原系统根下文件不相关的目录结构。在这个新的环境中,可以用来测试软件的静态编译以及一些与系统不相关的独立开发。

    3. 切换系统的根目录位置,引导 Linux 系统启动以及急救系统等。

      chroot 的作用就是切换系统的根位置,而这个作用最为明显的是在系统初始引导磁盘的处理过程中使用,从初始 RAM 磁盘 (initrd) 切换系统的根位置并执行真正的 init。另外,当系统出现一些问题时,我们也可以使用 chroot 来切换到一个临时的系统。

     

    chroot 的使用

    为了更好的理解 chroot 发挥的作用,我们将尝试指定一个特定的位置进行根目录切换。但是由于在经过 chroot 之后,系统读取到的 bin/ 等与系统相关目录将不再是旧系统根目录下的,而是切换后新根下的目录结构和文件,因此我们有必要准备一些目录结构以及必要的文件。

    清单 1. 准备切换的目录结构

    busybox

    Busybox 被称为是嵌入式 Linux 中的瑞士军刀。Busybox 包含了许多有用的命令,如 cat、find 等,但是它的体积却非常的小。


    $ pwd
    /home/wstone/Build/work
    $ tree .
    .
    |-- bin
    | |-- ash -> busybox
    | |-- bash
    | `-- busybox
    |-- etc
    `-- newhome

    这里使用了静态编译后的 busybox 来提供必要的命令,使用静态编译仅是为了避免动态库文件的拷贝。当然我们也可以拷贝旧系统的下的命令到新的目录结构中使用,但是那些命令通常是动态编译的,这就意味着我们不得不拷贝相关的动态库文件到相应的目录结构中。同时这里的 bash 也非真正的 Bourne Again shell,而是一个执行 ash 的 shell 脚本。在清单 2中,展示了位于旧系统中的 chroot 命令的使用。需要注意的是在使用 chroot 时,要求拥有相关的操作权限。


    清单 2. 位于系统中的 chroot 的使用
    $ pwd
    /home/wstone/Build/work
    
    # chroot .
    # pwd
    /
    
    # ls
    ash: ls: not found
    
    # busybox ls
    bin      etc      newhome
    
    3 directories, 3 files
    
    

    我们可以看到当前路径(/home/wstone/Build/work/),在经过 chroot 后转变成了 `/` 目录,同时从新根下读取了与系统相关的目录结构。使用 ls 命令失败是由于我们创建的测试目录结构中并没有包含命令 ls,但是我们成功的使用了 busybox 中的 ls。以上看到的只是 chroot 的一种使用方式,其实标准的 chroot (Coreutils - GNU core utilities 提供的 chroot)使用方式有2种:


    清单 3. 标准 chroot 的2种使用方式
    [1] chroot NEWROOT [COMMAND...]
    [2] chroot OPTION
    
    

    刚才我们使用的是方式[2]。这将在没有给定环境时,默认执行 `/bin/sh`,但是当给定环境后,将运行 `${SHELL} –i`,即与环境相同的可交互的 shell。我们的目录结构中并没有包含sh,显然清单 2中的 chroot 运行了 `${SHELL} –i`。当然我们也可以在进行切换时指定需要的命令,即使用方式[1]。

    清单 4. chroot 另一种方式的使用


    # chroot . /bin/ash

    清单 4 中,尝试了在经过 chroot 后,执行新目录结构下的 ash shell。不得不说的是,如果新根下的目录结构和文件准备的够充分,那么一个新的简单的 Linux 系统就可以使用了。其实更为常见的是在初始 RAM 磁盘 (initrd)中使用 chroot,以此来执行系统的init清单 5 中,展示的是在 Linux 2.4 内核 initrd 中使用 chroot。


    清单 5. 在 Linux 2.4 内核 initrd 中使用 chroot 的示例
    mount /dev/hda1 /new-root
    cd /new-root
    pivot_root . old-root
    exec chroot . /sbin/init <dev/console >dev/console 2>&1
    umount /old-root
    
    

    由于 Linux 内核的升级,initrd 处理机制和格式发生了变化,在 Linux 2.6 内核 initrd 中不能再使用 pivot_root,因此一般也不再使用 chroot,而是选择使用 busybox 提供的 switch_root 或者 klibc 提供的 run-init 进行根目录的切换。(这并不是说不能在 Linux 2.6内核 initrd 中使用 chroot,选择 switch_root 或 run-init 仅是出于习惯和方便的考虑。)但是实质上,它们仅是将 chroot 的功能进行了封装,以此更加方便简单的切换根目录。


    清单 6. 在 Linux 2.6 内核 initrd 中 chroot 的使用
    [1] find -xdev / -exec rm '{}' ';
    [2] cd /newmount; mount --move . /; chroot .
    
    

    switch_root 和 run-init 完成了类似清单 6中的功能,删除 rootfs 的全部内容以释放空间,以及挂载新的根文件系统并进行切换。在 busybox 和 klibc中也有提供 chroot 命令,只是功能上与 Coreutils (GNU core utilities) 包含的 chroot 有稍许差异。

     

    编写一个 chroot

    上面介绍了 chroot 及其使用,但是编写一个简单的 chroot 并不复杂,下面我们就尝试编写chroot 以此来更好的认识 chroot 的处理过程,先编写一个粗略的 chroot 然后再完善它的功能。chroot 的编写涉及了2个函数,chroot() 以及 chdir(),它们都包含在 unistd.h 头文件中。


    清单 7. 编写 chroot 涉及的2个函数
    #include <unistd.h>
    int chroot(const char *path);
    int chdir(const char *path);
    
    

    chroot() 将切换参数 path 所指位置为根目录 (/),chdir() 用来将当前的工作目录改变成以参数path 所指的目录。以此我们可以编写一个非常粗略的 `chroot`。


    清单 8. 粗略的 `chroot`
    #include <unistd.h>
    
    int main(int argc, char *argv[])
    {
        chroot(".");
        chdir("/");
    
        char *arrays[]={"ash",NULL};
        execvp("ash", arrays);
    
        return 0;
    }
    
    

    这个粗略的 `chroot` 仅能切换当前位置为根目录,同时默认执行 ash shell,不包含任何的错误处理及警告。编写并保存代码为test.c。在清单 9 中,展示了这个粗略 `chroot` 的使用情况,成功的进行了根目录的切换。


    清单 9. 粗略 `chroot` 的使用
    $ gcc -Wall test.c -o test
    
    # ./test
    # ls
    ash: ls: not found
    
    # busybox ls
    bin      etc      newhome  test     test.c
    
    

    下面给出功能将近完整的 chroot ,加上了一些错误处理并新增了可执行指定命令的功能。当在没有给出 chroot 切换后要执行的命令时,默认执行 `/bin/sh`,同时检测环境以确认使用何种 shell。


    清单 10. 功能完整的 chroot
    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    
    int main(int argc, char *argv[])
    {
        if(argc<2){
            printf("Usage: chroot NEWROOT [COMMAND...] 
    ");
            return 1;
        }
    
        printf("newroot = %s
    ", argv[1]);
        if(chroot(argv[1])) {
            perror("chroot");
            return 1;
        }
    
        if(chdir("/")) {
            perror("chdir");
            return 1;
        }
    
        if(argc == 2) {
            argv[0] = getenv("SHELL");
            if(!argv[0])
                argv[0] = (char *)"/bin/sh";
    
            argv[1] = (char *) "-i";
            argv[2] = NULL;
        } else {
            argv += 2;
        }
    
        execvp (argv[0], argv);
        printf("chroot: cannot run command `%s`
    ", *argv);
    
        return 0;
    }
    
    

    保存以上代码为 newchroot.c 文件,编译后运行测试其功能。最后要指出的是,本文中的 `chroot` 并没有使用静态编译。如果有必要(如,在 initrd 中使用 chroot),chroot 应该使用静态编译,若是使用动态编译,那么要拷贝相关的动态库文件到相应目录结构中。


    清单 11. `newchroot` 的测试
    $ gcc -Wall newchroot.c -o newchroot
    
    # ./newchroot . /bin/ash
    newroot = .
    #
    
    
    

     

    结束语

    在 Linux 系统初始引导的过程中,通常都有使用 chroot。但是 chroot 的好处不仅于此,它还增加了系统的安全性等。而通过本文后半部分对 chroot 的认识,我相信读者可以更好的发挥chroot 的作用。


     

    下载

    描述名字大小下载方法
    样例代码 work.tar.bz2 734KB HTTP

    关于下载方法的信息


    参考资料

     
     

    chroot[编辑]

    维基百科,自由的百科全书
     
     

    chroot是在unix系统的一个操作,用于对当前的程序和它的子进程改变真实的磁盘根目录。一个被改变根目录的程序不可以访问和命名在被改变根目录外的文件,那个根目录叫做“chroot监狱(chroot jail,chroot prison)”,chroot这一特殊表达可能指chroot(2)系统调用或chroot(8)前端程序。

    历史[编辑]

    chroot系统调用在1979年开发Version 7 Unix时出现,在1982年3月18日被Bill Joy加入BSD,那是在4.2BSD发布前17个月,被用于测试安装和构建系统。

    应用[编辑]

    一个chroot环境可用于创建并运行一个隔离的虚拟软件系统拷贝。对于以下应用是十分有用的:

    测试和开发 
    在chroot测试环境下,测试那些可能对生产系统带来危害的程序。
    依赖控制 
    可以在chroot环境下,设置一个仅有所希望的软件依赖,用于构建和测试。这样可以避免一些对开发者构造带有不同软件库设置所带来的链接(目标文件的链接)问题。
    兼容性 
    早期遗留软件或使用不同ABI的软件必须在chroot环境下运行,因为它们提供的库有可能和宿主机的库起名称或链接冲突。
    修复 
    当一个系统不能启动时,从代替系统(比如Live CD式安装盘),重新写入那些损坏的软件。
    特权分离 
    一个被允许打开文件实例(如文件、链接、网络连接)的软件被放入chroot中,这是对不必要留下在chroot目录工作文件的简单设计。同时也是一个简单的沙盘,也可以防御安全漏洞。注意!有root特权的程序,chroot是没有防御力的。

    侷限[编辑]

    chroot机制不是为了抵御特权(root)用户的蓄意篡改。在大多数的系统,chroot的情况下并没有正确堆栈并有足够的权限chroot的程序可能会引起第二chroot来逃出。为了减轻这种安全漏洞所带来的风险,使用chroot方案的程序应在使用chroot后尽快放弃root权限,或其他机制如FreeBSD Jails 。请注意,某些系统,如FreeBSD,采取预防措施以防止二次进攻的chroot.[1].

    • 在支持设备节点的文件系统中,一个在chroot中的root用户仍然可以创建设备节点和挂载在chroot根目录的文件系统;尽管,chroot机制不是被打算用来阻止低特权用户级访问系统设备。
    • 在启动时,程序都期望能在某些预设位置找到scratch space,配置文件,设备节点共享库。对于一个成功启动的被chroot的程序,在chroot目录必须最低限度配备的这些文件设置。这使得chroot很困难作为一般的沙箱来使用。
    • 只有root 用户可以执行chroot。这是为了防止用户把一个setuid的程序放入一个特制的chroot监牢(例如一个有着假的/etc/passwd 和 /etc/shadow 文件的chroot监牢) 由于引起提权攻击。
    • 在chroot的机制本身也不是为限制资源的使用而设计,如I/O,带宽,磁盘空间或CPU时间。大多数Unix系统都没有以完全文件系统为导向,以即给可能通过网络和过程控制,通过系统调用接口来提供一个破坏chroot的程序。

    一些Unix系统提供扩展的chroot机制, — 一般称为系统机虚拟化 — 至少解决其中的一些限制。包括:

    在chroot中使用图形界面[编辑]

    在chroot环境中使用图形界面是可能的,一下几个方案:

    • xhost
    • 使用内置像Xnest这样的X服务,或现代一点的 Xephyr(或者在监牢中启动真正的X服务)
    • 通过开启X11转发(X11 forwarding) 的 SSH 连接到chroot中(ssh -X)
    • 当一个X服务启动是设置为不监听tcp端口或没有可用的SSH服务器时,使用openroot
    • 通过一个X11 VNC 服务,链接到在外环境的VNC客户端

    参见[编辑]

    参考[编辑]

    外部链接[编辑]

  • 相关阅读:
    RDIFramework.NET ━ .NET快速信息化系统开发框架 V3.2-模块管理按子系统进行分类管理
    RDIFramework.NET ━ .NET快速信息化系统开发框架 V3.2-新增锁定用户与解除锁定用户的功能
    Vue常用经典开源项目汇总参考-海量
    RDIFramework.NET ━ .NET快速信息化系统开发框架 V3.2->用户管理模块新增“重置用户密码”功能
    RDIFramework.NET ━ .NET快速信息化系统开发框架 V3.2 新增解压缩工具类ZipHelper
    RDIFramework.NET ━ .NET快速信息化系统开发框架 V3.2->新增记录SQL执行过程
    RDIFramework.NET平台代码生成器V3.2版本全新发布(提供下载-免费使用)
    [译]何时使用 Parallel.ForEach,何时使用 PLINQ
    IntelliJ IDEA 12 与 Tomcat7 配置
    git用.gitignore忽略指定文件
  • 原文地址:https://www.cnblogs.com/baiyw/p/3376183.html
Copyright © 2020-2023  润新知