aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKyle Evans <kevans@FreeBSD.org>2025-07-24 14:59:07 +0000
committerKyle Evans <kevans@FreeBSD.org>2025-07-24 14:59:07 +0000
commit5138a20765c76cdc8f245d3d7caeffe9a9011bb2 (patch)
tree8c7481c4846b98e898a9f194dd5acf54890a9d0d
parent979210375351a667c248af09cfede81d0282fd75 (diff)
tftpd: explicitly set egid after dropping supplemental groups
tftpd seems to be the last program in base that implicitly relies on setgroups() to set the egid. This is a security landmine in portable software as most operating systems don't behave this way, so do an explicit setgid() in case the kernel doesn't set it already. While we're here, FreeBSD's setgroups() has supported nominally clearing all supplemental groups since 1997. It still leaves the egid in our cr_groups[0] because we don't have an out-of-band way to store the egid, and on other systems it'll clear the supplemental group entirely as one would want. Reviewed by: allanjude (previous version), des, olce Differential Revision: https://reviews.freebsd.org/D51149
-rw-r--r--libexec/tftpd/tftpd.c6
1 files changed, 5 insertions, 1 deletions
diff --git a/libexec/tftpd/tftpd.c b/libexec/tftpd/tftpd.c
index f8f9bd549a2e..a3faee86e7d0 100644
--- a/libexec/tftpd/tftpd.c
+++ b/libexec/tftpd/tftpd.c
@@ -351,10 +351,14 @@ main(int argc, char *argv[])
tftp_log(LOG_ERR, "chdir: %s", strerror(errno));
exit(1);
}
- if (setgroups(1, &nobody->pw_gid) != 0) {
+ if (setgroups(0, NULL) != 0) {
tftp_log(LOG_ERR, "setgroups failed");
exit(1);
}
+ if (setgid(nobody->pw_gid) != 0) {
+ tftp_log(LOG_ERR, "setgid failed");
+ exit(1);
+ }
if (setuid(nobody->pw_uid) != 0) {
tftp_log(LOG_ERR, "setuid failed");
exit(1);