Theo,
I've examined your fix to this, and I believe that it may rely
upon a variable being set to a valid file system ID (fsb.f_fsid)
which won't be set to a known value if the directory requested doesn't
exist. In the random chance that fsb.f_fsid is set to a valid fsid
(because of the unknown state of uninitialised automatic variables)
then an unprivileged client will receive ENOENT instead of EACCES.
In general, as mountd doesn't know which export list to apply to a
non-existant directory, it's not possible for it to determine whether
the client is permitted or not. Therefore, it's not really feasible
to differentiate between ENOENT for "valid" clients and EACCES for
"invalid" clients.
Returning EACCES for non-existant directories as well as for lack of
sufficient permissions results in far simpler code, as opposed to a
more complicated solution, which would return EACCES except if the
requested non-existant directory would be part of an export list
that the client does have permissions for.
A pseudocode outline of the relevant code section in OpenBSD follows:
(see ftp://ftp3.usa.openbsd.org/pub/OpenBSD/src/sbin/mountd/mountd.c,
mntsvc() function)
-->
struct stat stb;
struct statfs fsb;
struct exportlist *ep;
long bad = 0;
if (stat(dirpath, &stb) < 0 ||
(!S_ISDIR(stb.st_mode) && !S_ISREG(stb.st_mode)) ||
statfs(dirpath, &fsb) < 0) {
bad = ENOENT;
}
ep = ex_search(&fsb.f_fsid);
/* lm: note that if the earlier stat() fails,
(and therefore bad=ENOENT), fsb will have
unknown contents because the call to statfs()
won't be made. Usually, however, this search
will fail, but there is a chance that the
random contents of the uninitialised fsb
will result in a +ve match */
if (ep && (chk_host(ep->ex_defdir, ...) || (....))) {
if (bad) {
/* lm: it's possible to get here because of
the conditions described above */
svc_sendreply(..., &bad, ); /* ENOENT */
return;
}
/* ...
* mount ok
* ...
*/
} else
bad = EACCES;
if (bad) {
svc_sendreply(..., &bad, ); /* bad = EACCES */
return;
}
<--
Sure, this is probably being a bit too paranoid, but depending on the
value of an uninitialised variable probably isn't the best solution...
I hope that I haven't misinterpreted your code and caused undue alarm.
Luke.
PS: bugtraq is a wonderful service - thanks from another (usually)
silent reader.
-- Luke Mewburn <lm@cs.rmit.edu.au> UNIX Technical Support, Department of Computer Science, RMIT. Developer, NetBSD Foundation <lukem@netbsd.org>