svn commit: r231633 - stable/9/sys/nlm
Rick Macklem
rmacklem at FreeBSD.org
Tue Feb 14 04:07:36 UTC 2012
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;
More information about the svn-src-stable-9
mailing list