aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRick Macklem <rmacklem@FreeBSD.org>2021-02-28 22:15:32 +0000
committerRick Macklem <rmacklem@FreeBSD.org>2021-02-28 22:15:32 +0000
commit3e04ab36ba5ce5cbbf6d22f17a01a391a04e465f (patch)
tree43f8a79eba82925062d368c4939cdf51f63b7865
parentb12a960e4274926171dc7a4f9887a0d0a5195b44 (diff)
downloadsrc-3e04ab36ba5ce5cbbf6d22f17a01a391a04e465f.tar.gz
src-3e04ab36ba5ce5cbbf6d22f17a01a391a04e465f.zip
nfsclient: add checks for a server returning the current directory
Commit 3fe2c68ba20f dealt with a panic in cache_enter_time() where the vnode referred to the directory argument. It would also be possible to get these panics if a broken NFS server were to return the directory as an new object being created within the directory or in a Lookup reply. This patch adds checks to avoid the panics and logs messages to indicate that the server is broken for the file object creation cases. Reviewd by: kib MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D28987
-rw-r--r--sys/fs/nfsclient/nfs_clvnops.c38
1 files changed, 29 insertions, 9 deletions
diff --git a/sys/fs/nfsclient/nfs_clvnops.c b/sys/fs/nfsclient/nfs_clvnops.c
index 80317cfd7a50..fc5445ef1e76 100644
--- a/sys/fs/nfsclient/nfs_clvnops.c
+++ b/sys/fs/nfsclient/nfs_clvnops.c
@@ -1423,7 +1423,7 @@ nfs_lookup(struct vop_lookup_args *ap)
}
if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
cnp->cn_flags |= SAVENAME;
- if ((cnp->cn_flags & MAKEENTRY) &&
+ if ((cnp->cn_flags & MAKEENTRY) && dvp != newvp &&
(cnp->cn_nameiop != DELETE || !(flags & ISLASTCN)) &&
attrflag != 0 && (newvp->v_type != VDIR || dattrflag != 0))
cache_enter_time(dvp, newvp, cnp, &nfsva.na_ctime,
@@ -1752,9 +1752,14 @@ again:
}
}
if (!error) {
- if ((cnp->cn_flags & MAKEENTRY) && attrflag)
- cache_enter_time(dvp, newvp, cnp, &nfsva.na_ctime,
- NULL);
+ if ((cnp->cn_flags & MAKEENTRY) && attrflag) {
+ if (dvp != newvp)
+ cache_enter_time(dvp, newvp, cnp,
+ &nfsva.na_ctime, NULL);
+ else
+ printf("nfs_create: bogus NFS server returned "
+ "the directory as the new file object\n");
+ }
*ap->a_vpp = newvp;
} else if (NFS_ISV4(dvp)) {
error = nfscl_maperr(cnp->cn_thread, error, vap->va_uid,
@@ -2126,7 +2131,11 @@ nfs_link(struct vop_link_args *ap)
*/
if (VFSTONFS(vp->v_mount)->nm_negnametimeo != 0 &&
(cnp->cn_flags & MAKEENTRY) && attrflag != 0 && error == 0) {
- cache_enter_time(tdvp, vp, cnp, &nfsva.na_ctime, NULL);
+ if (tdvp != vp)
+ cache_enter_time(tdvp, vp, cnp, &nfsva.na_ctime, NULL);
+ else
+ printf("nfs_link: bogus NFS server returned "
+ "the directory as the new link\n");
}
if (error && NFS_ISV4(vp))
error = nfscl_maperr(cnp->cn_thread, error, (uid_t)0,
@@ -2205,7 +2214,12 @@ nfs_symlink(struct vop_symlink_args *ap)
*/
if (VFSTONFS(dvp->v_mount)->nm_negnametimeo != 0 &&
(cnp->cn_flags & MAKEENTRY) && attrflag != 0 && error == 0) {
- cache_enter_time(dvp, newvp, cnp, &nfsva.na_ctime, NULL);
+ if (dvp != newvp)
+ cache_enter_time(dvp, newvp, cnp, &nfsva.na_ctime,
+ NULL);
+ else
+ printf("nfs_symlink: bogus NFS server returned "
+ "the directory as the new file object\n");
}
return (error);
}
@@ -2278,9 +2292,15 @@ nfs_mkdir(struct vop_mkdir_args *ap)
*/
if (VFSTONFS(dvp->v_mount)->nm_negnametimeo != 0 &&
(cnp->cn_flags & MAKEENTRY) &&
- attrflag != 0 && dattrflag != 0)
- cache_enter_time(dvp, newvp, cnp, &nfsva.na_ctime,
- &dnfsva.na_ctime);
+ attrflag != 0 && dattrflag != 0) {
+ if (dvp != newvp)
+ cache_enter_time(dvp, newvp, cnp,
+ &nfsva.na_ctime, &dnfsva.na_ctime);
+ else
+ printf("nfs_mkdir: bogus NFS server returned "
+ "the directory that the directory was "
+ "created in as the new file object\n");
+ }
*ap->a_vpp = newvp;
}
return (error);