On Wed, 22 Feb 2023 17:11:47 +0100, Moritz Buhl wrote:
> The tool finds a path to ex_search where fsb.f_fsid is uninitialized.
>
> ex_search compares the potentially uninitialized stack data:
>
> ex_search(fsid_t *fsid)
> {
> struct exportlist *ep;
>
> ep = exphead;
> while (ep) {
> if (ep->ex_fs.val[0] == fsid->val[0] &&
> ...
>
> Is it sufficient to zero fsb?
> Is this really reachable?
I believe that it is. However, I don't know why we wouldn't just
want to skip ex_search, etc when bad is set. Also, there is no
reason to use a critical section now that the SIGHUP handle just
sets a flag. Something like this (untested), should be fine.
It needs testing by someone who actually uses NFS though...
- todd
Index: sbin/mountd/mountd.c
===================================================================
RCS file: /cvs/src/sbin/mountd/mountd.c,v
retrieving revision 1.89
diff -u -p -u -r1.89 mountd.c
--- sbin/mountd/mountd.c 6 Aug 2020 17:57:32 -0000 1.89
+++ sbin/mountd/mountd.c 22 Feb 2023 17:17:44 -0000
@@ -736,7 +736,6 @@ mntsrv(struct svc_req *rqstp, SVCXPRT *t
char rpcpath[RPCMNT_PATHLEN+1], dirpath[PATH_MAX];
struct hostent *hp = NULL;
struct exportlist *ep;
- sigset_t sighup_mask;
int defset, hostset;
struct fhreturn fhr;
struct dirlist *dp;
@@ -746,8 +745,6 @@ mntsrv(struct svc_req *rqstp, SVCXPRT *t
u_short sport;
long bad = 0;
- sigemptyset(&sighup_mask);
- sigaddset(&sighup_mask, SIGHUP);
saddr = transp->xp_raddr.sin_addr.s_addr;
sport = ntohs(transp->xp_raddr.sin_port);
switch (rqstp->rq_proc) {
@@ -790,9 +787,10 @@ mntsrv(struct svc_req *rqstp, SVCXPRT *t
fprintf(stderr, "stat failed on %s\n", dirpath);
bad = ENOENT; /* We will send error reply later */
}
+ if (bad)
+ goto mount_error;
/* Check in the exports list */
- sigprocmask(SIG_BLOCK, &sighup_mask, NULL);
ep = ex_search(&fsb.f_fsid);
hostset = defset = 0;
if (ep && (chk_host(ep->ex_defdir, saddr, &defset, &hostset) ||
@@ -800,13 +798,6 @@ mntsrv(struct svc_req *rqstp, SVCXPRT *t
chk_host(dp, saddr, &defset, &hostset)) ||
(defset && scan_tree(ep->ex_defdir, saddr) == 0 &&
scan_tree(ep->ex_dirl, saddr) == 0))) {
- if (bad) {
- if (!svc_sendreply(transp, xdr_long,
- (caddr_t)&bad))
- syslog(LOG_ERR, "Can't send reply");
- sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL);
- return;
- }
if (hostset & DP_HOSTSET)
fhr.fhr_flag = hostset;
else
@@ -817,11 +808,7 @@ mntsrv(struct svc_req *rqstp, SVCXPRT *t
if (imsg_getfh(dirpath, (fhandle_t *)&fhr.fhr_fh) < 0) {
bad = errno;
syslog(LOG_ERR, "Can't get fh for %s", dirpath);
- if (!svc_sendreply(transp, xdr_long,
- (caddr_t)&bad))
- syslog(LOG_ERR, "Can't send reply");
- sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL);
- return;
+ goto mount_error;
}
if (!svc_sendreply(transp, xdr_fhs, (caddr_t)&fhr))
syslog(LOG_ERR, "Can't send reply");
@@ -842,9 +829,11 @@ mntsrv(struct svc_req *rqstp, SVCXPRT *t
} else
bad = EACCES;
- if (bad && !svc_sendreply(transp, xdr_long, (caddr_t)&bad))
- syslog(LOG_ERR, "Can't send reply");
- sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL);
+ if (bad) {
+ mount_error:
+ if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad))
+ syslog(LOG_ERR, "Can't send reply");
+ }
return;
case RPCMNT_DUMP:
if (!svc_sendreply(transp, xdr_mlist, NULL))
@@ -958,11 +947,7 @@ xdr_explist(XDR *xdrsp, caddr_t cp)
{
struct exportlist *ep;
int false = 0, putdef;
- sigset_t sighup_mask;
- sigemptyset(&sighup_mask);
- sigaddset(&sighup_mask, SIGHUP);
- sigprocmask(SIG_BLOCK, &sighup_mask, NULL);
ep = exphead;
while (ep) {
putdef = 0;
@@ -973,12 +958,9 @@ xdr_explist(XDR *xdrsp, caddr_t cp)
goto errout;
ep = ep->ex_next;
}
- sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL);
- if (!xdr_bool(xdrsp, &false))
- return (0);
- return (1);
+ if (xdr_bool(xdrsp, &false))
+ return (1);
errout:
- sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL);
return (0);
}
@@ -1050,7 +1032,6 @@ void
new_exportlist(int signo)
{
gothup = 1;
-
}
/*