From b235f015f88e3052c52ba872a2e05c8a2844a74b Mon Sep 17 00:00:00 2001 From: Ravi Pokala Date: Wed, 21 Feb 2018 00:19:02 +0000 Subject: [PATCH] mountd: Return proper errno values in a few error paths When attempting to mount a non-directory which exists, return ENOTDIR instead of ENOENT. If stat() or statfs() failed, don't pass part of the invalid (struct statfs) to ex_search(). In that same case, preserve the value of "bad" rather than overwriting with EACCES. Submitted by: Bruce Leverett (Panasas) Reviewed by: rmacklem MFC after: 1 week Sponsored by: Panasas Differential Revision: https://reviews.freebsd.org/D14438 --- usr.sbin/mountd/mountd.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/usr.sbin/mountd/mountd.c b/usr.sbin/mountd/mountd.c index bb802e92faf1..8c43da0a7c05 100644 --- a/usr.sbin/mountd/mountd.c +++ b/usr.sbin/mountd/mountd.c @@ -1053,8 +1053,6 @@ mntsrv(struct svc_req *rqstp, SVCXPRT *transp) */ if (realpath(rpcpath, dirpath) == NULL || stat(dirpath, &stb) < 0 || - (!S_ISDIR(stb.st_mode) && - (dir_only || !S_ISREG(stb.st_mode))) || statfs(dirpath, &fsb) < 0) { chdir("/"); /* Just in case realpath doesn't */ syslog(LOG_NOTICE, @@ -1064,10 +1062,23 @@ mntsrv(struct svc_req *rqstp, SVCXPRT *transp) warnx("stat failed on %s", dirpath); bad = ENOENT; /* We will send error reply later */ } + if (!bad && + !S_ISDIR(stb.st_mode) && + (dir_only || !S_ISREG(stb.st_mode))) { + syslog(LOG_NOTICE, + "mount request from %s for non-directory path %s", + numerichost, dirpath); + if (debug) + warnx("mounting non-directory %s", dirpath); + bad = ENOTDIR; /* We will send error reply later */ + } /* Check in the exports list */ sigprocmask(SIG_BLOCK, &sighup_mask, NULL); - ep = ex_search(&fsb.f_fsid); + if (bad) + ep = NULL; + else + ep = ex_search(&fsb.f_fsid); hostset = defset = 0; if (ep && (chk_host(ep->ex_defdir, saddr, &defset, &hostset, &numsecflavors, &secflavorsp) || @@ -1118,7 +1129,8 @@ mntsrv(struct svc_req *rqstp, SVCXPRT *transp) "mount request succeeded from %s for %s", numerichost, dirpath); } else { - bad = EACCES; + if (!bad) + bad = EACCES; syslog(LOG_NOTICE, "mount request denied from %s for %s", numerichost, dirpath);