Skip to content

Commit 655a9fe

Browse files
authored
Merge pull request #129 from garlick/setgroups
improve setgroups error message and inline documentation
2 parents a0569b5 + 9abd6ae commit 655a9fe

File tree

5 files changed

+30
-264
lines changed

5 files changed

+30
-264
lines changed

scripts/check-root.sh

-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ sudo -n /bin/true || die "passwordless sudo is required to run privileged tests"
1010
sudo -n make -C src/libnpfs check TESTS="\
1111
test_capability.t \
1212
test_setfsuid.t \
13-
test_setgroups.t \
1413
test_setreuid.t" || die "test failed"
1514

1615
sudo -n make -C src/libdiod check TESTS="\

src/cmd/diod.c

+13-6
Original file line numberDiff line numberDiff line change
@@ -494,9 +494,14 @@ _service_sigsetup (void)
494494
}
495495

496496
#if USE_IMPERSONATION_LINUX
497-
/* Test whether setgroups applies to thread or process.
498-
* On RHEL6 (2.6.32 based) it applies to threads and we can use it.
499-
* On Ubuntu 11 (2.6.38 based) it applies to the whole process and we can't.
497+
/* POSIX setgroups(2) is per process but in Linux the underlying system call
498+
* is per-thread and the per-process bit is handled in glibc, so we can use
499+
* SYS_setgroups directly in the server thread pool when switching users.
500+
* This assumption is tenuous though, so we should quickly check it during
501+
* server startup, in case a future kernel update invalidates it.
502+
*
503+
* If we can't use it, a warning is issued and life goes on with group access
504+
* checks based on the user's primary group.
500505
*/
501506
void *
502507
_test_setgroups_thread (void *arg)
@@ -529,7 +534,7 @@ _test_setgroups (void)
529534
err_exit ("pthread_create");
530535
if ((err = pthread_join (t, NULL)))
531536
err_exit ("pthread_join");
532-
if ((n = getgroups (ngroups_max, sg)) < 0)
537+
if ((n = getgroups (0, NULL)) < 0)
533538
err_exit ("getgroups");
534539
if (n == 0)
535540
rc = 1;
@@ -619,8 +624,10 @@ _service_run (srvmode_t mode, int rfdno, int wfdno)
619624
#if USE_IMPERSONATION_LINUX
620625
if (_test_setgroups ())
621626
flags |= SRV_FLAGS_SETGROUPS;
622-
else
623-
msg ("test_setgroups: groups are per-process (disabling)");
627+
else {
628+
msg ("warning: supplemental group membership will be ignored."
629+
" Some accesses might be inappropriately denied.");
630+
}
624631
#elif USE_IMPERSONATION_GANESHA
625632
if (init_ganesha_syscalls() < 0)
626633
msg ("nfs-ganesha-kmod not loaded: changing user/group will fail");

src/libnpfs/Makefile.am

-4
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ TESTS = \
5151
test_fidpool.t \
5252
test_capability.t \
5353
test_setfsuid.t \
54-
test_setgroups.t \
5554
test_setreuid.t
5655

5756
check_PROGRAMS = $(TESTS)
@@ -71,8 +70,5 @@ test_capability_t_LDADD = $(test_ldadd)
7170
test_setfsuid_t_SOURCES = test/setfsuid.c
7271
test_setfsuid_t_LDADD = $(test_ldadd)
7372

74-
test_setgroups_t_SOURCES = test/setgroups.c
75-
test_setgroups_t_LDADD = $(test_ldadd)
76-
7773
test_setreuid_t_SOURCES = test/setreuid.c
7874
test_setreuid_t_LDADD = $(test_ldadd)

src/libnpfs/test/setgroups.c

-248
This file was deleted.

src/libnpfs/user-linux.c

+17-5
Original file line numberDiff line numberDiff line change
@@ -160,11 +160,23 @@ np_setfsid (Npreq *req, Npuser *u, u32 gid_override)
160160
else if (wt->fsuid == 0)
161161
wt->privcap = 0; /* trans from 0 clears caps */
162162

163-
/* Suppl groups need to be part of cred for NFS
164-
* forwarding even with DAC_BYPASS. However only
165-
* do it if kernel treats sg's per-thread not process.
166-
* Addendum: late model glibc attempts to make this
167-
* per-process, so for now bypass glibc. See issue 53.
163+
/* Set the user's supplementary groups (as read from the host
164+
* system's group configuration), but only if it can be
165+
* done safely.
166+
*
167+
* setgroups(2) is per-process (POSIX), which is incompatible
168+
* with the npfs thread pool model. SYS_setgroups, the
169+
* direct system call as opposed to the libc wrapper, is
170+
* per-thread, but relying on that is fragile. Therefore,
171+
* require the server to attest that SYS_setgroups is per-
172+
* thread on the server host kernel by setting a flag, e.g.
173+
* based on a test at startup. If the flag is unset, access
174+
* is determined solely by the user's uid and primary gid.
175+
*
176+
* Even with DAC_BYPASS, the supplementary groups might
177+
* into play if the host file system is NFS, since the
178+
* supplementary groups are still checked on the NFS server.
179+
* Unlike 9P, NFS transmits them over the wire.
168180
*/
169181
if ((srv->flags & SRV_FLAGS_SETGROUPS)) {
170182
if (syscall(SYS_setgroups, u->nsg, u->sg) < 0) {

0 commit comments

Comments
 (0)