4.2 系统对被囚禁程序的限制

  在整个内核中,有一系列对被囚禁程序的约束措施。 通常,这些约束只对被囚禁的程序有效。如果这些程序试图突破这些约束, 相关的函数将出错返回。例如:

if (p->p_prison) 
        return EPERM;

4.2.1 SysV进程间通信(IPC)

  System V进程间通信(IPC)是通过消息实现的。 每个进程都可以向其它进程发送消息,告诉对方该做什么。 处理消息的函数是:msgsys, msgctl, msgget, msgsendmsgrcv。前面我提到一些sysctl项开关可以影响Jail的行为, 其中有一个是jail_sysvipc_allowed。在大多数系统上, 这个sysctl项被设成0。如此它被设为1,它将使Jail完全失去意义: 在Jail中有权限的进程就可以影响Jail环境外的进程了。 消息与信号的区别是:消息仅由一个信号编号组成。

  /usr/src/sys/kern/sysv_msg.c:

  在这些系统调用的代码中,都有这样一个条件判断:

/usr/src/sys/kern/sysv msg.c:
if (!jail.sysvipc.allowed && p->p_prison != NULL)
        return (ENOSYS);

  信号量系统调用使得进程可以通过一系列操作实现同步。 信号量为进程锁定资源提供了又一种途径。 然而,进程将为正在被使用的信号量进入等待状态,一直休眠到资源被释放。 在Jail中如下的信号量系统调用将会失效: semsys, semget, semctlsemop

  /usr/src/sys/kern/sysv_sem.c:

  System V IPC使进程间可以共享内存。进程之间可以通过它们虚拟地址空间 的共享部分以及相关数据读写操作直接通讯。这些系统调用在Jail环境中将会失效: shmdt, shmat, oshmctl, shmctl, shmget, 和shmsys

  /usr/src/sys/kern/sysv shm.c:

4.2.2 套接字

  Jail以一种特殊的方式处理socket(2)系统调用和相关的低级套接字函数。 为了决定一个套接字是否允许被创建,它先检查sysctl项 jail.socket.unixiproute.only是否被设置为1。 如果被设为1,套接字建立时将只能指定这些协议族: PF_LOCAL, PF_INET, PF_ROUTE。否则,socket(2)将会返回出错。

/usr/src/sys/kern/uipc_socket.c:
int socreate(dom, aso, type, proto, p) 
... 
register struct protosw *prp; 
... 
{
        if (p->p_prison && jail_socket_unixiproute_only &&
            prp->pr_domain->dom_family != PR_LOCAL && prp->pr_domain->dom_family != PF_INET 
            && prp->pr_domain->dom_family != PF_ROUTE)
                return (EPROTONOSUPPORT); 
...
}

4.2.3 Berkeley包过滤器

  Berkeley包过滤器提供了一个与协议无关的,直接通向数据链路层的低级接口。 函数bpfopen()打开一个以太网设备。 代码中有一个条件判断禁止所有被囚禁的进程打开Berkeley包过滤器设备。

/usr/src/sys/net/bpf.c: 
static int bpfopen(dev, flags, fmt, p) 
... 
{
        if (p->p_prison) 
                return (EPERM);
...
}

4.2.4 网络协议

  网络协议TCP, UDP, IP和ICMP很常见。IP和ICMP处于同一协议层次:第二层, 网络层。当参数nam被设置时, 有一些限制措施会防止被囚禁的程序绑定到一些网络接口上。 nam是一个指向sockaddr结构体的指针,描述可以绑定服务的地址。 一个更确切的定义:sockaddr“是一个模板,包含了地址的标识符和地址的长度”[2]。 在函数中,pcbbind, sin 里有一个指向sockaddr的指针。结构体包含了套接字可以绑定的端口、地址、 长度、协议族。这就禁止了在Jail中的进程指定协议族。

/usr/src/sys/kern/netinet/in_pcb.c: 
int in.pcbbind(int, nam, p) 
...
        struct sockaddr *nam; 
        struct proc *p; 
{
        ... 
        struct sockaddr.in *sin; 
        ... 
        if (nam) {
                sin = (struct sockaddr.in *)nam; 
                ... 
                if (sin->sin_addr.s_addr != INADDR_ANY) 
                       if (prison.ip(p, 0, &sin->sin.addr.s_addr)) 
                              return (EINVAL); 
                ....
        }
...
}

  你也许想知道函数prison_ip()做什么。 prison.ip有三个参数,当前进程(用p表示), 一些标志(flag)和一个IP地址。当这个IP地址属于一个Jail时,返回1; 否则返回0。正如你从代码中看见的,如果,那个IP地址真的属于一个Jail, 就不再允许向一个网络接口绑定协议。

/usr/src/sys/kern/kern_jail.c:
int prison_ip(struct proc *p, int flag, u_int32_t *ip) {
        u_int32_t tmp;

       if (!p->p_prison) 
              return (0); 
       if (flag) 
              tmp = *ip; 
       else tmp = ntohl (*ip); 

       if (tmp == INADDR_ANY) {
              if (flag) 
                     *ip = p->p_prison->pr_ip; 
              else *ip = htonl(p->p_prison->pr_ip); 
              return (0); 
       }

       if (p->p_prison->pr_ip != tmp) 
              return (1); 
       return (0); 
}

  被囚禁的用户不能对一个不属于这个Jail的IP地址绑定服务。 这个限制在函数in_pcbbind中也有所体现:

/usr/src/sys/net inet/in_pcb.c
        if (nam) {
               ... 
               lport = sin->sin.port; 
               ... if (lport) { 
                          ... 
                         if (p && p->p_prison)
                                prison = 1; 
                         if (prison &&
                             prison_ip(p, 0, &sin->sin_addr.s_addr))
                        return (EADDRNOTAVAIL);

4.2.5 文件系统

  如此完全级大于0,即便是root,也不允许在Jail中设置文件标志, 如“不可修改”、“添加”、“不可删除”标志。

/usr/src/sys/ufs/ufs/ufs_vnops.c:
int ufs.setattr(ap) 
        ... 
{
        if ((cred->cr.uid == 0) && (p->prison == NULL)) {
            if ((ip->i_flags 
                     & (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND)) && 
                     securelevel > 0)
               return (EPERM);
}

本文档和其它文档可从这里下载:ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/.

如果对于FreeBSD有问题,请先阅读文档,如不能解决再联系<[email protected]>.
关于本文档的问题请发信联系 <[email protected]>.