Page MenuHomeFreeBSD

mountd(8): Allow to pass {NGROUPS_MAX} + 1 groups
ClosedPublic

Authored by olce on Oct 8 2024, 1:47 PM.
Tags
None
Referenced Files
F107352197: D47016.diff
Sun, Jan 12, 10:07 PM
F107345711: D47016.id144828.diff
Sun, Jan 12, 7:43 PM
Unknown Object (File)
Sun, Jan 5, 6:31 PM
Unknown Object (File)
Sun, Jan 5, 10:41 AM
Unknown Object (File)
Sat, Dec 21, 8:01 AM
Unknown Object (File)
Thu, Dec 19, 8:31 PM
Unknown Object (File)
Mon, Dec 16, 2:48 PM
Unknown Object (File)
Dec 9 2024, 1:31 AM
Subscribers

Details

Summary

NGROUPS_MAX is just the minimum maximum of the number of allowed
supplementary groups. The actual runtime value may be greater. Allow
more groups to be specified accordingly (now that, a few commits ago,
nmount(2) has been changed similarly).

To this end, we just allocate once and for all a static array called
'tmp_groups' big enough to hold {NGROUPS_MAX} + 1 groups (the maximum
number of supplementary groups and the effective GID) in main() and use
this temporary space in get_exportlist_one(), do_opt() and parsecred().
Doing so in passing fixes a memory leak in case "-maproot" and/or
"-mapall" were specified multiple times.

parcred() does not use 'cr_smallgrps' anymore, but we have kept
'cr_smallgrps'/SMALLNGROUPS as 'struct expcred' is also included in
'struct exportlist' and 'struct grouplist', and thus this preallocated
field still results in an optimization for the common case of small
number of groups (although its real impact is probably negligible and
arguably not worth the trouble).

While here, in do_mount(), remove some unnecessary groups array
allocation and copying.

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Skipped
Unit
Tests Skipped
Build Status
Buildable 59976
Build 56861: arc lint + arc unit

Event Timeline

olce requested review of this revision.Oct 8 2024, 1:47 PM
usr.sbin/mountd/mountd.c
3665–3666

This seems unnecessarily complex to me.
Since "kern.ngroups" cannot change after booting
(it is a RDTUN), you only need to sysconf() once.
Given the overhead, I'd suggest doing it once in
main().

Then you can just:

groups = malloc(sizeof(gid_t) * (ngroups_max + 1));

Since mountd is single threaded, you could even choose
to only do the malloc() once in main() and make "groups"
a global variable.
Alternately, doing one malloc()/free() for each call to parsecred()
seems ok to me, as well.

olce retitled this revision from mountd(8): parsecred(): Allow to pass _SC_NGROUPS_MAX + 1 groups to mountd(8): Allow to pass {NGROUPS_MAX} + 1 groups.
olce edited the summary of this revision. (Show Details)

Simplify by allocating a single temporary groups array big enough for {NGROUPS_MAX} + 1 groups at once at program startup.

See the revised commit message (this revision's description) for the other changes.

usr.sbin/mountd/mountd.c
3665–3666

Since "kern.ngroups" cannot change after booting
(it is a RDTUN), you only need to sysconf() once.
Given the overhead, I'd suggest doing it once in
main().

Not sure that really matters, but done, see below.

Then you can just:

groups = malloc(sizeof(gid_t) * (ngroups_max + 1));

Yes, I over-optimized by starting small and handling reallocations, instead of just allocating the max number of groups at once. What are a few to hundreds of kilobytes today anyway?

Since mountd is single threaded, you could even choose
to only do the malloc() once in main() and make "groups"
a global variable.

The allocation is now done once and for all in main() (pointer is stored in tmp_groups and number of groups in ngroups_max).

This version looks fine to me.

This revision is now accepted and ready to land.Oct 14 2024, 8:03 PM
usr.sbin/mountd/mountd.c
3688–3695

I'll revert this gratuitous change when committing. It is additionally wrong as cr_ngroups is incremented before the check and left as is although we are continuing with the process (eliding the supernumerary groups).

usr.sbin/mountd/mountd.c
3688–3695

I mean, all changes here except NGROUPS_MAX => ngroups_max.