From owner-svn-src-stable@FreeBSD.ORG Tue Feb 14 04:07:36 2012 Return-Path: Delivered-To: svn-src-stable@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 5BD72106564A; Tue, 14 Feb 2012 04:07:36 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 455BE8FC12; Tue, 14 Feb 2012 04:07:36 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q1E47aN1076892; Tue, 14 Feb 2012 04:07:36 GMT (envelope-from rmacklem@svn.freebsd.org) Received: (from rmacklem@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q1E47aEQ076890; Tue, 14 Feb 2012 04:07:36 GMT (envelope-from rmacklem@svn.freebsd.org) Message-Id: <201202140407.q1E47aEQ076890@svn.freebsd.org> From: Rick Macklem Date: Tue, 14 Feb 2012 04:07:36 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org X-SVN-Group: stable-9 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r231633 - stable/9/sys/nlm X-BeenThere: svn-src-stable@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for all the -stable branches of the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 14 Feb 2012 04:07:36 -0000 Author: rmacklem Date: Tue Feb 14 04:07:35 2012 New Revision: 231633 URL: http://svn.freebsd.org/changeset/base/231633 Log: MFC: r230801 jwd@ reported a problem via email to freebsd-fs@ on Aug 25, 2011 under the subject "F_RDLCK lock to FreeBSD NFS fails to R/O target file". This occurred because the server side NLM always checked for VWRITE access, irrespective of the type of lock request. This patch replaces VOP_ACCESS(..VWRITE..) with one appropriate to the lock operation. It allows unlock and lock cancellation to be done without a check of VOP_ACCESS(), so that files can't be left locked indefinitely after the file permissions have been changed. Modified: stable/9/sys/nlm/nlm_prot_impl.c Directory Properties: stable/9/sys/ (props changed) stable/9/sys/amd64/include/xen/ (props changed) stable/9/sys/boot/ (props changed) stable/9/sys/boot/i386/efi/ (props changed) stable/9/sys/boot/ia64/efi/ (props changed) stable/9/sys/boot/ia64/ski/ (props changed) stable/9/sys/boot/powerpc/boot1.chrp/ (props changed) stable/9/sys/boot/powerpc/ofw/ (props changed) stable/9/sys/cddl/contrib/opensolaris/ (props changed) stable/9/sys/conf/ (props changed) stable/9/sys/contrib/dev/acpica/ (props changed) stable/9/sys/contrib/octeon-sdk/ (props changed) stable/9/sys/contrib/pf/ (props changed) stable/9/sys/contrib/x86emu/ (props changed) Modified: stable/9/sys/nlm/nlm_prot_impl.c ============================================================================== --- stable/9/sys/nlm/nlm_prot_impl.c Tue Feb 14 02:03:17 2012 (r231632) +++ stable/9/sys/nlm/nlm_prot_impl.c Tue Feb 14 04:07:35 2012 (r231633) @@ -1774,10 +1774,10 @@ struct vfs_state { static int nlm_get_vfs_state(struct nlm_host *host, struct svc_req *rqstp, - fhandle_t *fhp, struct vfs_state *vs) + fhandle_t *fhp, struct vfs_state *vs, accmode_t accmode) { int error, exflags; - struct ucred *cred = NULL, *credanon; + struct ucred *cred = NULL, *credanon = NULL; memset(vs, 0, sizeof(*vs)); @@ -1787,14 +1787,19 @@ nlm_get_vfs_state(struct nlm_host *host, } vs->vs_vfslocked = VFS_LOCK_GIANT(vs->vs_mp); - error = VFS_CHECKEXP(vs->vs_mp, (struct sockaddr *)&host->nh_addr, - &exflags, &credanon, NULL, NULL); - if (error) - goto out; + /* accmode == 0 means don't check, since it is an unlock. */ + if (accmode != 0) { + error = VFS_CHECKEXP(vs->vs_mp, + (struct sockaddr *)&host->nh_addr, &exflags, &credanon, + NULL, NULL); + if (error) + goto out; - if (exflags & MNT_EXRDONLY || (vs->vs_mp->mnt_flag & MNT_RDONLY)) { - error = EROFS; - goto out; + if (exflags & MNT_EXRDONLY || + (vs->vs_mp->mnt_flag & MNT_RDONLY)) { + error = EROFS; + goto out; + } } error = VFS_FHTOVP(vs->vs_mp, &fhp->fh_fid, LK_EXCLUSIVE, &vs->vs_vp); @@ -1802,22 +1807,31 @@ nlm_get_vfs_state(struct nlm_host *host, goto out; vs->vs_vnlocked = TRUE; - if (!svc_getcred(rqstp, &cred, NULL)) { - error = EINVAL; - goto out; - } - if (cred->cr_uid == 0 || (exflags & MNT_EXPORTANON)) { - crfree(cred); - cred = credanon; - credanon = NULL; - } + if (accmode != 0) { + if (!svc_getcred(rqstp, &cred, NULL)) { + error = EINVAL; + goto out; + } + if (cred->cr_uid == 0 || (exflags & MNT_EXPORTANON)) { + crfree(cred); + cred = credanon; + credanon = NULL; + } - /* - * Check cred. - */ - error = VOP_ACCESS(vs->vs_vp, VWRITE, cred, curthread); - if (error) - goto out; + /* + * Check cred. + */ + error = VOP_ACCESS(vs->vs_vp, accmode, cred, curthread); + /* + * If this failed and accmode != VWRITE, try again with + * VWRITE to maintain backwards compatibility with the + * old code that always used VWRITE. + */ + if (error != 0 && accmode != VWRITE) + error = VOP_ACCESS(vs->vs_vp, VWRITE, cred, curthread); + if (error) + goto out; + } #if __FreeBSD_version < 800011 VOP_UNLOCK(vs->vs_vp, 0, curthread); @@ -1871,6 +1885,7 @@ nlm_do_test(nlm4_testargs *argp, nlm4_te struct nlm_host *host, *bhost; int error, sysid; struct flock fl; + accmode_t accmode; memset(result, 0, sizeof(*result)); memset(&vs, 0, sizeof(vs)); @@ -1896,7 +1911,8 @@ nlm_do_test(nlm4_testargs *argp, nlm4_te goto out; } - error = nlm_get_vfs_state(host, rqstp, &fh, &vs); + accmode = argp->exclusive ? VWRITE : VREAD; + error = nlm_get_vfs_state(host, rqstp, &fh, &vs, accmode); if (error) { result->stat.stat = nlm_convert_error(error); goto out; @@ -1967,6 +1983,7 @@ nlm_do_lock(nlm4_lockargs *argp, nlm4_re struct nlm_host *host; int error, sysid; struct flock fl; + accmode_t accmode; memset(result, 0, sizeof(*result)); memset(&vs, 0, sizeof(vs)); @@ -2001,7 +2018,8 @@ nlm_do_lock(nlm4_lockargs *argp, nlm4_re goto out; } - error = nlm_get_vfs_state(host, rqstp, &fh, &vs); + accmode = argp->exclusive ? VWRITE : VREAD; + error = nlm_get_vfs_state(host, rqstp, &fh, &vs, accmode); if (error) { result->stat.stat = nlm_convert_error(error); goto out; @@ -2180,7 +2198,7 @@ nlm_do_cancel(nlm4_cancargs *argp, nlm4_ goto out; } - error = nlm_get_vfs_state(host, rqstp, &fh, &vs); + error = nlm_get_vfs_state(host, rqstp, &fh, &vs, (accmode_t)0); if (error) { result->stat.stat = nlm_convert_error(error); goto out; @@ -2269,7 +2287,7 @@ nlm_do_unlock(nlm4_unlockargs *argp, nlm goto out; } - error = nlm_get_vfs_state(host, rqstp, &fh, &vs); + error = nlm_get_vfs_state(host, rqstp, &fh, &vs, (accmode_t)0); if (error) { result->stat.stat = nlm_convert_error(error); goto out;