mountd: Fix updating the network/host(s) for an exports line

Mountd reloads the exports(5) file(s) when it receives a SIGHUP
and then compares the old and new exports, updating any ones that
have changed in the kernel.

Without this patch, mountd failed to recognize that a network/host(s)
had changed, if there was no other change to the exports line.
As such, the change of network/hosts(s) did not take effect until
the mountd daemon was (re)started.

This patch fixes the code so that it checks for changes in
the network/host(s) list for an exports line.

PR:	286260
Approved by:	re (cperciva)

(cherry picked from commit 68daa781c1f12e1cfef768030eaff970c3d35543)
(cherry picked from commit 37abcf06f2100eeca41dbd67f8ca8228903ce5e8)
This commit is contained in:
Rick Macklem 2025-05-01 16:17:20 -07:00
parent 97a057f168
commit 2773c07181

View file

@ -244,6 +244,7 @@ static void free_exports(struct exportlisthead *);
static void read_exportfile(int);
static int compare_nmount_exportlist(struct iovec *, int, char *);
static int compare_export(struct exportlist *, struct exportlist *);
static int compare_addr(struct grouplist *, struct grouplist *);
static int compare_cred(struct expcred *, struct expcred *);
static int compare_secflavor(int *, int *, int);
static void delete_export(struct iovec *, int, struct statfs *, char *);
@ -2350,7 +2351,8 @@ compare_export(struct exportlist *ep, struct exportlist *oep)
grp->gr_exflags == ogrp->gr_exflags &&
compare_cred(&grp->gr_anon, &ogrp->gr_anon) == 0 &&
compare_secflavor(grp->gr_secflavors,
ogrp->gr_secflavors, grp->gr_numsecflavors) == 0)
ogrp->gr_secflavors, grp->gr_numsecflavors) == 0 &&
compare_addr(grp, ogrp) == 0)
break;
if (ogrp != NULL)
ogrp->gr_flag |= GR_FND;
@ -2363,6 +2365,46 @@ compare_export(struct exportlist *ep, struct exportlist *oep)
return (0);
}
/*
* Compare the addresses in the group. It is safe to return they are not
* the same when the are, so only return they are the same when they are
* exactly the same.
*/
static int
compare_addr(struct grouplist *grp, struct grouplist *ogrp)
{
struct addrinfo *ai, *oai;
if (grp->gr_type != ogrp->gr_type)
return (1);
switch (grp->gr_type) {
case GT_HOST:
ai = grp->gr_ptr.gt_addrinfo;
oai = ogrp->gr_ptr.gt_addrinfo;
for (; ai != NULL && oai != NULL; ai = ai->ai_next,
oai = oai->ai_next) {
if (sacmp(ai->ai_addr, oai->ai_addr, NULL) != 0)
return (1);
}
if (ai != NULL || oai != NULL)
return (1);
break;
case GT_NET:
/* First compare the masks and then the nets. */
if (sacmp((struct sockaddr *)&grp->gr_ptr.gt_net.nt_mask,
(struct sockaddr *)&ogrp->gr_ptr.gt_net.nt_mask, NULL) != 0)
return (1);
if (sacmp((struct sockaddr *)&grp->gr_ptr.gt_net.nt_net,
(struct sockaddr *)&ogrp->gr_ptr.gt_net.nt_net,
(struct sockaddr *)&grp->gr_ptr.gt_net.nt_mask) != 0)
return (1);
break;
default:
return (1);
}
return (0);
}
/*
* This algorithm compares two arrays of "n" items. It returns 0 if they are
* the "same" and 1 otherwise. Although suboptimal, it is always safe to