On Wed, Feb 22, 2023 at 10:19:57AM -0700, Todd C. Miller wrote: > 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.
The code checker still finds an issue. if (realpath(rpcpath, dirpath) == NULL) { bad = errno; ... } if (bad) goto mount_error; This relys on the fact that after realpath() == NULL, errno != 0. I have checked libc, this works. The new report is a false positive. mbuhl@ mentioned to me that strlcpy(dirpath, rpcpath, sizeof(dirpath)); is dead code now. Before dirpath was used in ((dp = dirp_search(ep->ex_dirl, dirpath)) && even in the bad case. Now bad is set to ENOENT in a case where EACCES was used before. I doubt that this little change has relevant impact. OK bluhm@ > It needs testing by someone who actually uses NFS though... I am running it on my NFS server. > 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; > - > } > > /*