Attila Bogar reported a bug in mountd when multiple export

entries with different security flavors are in the exports(5)
file. For that case, mountd replies with the security flavors
of the last entry and not the correct one for the client host.
This patch fixes that by storing separate copies of the flavors
for each host/net case, plus a default one for the case where
no hosts/nets are specified on an entry in the exports(5) file.
Unlike the patch in the PR, it replies with the security flavors
for the entry instead of merging the security flavors for all
the entries and replying with that.

Tested by:	attila.bogar at linguamatics.com
PR:		kern/164933
MFC after:	2 weeks
This commit is contained in:
Rick Macklem 2012-09-24 23:57:16 +00:00
parent 6aa3468375
commit c3f86a256c
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=240902

View File

@ -117,6 +117,8 @@ struct exportlist {
char *ex_indexfile;
int ex_numsecflavors;
int ex_secflavors[MAXSECFLAVORS];
int ex_defnumsecflavors;
int ex_defsecflavors[MAXSECFLAVORS];
};
/* ex_flag bits */
#define EX_LINKED 0x1
@ -136,6 +138,8 @@ struct grouplist {
int gr_type;
union grouptypes gr_ptr;
struct grouplist *gr_next;
int gr_numsecflavors;
int gr_secflavors[MAXSECFLAVORS];
};
/* Group types */
#define GT_NULL 0x0
@ -163,12 +167,13 @@ struct fhreturn {
/* Global defs */
char *add_expdir(struct dirlist **, char *, int);
void add_dlist(struct dirlist **, struct dirlist *,
struct grouplist *, int);
struct grouplist *, int, struct exportlist *);
void add_mlist(char *, char *);
int check_dirpath(char *);
int check_options(struct dirlist *);
int checkmask(struct sockaddr *sa);
int chk_host(struct dirlist *, struct sockaddr *, int *, int *);
int chk_host(struct dirlist *, struct sockaddr *, int *, int *, int *,
int **);
static int create_service(struct netconfig *nconf);
static void complete_service(struct netconfig *nconf, char *port_str);
static void clearout_service(void);
@ -938,6 +943,7 @@ mntsrv(struct svc_req *rqstp, SVCXPRT *transp)
char rpcpath[MNTPATHLEN + 1], dirpath[MAXPATHLEN];
int bad = 0, defset, hostset;
sigset_t sighup_mask;
int numsecflavors, *secflavorsp;
sigemptyset(&sighup_mask);
sigaddset(&sighup_mask, SIGHUP);
@ -1000,9 +1006,11 @@ mntsrv(struct svc_req *rqstp, SVCXPRT *transp)
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) ||
if (ep && (chk_host(ep->ex_defdir, saddr, &defset, &hostset,
&numsecflavors, &secflavorsp) ||
((dp = dirp_search(ep->ex_dirl, dirpath)) &&
chk_host(dp, saddr, &defset, &hostset)) ||
chk_host(dp, saddr, &defset, &hostset, &numsecflavors,
&secflavorsp)) ||
(defset && scan_tree(ep->ex_defdir, saddr) == 0 &&
scan_tree(ep->ex_dirl, saddr) == 0))) {
if (bad) {
@ -1012,10 +1020,15 @@ mntsrv(struct svc_req *rqstp, SVCXPRT *transp)
sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL);
return;
}
if (hostset & DP_HOSTSET)
if (hostset & DP_HOSTSET) {
fhr.fhr_flag = hostset;
else
fhr.fhr_numsecflavors = numsecflavors;
fhr.fhr_secflavors = secflavorsp;
} else {
fhr.fhr_flag = defset;
fhr.fhr_numsecflavors = ep->ex_defnumsecflavors;
fhr.fhr_secflavors = ep->ex_defsecflavors;
}
fhr.fhr_vers = rqstp->rq_vers;
/* Get the file handle */
memset(&fhr.fhr_fh, 0, sizeof(nfsfh_t));
@ -1028,8 +1041,6 @@ mntsrv(struct svc_req *rqstp, SVCXPRT *transp)
sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL);
return;
}
fhr.fhr_numsecflavors = ep->ex_numsecflavors;
fhr.fhr_secflavors = ep->ex_secflavors;
if (!svc_sendreply(transp, (xdrproc_t)xdr_fhs,
(caddr_t)&fhr))
syslog(LOG_ERR, "can't send reply");
@ -1881,11 +1892,21 @@ hang_dirp(struct dirlist *dp, struct grouplist *grp, struct exportlist *ep,
ep->ex_defdir = dp;
if (grp == (struct grouplist *)NULL) {
ep->ex_defdir->dp_flag |= DP_DEFSET;
/* Save the default security flavors list. */
ep->ex_defnumsecflavors = ep->ex_numsecflavors;
if (ep->ex_numsecflavors > 0)
memcpy(ep->ex_defsecflavors, ep->ex_secflavors,
sizeof(ep->ex_secflavors));
} else while (grp) {
hp = get_ht();
hp->ht_grp = grp;
hp->ht_next = ep->ex_defdir->dp_hosts;
ep->ex_defdir->dp_hosts = hp;
/* Save the security flavors list for this host set. */
grp->gr_numsecflavors = ep->ex_numsecflavors;
if (ep->ex_numsecflavors > 0)
memcpy(grp->gr_secflavors, ep->ex_secflavors,
sizeof(ep->ex_secflavors));
grp = grp->gr_next;
}
} else {
@ -1895,7 +1916,7 @@ hang_dirp(struct dirlist *dp, struct grouplist *grp, struct exportlist *ep,
*/
while (dp) {
dp2 = dp->dp_left;
add_dlist(&ep->ex_dirl, dp, grp, flags);
add_dlist(&ep->ex_dirl, dp, grp, flags, ep);
dp = dp2;
}
}
@ -1907,7 +1928,7 @@ hang_dirp(struct dirlist *dp, struct grouplist *grp, struct exportlist *ep,
*/
void
add_dlist(struct dirlist **dpp, struct dirlist *newdp, struct grouplist *grp,
int flags)
int flags, struct exportlist *ep)
{
struct dirlist *dp;
struct hostlist *hp;
@ -1917,10 +1938,10 @@ add_dlist(struct dirlist **dpp, struct dirlist *newdp, struct grouplist *grp,
if (dp) {
cmp = strcmp(dp->dp_dirp, newdp->dp_dirp);
if (cmp > 0) {
add_dlist(&dp->dp_left, newdp, grp, flags);
add_dlist(&dp->dp_left, newdp, grp, flags, ep);
return;
} else if (cmp < 0) {
add_dlist(&dp->dp_right, newdp, grp, flags);
add_dlist(&dp->dp_right, newdp, grp, flags, ep);
return;
} else
free((caddr_t)newdp);
@ -1939,10 +1960,20 @@ add_dlist(struct dirlist **dpp, struct dirlist *newdp, struct grouplist *grp,
hp->ht_grp = grp;
hp->ht_next = dp->dp_hosts;
dp->dp_hosts = hp;
/* Save the security flavors list for this host set. */
grp->gr_numsecflavors = ep->ex_numsecflavors;
if (ep->ex_numsecflavors > 0)
memcpy(grp->gr_secflavors, ep->ex_secflavors,
sizeof(ep->ex_secflavors));
grp = grp->gr_next;
} while (grp);
} else {
dp->dp_flag |= DP_DEFSET;
/* Save the default security flavors list. */
ep->ex_defnumsecflavors = ep->ex_numsecflavors;
if (ep->ex_numsecflavors > 0)
memcpy(ep->ex_defsecflavors, ep->ex_secflavors,
sizeof(ep->ex_secflavors));
}
}
@ -1971,7 +2002,7 @@ dirp_search(struct dirlist *dp, char *dirp)
*/
int
chk_host(struct dirlist *dp, struct sockaddr *saddr, int *defsetp,
int *hostsetp)
int *hostsetp, int *numsecflavors, int **secflavorsp)
{
struct hostlist *hp;
struct grouplist *grp;
@ -1990,6 +2021,12 @@ chk_host(struct dirlist *dp, struct sockaddr *saddr, int *defsetp,
if (!sacmp(ai->ai_addr, saddr, NULL)) {
*hostsetp =
(hp->ht_flag | DP_HOSTSET);
if (numsecflavors != NULL) {
*numsecflavors =
grp->gr_numsecflavors;
*secflavorsp =
grp->gr_secflavors;
}
return (1);
}
}
@ -2000,6 +2037,12 @@ chk_host(struct dirlist *dp, struct sockaddr *saddr, int *defsetp,
(struct sockaddr *)
&grp->gr_ptr.gt_net.nt_mask)) {
*hostsetp = (hp->ht_flag | DP_HOSTSET);
if (numsecflavors != NULL) {
*numsecflavors =
grp->gr_numsecflavors;
*secflavorsp =
grp->gr_secflavors;
}
return (1);
}
break;
@ -2021,7 +2064,7 @@ scan_tree(struct dirlist *dp, struct sockaddr *saddr)
if (dp) {
if (scan_tree(dp->dp_left, saddr))
return (1);
if (chk_host(dp, saddr, &defset, &hostset))
if (chk_host(dp, saddr, &defset, &hostset, NULL, NULL))
return (1);
if (scan_tree(dp->dp_right, saddr))
return (1);