From: Thomas Veerman Date: Thu, 26 Jul 2012 12:28:03 +0000 (+0000) Subject: VFS: fix locking bug in clone_opcl X-Git-Tag: v3.2.1~429 X-Git-Url: http://zhaoyanbai.com/repos/%22http:/www.isc.org/icons/zpipe.c?a=commitdiff_plain;h=66dbf73049849f550288e82ffe192728df0b588c;p=minix.git VFS: fix locking bug in clone_opcl When VFS runs out of vnodes after closing a vnode in opcl, common_open will try to unlock a vnode through unlock_filp that has already been unlocked in clone_opcl. By first obtaining and locking a new vnode this situation is prevented; if there are no free vnodes, common_open will unlock a still locked vnode. --- diff --git a/servers/vfs/device.c b/servers/vfs/device.c index 0426d8d31..3e3e507e1 100644 --- a/servers/vfs/device.c +++ b/servers/vfs/device.c @@ -881,35 +881,33 @@ int clone_opcl( if (op == DEV_OPEN && dev_mess.REP_STATUS >= 0) { if (dev_mess.REP_STATUS != minor_dev) { - struct vnode *vp; - struct node_details res; + struct vnode *vp; + struct node_details res; /* A new minor device number has been returned. - * Request PFS to create a temporary device file to hold it. - */ + * Request PFS to create a temporary device file to hold it. + */ - /* Device number of the new device. */ + /* Device number of the new device. */ dev = (dev & ~(BYTE << MINOR)) | (dev_mess.REP_STATUS << MINOR); - /* Issue request */ + /* Issue request */ r = req_newnode(PFS_PROC_NR, fp->fp_effuid, fp->fp_effgid, - ALL_MODES | I_CHAR_SPECIAL, dev, &res); - if (r != OK) { + ALL_MODES | I_CHAR_SPECIAL, dev, &res); + if (r != OK) { (void) clone_opcl(DEV_CLOSE, dev, proc_e, 0); return r; - } - - /* Drop old node and use the new values */ - assert(FD_ISSET(scratch(fp).file.fd_nr, &fp->fp_filp_inuse)); - vp = fp->fp_filp[scratch(fp).file.fd_nr]->filp_vno; + } - unlock_vnode(vp); - put_vnode(vp); + /* Drop old node and use the new values */ if ((vp = get_free_vnode()) == NULL) return(err_code); - lock_vnode(vp, VNODE_OPCL); + assert(FD_ISSET(scratch(fp).file.fd_nr, &fp->fp_filp_inuse)); + unlock_vnode(fp->fp_filp[scratch(fp).file.fd_nr]->filp_vno); + put_vnode(fp->fp_filp[scratch(fp).file.fd_nr]->filp_vno); + vp->v_fs_e = res.fs_e; vp->v_vmnt = NULL; vp->v_dev = NO_DEV;