since the match can never succeed after realpath() converts incoming
paths to the "real" one.
From Rick Macklem root@snowhite.cis.uoguelph.ca (Charlie Root)
SCCS-vsn: sbin/mountd/exports.5 8.2
SCCS-vsn: sbin/mountd/mountd.c 8.6
.\"
.\" %sccs.include.redist.roff%
.\"
.\"
.\" %sccs.include.redist.roff%
.\"
-.\" @(#)exports.5 8.1 (Berkeley) %G%
+.\" @(#)exports.5 8.2 (Berkeley) %G%
.Fl alldirs
flag;
this form allows the host(s) to mount any directory within the filesystem.
.Fl alldirs
flag;
this form allows the host(s) to mount any directory within the filesystem.
+The pathnames must not have any symbolic links in them and should not have
+any "." or ".." components.
Mount points for a filesystem may appear on multiple lines each with
different sets of hosts and export options.
.Pp
Mount points for a filesystem may appear on multiple lines each with
different sets of hosts and export options.
.Pp
#endif not lint
#ifndef lint
#endif not lint
#ifndef lint
-static char sccsid[] = "@(#)mountd.c 8.5 (Berkeley) %G%";
+static char sccsid[] = "@(#)mountd.c 8.6 (Berkeley) %G%";
#endif not lint
#include <sys/param.h>
#endif not lint
#include <sys/param.h>
/* Global defs */
int mntsrv(), umntall_each(), xdr_fhs(), xdr_mlist(), xdr_dir(), xdr_explist();
/* Global defs */
int mntsrv(), umntall_each(), xdr_fhs(), xdr_mlist(), xdr_dir(), xdr_explist();
void get_exportlist(), send_umntall(), nextfield(), out_of_mem();
void get_mountlist(), add_mlist(), del_mlist(), free_exp(), free_grp();
void getexp_err(), hang_dirp(), add_dlist(), free_dir(), free_host();
void get_exportlist(), send_umntall(), nextfield(), out_of_mem();
void get_mountlist(), add_mlist(), del_mlist(), free_exp(), free_grp();
void getexp_err(), hang_dirp(), add_dlist(), free_dir(), free_host();
register struct grouplist *grp, *tgrp;
struct exportlist **epp;
struct dirlist *dirhead;
register struct grouplist *grp, *tgrp;
struct exportlist **epp;
struct dirlist *dirhead;
struct statfs fsb, *fsp;
struct hostent *hpe;
struct ucred anon;
struct statfs fsb, *fsp;
struct hostent *hpe;
struct ucred anon;
} else if (*cp == '/') {
savedc = *endcp;
*endcp = '\0';
} else if (*cp == '/') {
savedc = *endcp;
*endcp = '\0';
- if (stat(cp, &sb) >= 0 &&
- (sb.st_mode & S_IFMT) == S_IFDIR &&
+ if (check_dirpath(cp) &&
statfs(cp, &fsb) >= 0) {
if (got_nondir) {
syslog(LOG_ERR, "Dirs must be first");
statfs(cp, &fsb) >= 0) {
if (got_nondir) {
syslog(LOG_ERR, "Dirs must be first");
+
+/*
+ * Check an absolute directory path for any symbolic links. Return true
+ * if no symbolic links are found.
+ */
+int
+check_dirpath(dirp)
+ register char *dirp;
+{
+ register char *cp;
+ int ret = 1;
+ struct stat sb;
+
+ cp = dirp + 1;
+ while (*cp && ret) {
+ if (*cp == '/') {
+ *cp = '\0';
+ if (lstat(dirp, &sb) < 0 ||
+ (sb.st_mode & S_IFMT) != S_IFDIR)
+ ret = 0;
+ *cp = '/';
+ }
+ cp++;
+ }
+ if (lstat(dirp, &sb) < 0 ||
+ (sb.st_mode & S_IFMT) != S_IFDIR)
+ ret = 0;
+ return (ret);
+}