aboutsummaryrefslogtreecommitdiff
path: root/security/openssh-portable/files/patch-uidswap.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/openssh-portable/files/patch-uidswap.c')
-rw-r--r--security/openssh-portable/files/patch-uidswap.c57
1 files changed, 57 insertions, 0 deletions
diff --git a/security/openssh-portable/files/patch-uidswap.c b/security/openssh-portable/files/patch-uidswap.c
new file mode 100644
index 000000000000..b906d1d67480
--- /dev/null
+++ b/security/openssh-portable/files/patch-uidswap.c
@@ -0,0 +1,57 @@
+commit 239e8c98636a7578cc67a6f9d54d14c71b095e36
+Author: Kyle Evans <kevans@FreeBSD.org>
+Date: Sat Aug 9 11:01:57 2025 -0500
+
+ ssh: sshd-session: properly save off the privileged gid
+
+ Current and traditional FreeBSD behavior means that getegid() here is
+ the first element in the prior setgroups() call, if any, so we may
+ inadvertently wipe out our rgid with the unprivileged gid. This is
+ rendered somewhat harmless by the fact that we're losing the privileged
+ gid -- we'll still regain it as the egid in restore_uid() later by way
+ of restoring saved_egroups, rather than by intentionally restoring it
+ from getgid().
+
+ This will be promptly reverted if we can get setgroups(2)/getgroups(2)
+ changed in FreeBSD 15.0, but it seemed wise to get this technically
+ correct for previous branches.
+
+ Reviewed by: jlduran
+ Differential Revision: https://reviews.freebsd.org/D51753
+
+diff --git uidswap.c uidswap.c
+index 6ed3024d0180..0143f4994611 100644
+--- uidswap.c
++++ uidswap.c
+@@ -14,6 +14,10 @@
+
+ #include "includes.h"
+
++#ifdef __FreeBSD__
++#include <sys/param.h>
++#include <assert.h>
++#endif
+ #include <errno.h>
+ #include <pwd.h>
+ #include <string.h>
+@@ -121,8 +124,20 @@ temporarily_use_uid(struct passwd *pw)
+ fatal("setgroups: %.100s", strerror(errno));
+ #ifndef SAVED_IDS_WORK_WITH_SETEUID
+ /* Propagate the privileged gid to all of our gids. */
++#if defined(__FreeBSD__) && __FreeBSD_version < 1500061
++ /*
++ * FreeBSD traditionally includes the egid as the first element. If we
++ * use getegid() here then we effectively propagate user_groups[0],
++ * which is probably pw->pw_gid. Fix it to work as intended by using
++ * the egid we already have stashed off.
++ */
++ assert(saved_egroupslen > 0);
++ if (setgid(saved_egroups[0]) == -1)
++ debug("setgid %u: %.100s", (u_int) saved_egroups[0], strerror(errno));
++#else
+ if (setgid(getegid()) == -1)
+ debug("setgid %u: %.100s", (u_int) getegid(), strerror(errno));
++#endif
+ /* Propagate the privileged uid to all of our uids. */
+ if (setuid(geteuid()) == -1)
+ debug("setuid %u: %.100s", (u_int) geteuid(), strerror(errno));