FreeBSD fifo_vnops.c资源泄漏本地拒绝服务漏洞

受影响系统:

FreeBSD FreeBSD 8.x
FreeBSD FreeBSD 7.x
FreeBSD FreeBSD 6.x

描述:

FreeBSD就是一种运行在Intel平台上、可以自由使用的开放源码Unix类系统。

FreeBSD的usr/src/sys/fs/fifofs/fifo_vnops.c文件中存在资源泄漏漏洞:

/*
* Open called to set up a new instance of a fifo or
* to find an active instance of a fifo.
*/
/* ARGSUSED */
static int
fifo_open(ap)
        struct vop_open_args /* {
                struct vnode *a_vp;
                int  a_mode;
                struct ucred *a_cred;
                struct thread *a_td;
                struct file *a_fp;
        } */ *ap;
{
        struct vnode *vp = ap->a_vp;
        struct fifoinfo *fip;
        struct thread *td = ap->a_td;
        struct ucred *cred = ap->a_cred;
        struct file *fp = ap->a_fp;
        struct socket *rso, *wso;
        int error;
    …
         if ((fip = vp->v_fifoinfo) == NULL) {
    …
        }
    …
         if (ap->a_mode & FWRITE) {
                 if ((ap->a_mode & O_NONBLOCK) && fip->fi_readers == 0) {
                         mtx_unlock(&fifo_mtx);
                         return (ENXIO);
                 }
                 fip->fi_writers++;
                 if (fip->fi_writers == 1) {
                         SOCKBUF_LOCK(&fip->fi_readsock->so_rcv);
                         fip->fi_readsock->so_rcv.sb_state &= ~SBS_CANTRCVMORE;
                         SOCKBUF_UNLOCK(&fip->fi_readsock->so_rcv);
                         if (fip->fi_readers > 0) {
                                 wakeup(&fip->fi_readers);
                                 sorwakeup(fip->fi_readsock);
                         }
                 }
         }
    …
                 if ((ap->a_mode & FWRITE) && fip->fi_readers == 0) {
                         VOP_UNLOCK(vp, 0);
                         error = msleep(&fip->fi_writers, &fifo_mtx,
                             PDROP | PCATCH | PSOCK, "fifoow", 0);
                         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
                         if (error) {
                                 fip->fi_writers–;
                                 if (fip->fi_writers == 0) {
                                         socantrcvmore(fip->fi_readsock);
                                         mtx_lock(&fifo_mtx);
                                         fip->fi_wgen++;
                                         mtx_unlock(&fifo_mtx);
                                         fifo_cleanup(vp);
                                 }
                                 return (error);
                         }
    …
}

在这段代码中,vp指针用于存储sys/vnode.h中定义的vnode结构。从最后一个if语句可知如果msleep()中出错,就会递减writer的引用计数器;如果已递减至无,就会使用socantrcvmore()锁定fip->fi_readsock套接字描述符,然后启动互斥锁递增fip->fi_wgen计数器,最终对vp指针调用fifo_cleanup()清除FIFO资源:

/*
* Dispose of fifo resources.
*/
static void
fifo_cleanup(struct vnode *vp)
{
        struct fifoinfo *fip = vp->v_fifoinfo;

        ASSERT_VOP_ELOCKED(vp, "fifo_cleanup");
        if (fip->fi_readers == 0 && fip->fi_writers == 0) {
                vp->v_fifoinfo = NULL;
                (void)soclose(fip->fi_readsock);
                (void)soclose(fip->fi_writesock);
                free(fip, M_VNODE);
        }
}

但是在fifo_open()中,如果FIFO为非阻断模式且reader的引用计数器等于0,ap->a_mode & FWRITE的if语句就会解锁FIFO互斥锁并未经释放资源便返回ENXIO,导致资源泄漏。

<*来源:Dorr H. Clark (dclark@engr.scu.edu
*>

测试方法:

以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!

 

http://marc.info/?l=freebsd-hackers&m=125747695726241&w=2

建议:

厂商补丁:

FreeBSD
——-
目前厂商还没有提供补丁或者升级程序,我们建议使用此软件的用户随时关注厂商的主页以获取最新版本:

http://www.freebsd.org/security/index.html

发表评论?

0 条评论。

发表评论