From 3e474c2f201484be83d994ae10a4e20e8c81bb69 Mon Sep 17 00:00:00 2001
From: "Todd C. Miller" <Todd.Miller@sudo.ws>
Date: Sat, 8 Nov 2025 15:34:02 -0700
Subject: [PATCH] exec_mailer: Set group as well as uid when running the mailer

Also make a setuid(), setgid() or setgroups() failure fatal.

Found by the ZeroPath AI Security Engineer <https://zeropath.com>

CVE: CVE-2026-35535
Upstream-Status: Backport [https://github.com/sudo-project/sudo/commit/3e474c2f201484be83d994ae10a4e20e8c81bb69]
Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
---
 include/sudo_eventlog.h      |  3 ++-
 lib/eventlog/eventlog.c      | 21 +++++++++++++++++----
 lib/eventlog/eventlog_conf.c |  4 +++-
 plugins/sudoers/logging.c    |  2 +-
 plugins/sudoers/policy.c     |  2 +-
 5 files changed, 24 insertions(+), 8 deletions(-)

diff --git a/include/sudo_eventlog.h b/include/sudo_eventlog.h
index eb9f4f4..485d259 100644
--- a/include/sudo_eventlog.h
+++ b/include/sudo_eventlog.h
@@ -80,6 +80,7 @@ struct eventlog_config {
     int syslog_rejectpri;
     int syslog_alertpri;
     uid_t mailuid;
+    gid_t mailgid;
     bool omit_hostname;
     const char *logpath;
     const char *time_fmt;
@@ -151,7 +152,7 @@ void eventlog_set_syslog_rejectpri(int pri);
 void eventlog_set_syslog_alertpri(int pri);
 void eventlog_set_syslog_maxlen(size_t len);
 void eventlog_set_file_maxlen(size_t len);
-void eventlog_set_mailuid(uid_t uid);
+void eventlog_set_mailuser(uid_t uid, gid_t gid);
 void eventlog_set_omit_hostname(bool omit_hostname);
 void eventlog_set_logpath(const char *path);
 void eventlog_set_time_fmt(const char *fmt);
diff --git a/lib/eventlog/eventlog.c b/lib/eventlog/eventlog.c
index 5a32824..d56c4e4 100644
--- a/lib/eventlog/eventlog.c
+++ b/lib/eventlog/eventlog.c
@@ -304,15 +304,13 @@ exec_mailer(int pipein)
 	syslog(LOG_ERR, _("unable to dup stdin: %m")); // -V618
 	sudo_debug_printf(SUDO_DEBUG_ERROR,
 	    "unable to dup stdin: %s", strerror(errno));
-	sudo_debug_exit(__func__, __FILE__, __LINE__, sudo_debug_subsys);
-	_exit(127);
+	goto bad;
     }
 
     /* Build up an argv based on the mailer path and flags */
     if ((mflags = strdup(evl_conf->mailerflags)) == NULL) {
 	syslog(LOG_ERR, _("unable to allocate memory")); // -V618
-	sudo_debug_exit(__func__, __FILE__, __LINE__, sudo_debug_subsys);
-	_exit(127);
+	goto bad;
     }
     argv[0] = sudo_basename(mpath);
 
@@ -331,11 +329,23 @@ exec_mailer(int pipein)
     if (setuid(ROOT_UID) != 0) {
 	sudo_debug_printf(SUDO_DEBUG_ERROR, "unable to change uid to %u",
 	    ROOT_UID);
+	goto bad;
+    }
+    if (setgid(evl_conf->mailgid) != 0) {
+	sudo_debug_printf(SUDO_DEBUG_ERROR, "unable to change gid to %u",
+	    (unsigned int)evl_conf->mailgid);
+	goto bad;
+    }
+    if (setgroups(1, &evl_conf->mailgid) != 0) {
+	sudo_debug_printf(SUDO_DEBUG_ERROR, "unable to set groups to %u",
+	    (unsigned int)evl_conf->mailgid);
+	goto bad;
     }
     if (evl_conf->mailuid != ROOT_UID) {
 	if (setuid(evl_conf->mailuid) != 0) {
 	    sudo_debug_printf(SUDO_DEBUG_ERROR, "unable to change uid to %u",
 		(unsigned int)evl_conf->mailuid);
+	    goto bad;
 	}
     }
     sudo_debug_exit(__func__, __FILE__, __LINE__, sudo_debug_subsys);
@@ -347,6 +357,9 @@ exec_mailer(int pipein)
     sudo_debug_printf(SUDO_DEBUG_ERROR, "unable to execute %s: %s",
 	mpath, strerror(errno));
     _exit(127);
+bad:
+    sudo_debug_exit(__func__, __FILE__, __LINE__, sudo_debug_subsys);
+    _exit(127);
 }
 
 /* Send a message to the mailto user */
diff --git a/lib/eventlog/eventlog_conf.c b/lib/eventlog/eventlog_conf.c
index 0663a38..ec3b569 100644
--- a/lib/eventlog/eventlog_conf.c
+++ b/lib/eventlog/eventlog_conf.c
@@ -70,6 +70,7 @@ static struct eventlog_config evl_conf = {
     MAXSYSLOGLEN,		/* syslog_maxlen */
     0,				/* file_maxlen */
     ROOT_UID,			/* mailuid */
+    ROOT_GID,			/* mailgid */
     false,			/* omit_hostname */
     _PATH_SUDO_LOGFILE,		/* logpath */
     "%h %e %T",			/* time_fmt */
@@ -151,9 +152,10 @@ eventlog_set_file_maxlen(size_t len)
 }
 
 void
-eventlog_set_mailuid(uid_t uid)
+eventlog_set_mailuser(uid_t uid, gid_t gid)
 {
     evl_conf.mailuid = uid;
+    evl_conf.mailgid = gid;
 }
 
 void
diff --git a/plugins/sudoers/logging.c b/plugins/sudoers/logging.c
index bd4de92..9535289 100644
--- a/plugins/sudoers/logging.c
+++ b/plugins/sudoers/logging.c
@@ -1157,7 +1157,7 @@ init_eventlog_config(void)
     eventlog_set_syslog_alertpri(def_syslog_badpri);
     eventlog_set_syslog_maxlen(def_syslog_maxlen);
     eventlog_set_file_maxlen(def_loglinelen);
-    eventlog_set_mailuid(ROOT_UID);
+    eventlog_set_mailuser(ROOT_UID, ROOT_GID);
     eventlog_set_omit_hostname(!def_log_host);
     eventlog_set_logpath(def_logfile);
     eventlog_set_time_fmt(def_log_year ? "%h %e %T %Y" : "%h %e %T");
diff --git a/plugins/sudoers/policy.c b/plugins/sudoers/policy.c
index f3adfb0..27f6e58 100644
--- a/plugins/sudoers/policy.c
+++ b/plugins/sudoers/policy.c
@@ -639,7 +639,7 @@ sudoers_policy_deserialize_info(struct sudoers_context *ctx, void *v,
     }
 
 #ifdef NO_ROOT_MAILER
-    eventlog_set_mailuid(ctx->user.uid);
+    eventlog_set_mailuser(ctx->user.uid, ctx->user.gid);
 #endif
 
     /* Dump settings and user info (XXX - plugin args) */
-- 
2.50.1

