Changeset View
Changeset View
Standalone View
Standalone View
usr.sbin/mountd/mountd.c
Show First 20 Lines • Show All 204 Lines • ▼ Show 20 Lines | |||||
#define RELOADDELAY 250000 | #define RELOADDELAY 250000 | ||||
/* Global defs */ | /* Global defs */ | ||||
static char *add_expdir(struct dirlist **, char *, int); | static char *add_expdir(struct dirlist **, char *, int); | ||||
static void add_dlist(struct dirlist **, struct dirlist *, | static void add_dlist(struct dirlist **, struct dirlist *, | ||||
struct grouplist *, int, struct exportlist *, | struct grouplist *, int, struct exportlist *, | ||||
struct expcred *, uint64_t); | struct expcred *, uint64_t); | ||||
static void add_mlist(char *, char *); | static void add_mlist(char *, char *); | ||||
static int check_dirpath(char *); | static int check_path_component(const char *, char **); | ||||
static int check_dirpath(char *, char **); | |||||
static int check_statfs(const char *, struct statfs *, char **); | |||||
static int check_options(struct dirlist *); | static int check_options(struct dirlist *); | ||||
static int checkmask(struct sockaddr *sa); | static int checkmask(struct sockaddr *sa); | ||||
static int chk_host(struct dirlist *, struct sockaddr *, int *, int *, | static int chk_host(struct dirlist *, struct sockaddr *, int *, int *, | ||||
int *, int **); | int *, int **); | ||||
static char *strsep_quote(char **stringp, const char *delim); | static char *strsep_quote(char **stringp, const char *delim); | ||||
static int create_service(struct netconfig *nconf); | static int create_service(struct netconfig *nconf); | ||||
static void complete_service(struct netconfig *nconf, char *port_str); | static void complete_service(struct netconfig *nconf, char *port_str); | ||||
static void clearout_service(void); | static void clearout_service(void); | ||||
▲ Show 20 Lines • Show All 1,330 Lines • ▼ Show 20 Lines | |||||
get_exportlist_one(int passno) | get_exportlist_one(int passno) | ||||
{ | { | ||||
struct exportlist *ep; | struct exportlist *ep; | ||||
struct grouplist *grp, *tgrp, *savgrp; | struct grouplist *grp, *tgrp, *savgrp; | ||||
struct dirlist *dirhead; | struct dirlist *dirhead; | ||||
struct statfs fsb; | struct statfs fsb; | ||||
struct expcred anon; | struct expcred anon; | ||||
char *cp, *endcp, *dirp, *hst, *usr, *dom, savedc; | char *cp, *endcp, *dirp, *hst, *usr, *dom, savedc; | ||||
char *err_msg = NULL; | |||||
int len, has_host, got_nondir, dirplen, netgrp; | int len, has_host, got_nondir, dirplen, netgrp; | ||||
uint64_t exflags; | uint64_t exflags; | ||||
v4root_phase = 0; | v4root_phase = 0; | ||||
anon.cr_groups = NULL; | anon.cr_groups = NULL; | ||||
dirhead = (struct dirlist *)NULL; | dirhead = (struct dirlist *)NULL; | ||||
while (get_line()) { | while (get_line()) { | ||||
if (debug) | if (debug) | ||||
▲ Show 20 Lines • Show All 61 Lines • ▼ Show 20 Lines | while (len > 0) { | ||||
} else if (*cp == '/') { | } else if (*cp == '/') { | ||||
savedc = *endcp; | savedc = *endcp; | ||||
*endcp = '\0'; | *endcp = '\0'; | ||||
if (v4root_phase > 1) { | if (v4root_phase > 1) { | ||||
if (dirp != NULL) { | if (dirp != NULL) { | ||||
getexp_err(ep, tgrp, "Multiple V4 dirs"); | getexp_err(ep, tgrp, "Multiple V4 dirs"); | ||||
goto nextline; | goto nextline; | ||||
} | } | ||||
} | } | ||||
if (check_dirpath(cp) && | if (check_dirpath(cp, &err_msg) && | ||||
rmacklem: Minor nit. Although not needed for correctness,
I think setting err_msg = NULL here might be… | |||||
statfs(cp, &fsb) >= 0) { | check_statfs(cp, &fsb, &err_msg)) { | ||||
if ((fsb.f_flags & MNT_AUTOMOUNTED) != 0) | if ((fsb.f_flags & MNT_AUTOMOUNTED) != 0) | ||||
syslog(LOG_ERR, "Warning: exporting of " | syslog(LOG_ERR, "Warning: exporting of " | ||||
"automounted fs %s not supported", cp); | "automounted fs %s not supported", cp); | ||||
if (got_nondir) { | if (got_nondir) { | ||||
getexp_err(ep, tgrp, "dirs must be first"); | getexp_err(ep, tgrp, "dirs must be first"); | ||||
goto nextline; | goto nextline; | ||||
} | } | ||||
if (v4root_phase == 1) { | if (v4root_phase == 1) { | ||||
▲ Show 20 Lines • Show All 48 Lines • ▼ Show 20 Lines | while (len > 0) { | ||||
/* | /* | ||||
* Add dirpath to export mount point. | * Add dirpath to export mount point. | ||||
*/ | */ | ||||
dirp = add_expdir(&dirhead, cp, len); | dirp = add_expdir(&dirhead, cp, len); | ||||
dirplen = len; | dirplen = len; | ||||
} | } | ||||
} else { | } else { | ||||
if (err_msg != NULL) { | |||||
getexp_err(ep, tgrp, err_msg); | |||||
free(err_msg); | |||||
err_msg = NULL; | |||||
} else { | |||||
getexp_err(ep, tgrp, | getexp_err(ep, tgrp, | ||||
"symbolic link in export path or statfs failed"); | "symbolic link in export path or " | ||||
"statfs failed"); | |||||
} | |||||
goto nextline; | goto nextline; | ||||
} | } | ||||
*endcp = savedc; | *endcp = savedc; | ||||
} else { | } else { | ||||
savedc = *endcp; | savedc = *endcp; | ||||
*endcp = '\0'; | *endcp = '\0'; | ||||
got_nondir = 1; | got_nondir = 1; | ||||
if (ep == (struct exportlist *)NULL) { | if (ep == (struct exportlist *)NULL) { | ||||
▲ Show 20 Lines • Show All 2,067 Lines • ▼ Show 20 Lines | check_options(struct dirlist *dp) | ||||
} | } | ||||
if ((opt_flags & OP_ALLDIRS) && dp->dp_left) { | if ((opt_flags & OP_ALLDIRS) && dp->dp_left) { | ||||
syslog(LOG_ERR, "-alldirs has multiple directories"); | syslog(LOG_ERR, "-alldirs has multiple directories"); | ||||
return (1); | return (1); | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | |||||
check_path_component(const char *path, char **err) | |||||
{ | |||||
struct stat sb; | |||||
if (lstat(path, &sb)) { | |||||
asprintf(err, "%s: lstat() failed: %s.\n", | |||||
path, strerror(errno)); | |||||
return (0); | |||||
} | |||||
switch (sb.st_mode & S_IFMT) { | |||||
case S_IFDIR: | |||||
return (1); | |||||
case S_IFLNK: | |||||
asprintf(err, "%s: path is a symbolic link.\n", path); | |||||
break; | |||||
case S_IFREG: | |||||
asprintf(err, "%s: path is a file rather than a directory.\n", | |||||
path); | |||||
break; | |||||
default: | |||||
asprintf(err, "%s: path is not a directory.\n", path); | |||||
} | |||||
return (0); | |||||
} | |||||
/* | /* | ||||
* Check an absolute directory path for any symbolic links. Return true | * Check each path component for the presence of symbolic links. Return true | ||||
*/ | */ | ||||
Not Done Inline ActionsI'd update this comment to accurately note what this rmacklem: I'd update this comment to accurately note what this
function does. Then I would put an updated… | |||||
static int | static int | ||||
check_dirpath(char *dirp) | check_dirpath(char *dirp, char **err) | ||||
{ | { | ||||
char *cp; | char *cp; | ||||
int ret = 1; | |||||
struct stat sb; | |||||
Not Done Inline ActionsYou could get rid of "ret", since it no longer rmacklem: You could get rid of "ret", since it no longer
does anything. | |||||
cp = dirp + 1; | cp = dirp + 1; | ||||
while (*cp && ret) { | while (*cp) { | ||||
if (*cp == '/') { | if (*cp == '/') { | ||||
*cp = '\0'; | *cp = '\0'; | ||||
if (lstat(dirp, &sb) < 0 || !S_ISDIR(sb.st_mode)) | |||||
ret = 0; | if (!check_path_component(dirp, err)) { | ||||
*cp = '/'; | *cp = '/'; | ||||
return (0); | |||||
} | } | ||||
*cp = '/'; | |||||
} | |||||
cp++; | cp++; | ||||
} | } | ||||
if (lstat(dirp, &sb) < 0 || !S_ISDIR(sb.st_mode)) | |||||
ret = 0; | if (!check_path_component(dirp, err)) | ||||
return (ret); | return (0); | ||||
return (1); | |||||
} | |||||
/* | |||||
* Populate statfs information. Return true on success. | |||||
Not Done Inline ActionsSince statfs() is really a separate operation from Just a suggestion. rmacklem: Since statfs() is really a separate operation from
checking for a symbolic link, you might want… | |||||
*/ | |||||
static int | |||||
check_statfs(const char *dirp, struct statfs *fsb, char **err) | |||||
{ | |||||
if (statfs(dirp, fsb)) { | |||||
asprintf(err, "%s: statfs() failed: %s\n", dirp, | |||||
strerror(errno)); | |||||
return (0); | |||||
} | |||||
return (1); | |||||
} | } | ||||
/* | /* | ||||
* Make a netmask according to the specified prefix length. The ss_family | * Make a netmask according to the specified prefix length. The ss_family | ||||
* and other non-address fields must be initialised before calling this. | * and other non-address fields must be initialised before calling this. | ||||
*/ | */ | ||||
static int | static int | ||||
makemask(struct sockaddr_storage *ssp, int bitlen) | makemask(struct sockaddr_storage *ssp, int bitlen) | ||||
▲ Show 20 Lines • Show All 141 Lines • Show Last 20 Lines |
Minor nit. Although not needed for correctness,
I think setting err_msg = NULL here might be useful
as an extra safety belt and for readability.
(I'd only initialize it to NULL
when declared if the compiler complains it "might not
be initialized".)
But I'll leave this change up to you.