[packages/screen] Rel 2; security fixes for few issues https://security.opensuse.org/2025/05/12/screen-security-issues

arekm arekm at pld-linux.org
Mon May 12 23:37:42 CEST 2025


commit 06b56d959517296e2d87a47310d0cf8318096d5e
Author: Arkadiusz Miśkiewicz <arekm at maven.pl>
Date:   Mon May 12 23:37:30 2025 +0200

    Rel 2; security fixes for few issues https://security.opensuse.org/2025/05/12/screen-security-issues.html

 ...ntroduce-lf_secreopen-to-fix-CVE-2025-233.patch | 137 +++++++++++++++++++++
 ...-mode-apply-safe-default-mode-of-0620-to-.patch |  49 ++++++++
 ...fix-bad-strncpy-which-can-lead-to-a-buffe.patch |  60 +++++++++
 ...prevent-temporary-0666-mode-on-PTYs-to-fi.patch | 113 +++++++++++++++++
 ...existence-test-information-leaks-to-fix-C.patch | 130 +++++++++++++++++++
 ...n-t-send-signals-with-root-privileges-to-.patch | 115 +++++++++++++++++
 screen.spec                                        |  29 +++--
 7 files changed, 625 insertions(+), 8 deletions(-)
---
diff --git a/screen.spec b/screen.spec
index 9d8aacb..2a2cfc1 100644
--- a/screen.spec
+++ b/screen.spec
@@ -11,7 +11,7 @@ Summary(tr.UTF-8):	Bir uçbirimde birden fazla oturumu düzenler
 Summary(uk.UTF-8):	Менеджер екрану, що підтримує кілька логінів з одного терміналу
 Name:		screen
 Version:	5.0.0
-Release:	1
+Release:	2
 License:	GPL v3+
 Group:		Applications/Terminal
 Source0:	https://ftp.gnu.org/gnu/screen/%{name}-%{version}.tar.gz
@@ -20,6 +20,12 @@ Source1:	http://www.mif.pg.gda.pl/homepages/ankry/man-PLD/%{name}-non-english-ma
 # Source1-md5:	236166e774cee788cf594b05dd1dd70d
 Source2:	%{name}.pamd
 Source3:	%{name}rc
+Patch100:	0001-logfile-reintroduce-lf_secreopen-to-fix-CVE-2025-233.patch
+Patch101:	0002-default-PTY-mode-apply-safe-default-mode-of-0620-to-.patch
+Patch102:	0003-attacher.c-fix-bad-strncpy-which-can-lead-to-a-buffe.patch
+Patch103:	0004-attacher.c-prevent-temporary-0666-mode-on-PTYs-to-fi.patch
+Patch104:	0005-Avoid-file-existence-test-information-leaks-to-fix-C.patch
+Patch105:	0006-socket.c-don-t-send-signals-with-root-privileges-to-.patch
 Patch2:		%{name}-manual.patch
 Patch4:		%{name}-info.patch
 Patch7:		%{name}-no_hardcoded_term_sequences.patch
@@ -92,16 +98,23 @@ Screen корисний користувачам, які заходять на 
 
 %prep
 %setup -q
-%patch2 -p1
-%patch4 -p1
+%patch -P2 -p1
+%patch -P4 -p1
 # DON'T ENABLE IT UNLESS YOU REALLY FIX IT
 # (it's heavily broken - note that some sequences should be get for
 # $TERM before running screen instance, and others for TERM=screen!)
-###%patch7 -p1
-#%patch8 -p1
-%patch12 -p1
-#%patch13 -p1 # my brain farted here, see if you have better luck
-%patch18 -p1
+###%%patch -P7 -p1
+#%%patch -P8 -p1
+%patch -P12 -p1
+#%%patch -P13 -p1 # my brain farted here, see if you have better luck
+%patch -P18 -p1
+
+%patch -P100 -p1
+%patch -P101 -p1
+%patch -P102 -p1
+%patch -P103 -p1
+%patch -P104 -p1
+%patch -P105 -p1
 
 %build
 %{__aclocal}
diff --git a/0001-logfile-reintroduce-lf_secreopen-to-fix-CVE-2025-233.patch b/0001-logfile-reintroduce-lf_secreopen-to-fix-CVE-2025-233.patch
new file mode 100644
index 0000000..37c7043
--- /dev/null
+++ b/0001-logfile-reintroduce-lf_secreopen-to-fix-CVE-2025-233.patch
@@ -0,0 +1,137 @@
+From a23f2fa9fbb3cb214ed6a8ab71c99bba94f79e92 Mon Sep 17 00:00:00 2001
+From: Alex Naumov <alexander_naumov at opensuse.org>
+Date: Wed, 7 May 2025 10:42:55 +0200
+Subject: [PATCH 1/6] logfile: reintroduce lf_secreopen() to fix CVE-2025-23395
+
+In commit 441bca708bd this function was mistakenly removed, which
+introduces a local root exploit vulnerability when running screen in
+setuid-root context.
+
+Committed-By: Matthias Gerstner <matthias.gerstner at suse.de>
+---
+ logfile.c | 27 +++++++++++++++++++++++----
+ logfile.h | 10 ++++++++++
+ screen.c  | 19 +++++++++++++++++++
+ 3 files changed, 52 insertions(+), 4 deletions(-)
+
+diff --git a/logfile.c b/logfile.c
+index 65e7205..91dc224 100644
+--- a/logfile.c
++++ b/logfile.c
+@@ -88,10 +88,29 @@ static int logfile_reopen(char *name, int wantfd, Log *l)
+ 		return -1;
+ 	}
+ 	changed_logfile(l);
+-	l->st->st_ino = l->st->st_dev = 0;
+ 	return 0;
+ }
+ 
++static int (*lf_reopen_fn) (char *, int, struct Log *) = logfile_reopen;
++
++/*
++ * Whenever logfwrite discoveres that it is required to close and
++ * reopen the logfile, the function registered here is called.
++ * If you do not register anything here, the above logfile_reopen()
++ * will be used instead.
++ * Your function should perform the same steps as logfile_reopen():
++ * a) close the original filedescriptor without flushing any output
++ * b) open a new logfile for future output on the same filedescriptor number.
++ * c) zero out st_dev, st_ino to tell the stolen_logfile() indcator to
++ *    reinitialise itself.
++ * d) return 0 on success.
++ */
++void logreopen_register(int (*fn) (char *, int, struct Log *))
++{
++	lf_reopen_fn = fn ? fn : logfile_reopen;
++}
++
++
+ /*
+  * If the logfile has been removed, truncated, unlinked or the like,
+  * return nonzero.
+@@ -204,7 +223,7 @@ int logfwrite(Log *l, char *buf, size_t n)
+ {
+ 	int r;
+ 
+-	if (stolen_logfile(l) && logfile_reopen(l->name, fileno(l->fp), l))
++	if (stolen_logfile(l) && lf_reopen_fn(l->name, fileno(l->fp), l))
+ 		return -1;
+ 	r = fwrite(buf, n, 1, l->fp);
+ 	l->writecount += l->flushcount + 1;
+@@ -219,13 +238,13 @@ int logfflush(Log *l)
+ 
+ 	if (!l)
+ 		for (l = logroot; l; l = l->next) {
+-			if (stolen_logfile(l) && logfile_reopen(l->name, fileno(l->fp), l))
++			if (stolen_logfile(l) && lf_reopen_fn(l->name, fileno(l->fp), l))
+ 				return -1;
+ 			r |= fflush(l->fp);
+ 			l->flushcount++;
+ 			changed_logfile(l);
+ 	} else {
+-		if (stolen_logfile(l) && logfile_reopen(l->name, fileno(l->fp), l))
++		if (stolen_logfile(l) && lf_reopen_fn(l->name, fileno(l->fp), l))
+ 			return -1;
+ 		r = fflush(l->fp);
+ 		l->flushcount++;
+diff --git a/logfile.h b/logfile.h
+index dbc9c2c..569a90e 100644
+--- a/logfile.h
++++ b/logfile.h
+@@ -71,6 +71,16 @@ int logfwrite (Log *, char *, size_t);
+  */
+ int logfflush (Log *ifany);
+ 
++/*
++ * a reopen function may be registered here, in case you want to bring your
++ * own (more secure open), it may come along with a private data pointer.
++ * this function is called, whenever logfwrite/logfflush detect that the
++ * file has been (re)moved, truncated or changed by someone else.
++ * if you provide NULL as parameter to logreopen_register, the builtin
++ * reopen function will be reactivated.
++ */
++void logreopen_register (int (*fn) (char *, int, struct Log *) );
++
+ /*
+  * Your custom reopen function is required to reuse the exact
+  * filedescriptor.
+diff --git a/screen.c b/screen.c
+index a79c3b1..728e717 100644
+--- a/screen.c
++++ b/screen.c
+@@ -199,6 +199,21 @@ static int GotSigChld;
+ /********************************************************************/
+ /********************************************************************/
+ 
++static int lf_secreopen(char *name, int wantfd, struct Log *l)
++{
++	int got_fd;
++
++	close(wantfd);
++	if (((got_fd = secopen(name, O_WRONLY | O_CREAT | O_APPEND, 0666)) < 0) || lf_move_fd(got_fd, wantfd) < 0) {
++		logfclose(l);
++		return -1;
++	}
++	l->st->st_ino = l->st->st_dev = 0;
++	return 0;
++}
++
++
++
+ static struct passwd *getpwbyname(char *name, struct passwd *ppp)
+ {
+ 	int n;
+@@ -349,6 +364,10 @@ int main(int argc, char **argv)
+ #ifdef ENABLE_TELNET
+ 	af                = AF_UNSPEC;
+ #endif
++	/* lf_secreopen() is vital for the secure operation in setuid-root context.
++	 * Do not remove it
++	 */
++	logreopen_register(lf_secreopen);
+ 
+ 	real_uid          = getuid();
+ 	real_gid          = getgid();
+-- 
+2.49.0
+
diff --git a/0002-default-PTY-mode-apply-safe-default-mode-of-0620-to-.patch b/0002-default-PTY-mode-apply-safe-default-mode-of-0620-to-.patch
new file mode 100644
index 0000000..d9f8dab
--- /dev/null
+++ b/0002-default-PTY-mode-apply-safe-default-mode-of-0620-to-.patch
@@ -0,0 +1,49 @@
+From 4f1c9e41bae1547077a524241952c244b969645f Mon Sep 17 00:00:00 2001
+From: Alex Naumov <alexander_naumov at opensuse.org>
+Date: Wed, 7 May 2025 10:45:30 +0200
+Subject: [PATCH 2/6] default PTY mode: apply safe default mode of 0620 to fix
+ CVE-2025-46803
+
+During refactoring of configure.ac the default PTY mode was changed from
+0620 to 0622 without documenting this change. Packagers that don't pass
+an explicit `--with-pty-mode=0620` will end up with world-writable PTYs.
+Revert the default back of 0620 to provide a safe default again.
+
+Committed-By: Matthias Gerstner <matthias.gerstner at suse.de>
+---
+ configure.ac | 4 ++--
+ process.c    | 2 +-
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/configure.ac b/configure.ac
+index 976b1e0..34caf99 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -117,9 +117,9 @@ AC_ARG_WITH(system_screenrc, AS_HELP_STRING([--with-system_screenrc],
+ 	    [with_system_screenrc=$withval],
+ 	    [with_system_screenrc=/etc/screenrc])
+ AC_ARG_WITH(pty-mode, AS_HELP_STRING([--with-pty-mode],
+-	    [set pty mode (default: 0622)]),
++	    [set pty mode (default: 0620)]),
+ 	    [with_pty_mode=$withval],
+-	    [with_pty_mode=0622])
++	    [with_pty_mode=0620])
+ AC_ARG_WITH(pty-group, AS_HELP_STRING([--with-pty-group],
+ 	    [set pty group (default: 5)]),
+ 	    [with_pty_group=$withval],
+diff --git a/process.c b/process.c
+index 470e70a..3912803 100644
+--- a/process.c
++++ b/process.c
+@@ -117,7 +117,7 @@ char NullStr[] = "";
+ struct plop plop_tab[MAX_PLOP_DEFS];
+ 
+ #ifndef PTY_MODE
+-#define PTY_MODE 0622
++#define PTY_MODE 0620
+ #endif
+ 
+ int TtyMode = PTY_MODE;
+-- 
+2.49.0
+
diff --git a/0003-attacher.c-fix-bad-strncpy-which-can-lead-to-a-buffe.patch b/0003-attacher.c-fix-bad-strncpy-which-can-lead-to-a-buffe.patch
new file mode 100644
index 0000000..3ad0a01
--- /dev/null
+++ b/0003-attacher.c-fix-bad-strncpy-which-can-lead-to-a-buffe.patch
@@ -0,0 +1,60 @@
+From e61649242afc42213e7fd3bb8b3dbea33be96761 Mon Sep 17 00:00:00 2001
+From: Alex Naumov <alexander_naumov at opensuse.org>
+Date: Wed, 7 May 2025 10:49:24 +0200
+Subject: [PATCH 3/6] attacher.c: fix bad strncpy() which can lead to a buffer
+ overflow
+
+`strncpy()` always pads the destination buffer with zeroes, regardless
+of the length of the input string. Passing `MAXPATHLEN` in every `for`
+loop iteration will cause a buffer write overflow past the end of the
+`m.m.command.cmd` buffer.
+
+This becomes visible on systems that compile Screen with the
+`_FORTIFY_SOURCE` macro enabled when passing more than one parameter,
+for example like this:
+
+```
+screen -S myinstance -X blankerprg /path/to/blanker
+*** buffer overflow detected ***: terminated
+Aborted (core dumped)
+```
+
+This is not security relevant, since only zeroes are written past the
+end of the buffer and only other message buffer fields can be reached,
+no internal state of Screen can be changed.
+
+Committed-By: Matthias Gerstner <matthias.gerstner at suse.de>
+---
+ attacher.c | 15 +++++++++------
+ 1 file changed, 9 insertions(+), 6 deletions(-)
+
+diff --git a/attacher.c b/attacher.c
+index d8de9d4..4e1a77e 100644
+--- a/attacher.c
++++ b/attacher.c
+@@ -457,13 +457,16 @@ void SendCmdMessage(char *sty, char *match, char **av, int query)
+ 	}
+ 	p = m.m.command.cmd;
+ 	n = 0;
++	size_t space_left = ARRAY_SIZE(m.m.command.cmd);
++
+ 	for (; *av && n < MAXARGS - 1; ++av, ++n) {
+-		size_t len;
+-		len = strlen(*av) + 1;
+-		if (p + len >= m.m.command.cmd + ARRAY_SIZE(m.m.command.cmd) - 1)
+-			break;
+-		strncpy(p, *av, MAXPATHLEN);
+-		p += len;
++		int printed = snprintf(p, space_left, "%s", *av);
++		if (printed < 0 || (size_t)printed >= space_left)
++			Panic(0, "Total length of the command to send too large.\n");
++
++		printed += 1; // add null terminator
++		p += printed;
++		space_left -= printed;
+ 	}
+ 	*p = 0;
+ 	m.m.command.nargs = n;
+-- 
+2.49.0
+
diff --git a/0004-attacher.c-prevent-temporary-0666-mode-on-PTYs-to-fi.patch b/0004-attacher.c-prevent-temporary-0666-mode-on-PTYs-to-fi.patch
new file mode 100644
index 0000000..b2ae38d
--- /dev/null
+++ b/0004-attacher.c-prevent-temporary-0666-mode-on-PTYs-to-fi.patch
@@ -0,0 +1,113 @@
+From 5a5383b312b2422689ca0220ac1557885b6ce67d Mon Sep 17 00:00:00 2001
+From: Matthias Gerstner <matthias.gerstner at suse.de>
+Date: Wed, 7 May 2025 10:56:17 +0200
+Subject: [PATCH 4/6] attacher.c: prevent temporary 0666 mode on PTYs to fix
+ CVE-2025-46802
+
+This temporary chmod of the PTY to mode 0666 is most likely a remnant of
+past times, before the PTY file descriptor was passed to the target
+session via the UNIX domain socket.
+
+This chmod() causes a race condition during which any other user in the
+system can open the PTY for reading and writing, and thus allows PTY
+hijacking.
+
+Simply remove this logic completely.
+---
+ attacher.c | 14 --------------
+ screen.c   | 12 ------------
+ screen.h   |  2 --
+ 3 files changed, 28 deletions(-)
+
+diff --git a/attacher.c b/attacher.c
+index 4e1a77e..e5a48b0 100644
+--- a/attacher.c
++++ b/attacher.c
+@@ -127,9 +127,6 @@ int Attach(int how)
+ 		xseteuid(multi_uid);
+ 		xseteuid(own_uid);
+ #endif
+-		if (chmod(attach_tty, 0666))
+-			Panic(errno, "chmod %s", attach_tty);
+-		tty_oldmode = tty_mode;
+ 	}
+ 
+ 	memset((char *)&m, 0, sizeof(Message));
+@@ -279,12 +276,6 @@ int Attach(int how)
+ 			pause();	/* wait for SIGCONT */
+ 		xsignal(SIGCONT, SIG_DFL);
+ 		ContinuePlease = false;
+-		xseteuid(own_uid);
+-		if (tty_oldmode >= 0)
+-			if (chmod(attach_tty, tty_oldmode))
+-				Panic(errno, "chmod %s", attach_tty);
+-		tty_oldmode = -1;
+-		xseteuid(real_uid);
+ 	}
+ 	rflag = 0;
+ 	return 1;
+@@ -334,11 +325,6 @@ void AttacherFinit(int sigsig)
+ 			close(s);
+ 		}
+ 	}
+-	if (tty_oldmode >= 0) {
+-		if (setuid(own_uid))
+-			Panic(errno, "setuid");
+-		chmod(attach_tty, tty_oldmode);
+-	}
+ 	exit(0);
+ }
+ 
+diff --git a/screen.c b/screen.c
+index 728e717..fb61c7f 100644
+--- a/screen.c
++++ b/screen.c
+@@ -145,8 +145,6 @@ bool      hastruecolor = false;
+ 
+ char     *multi;
+ int       multiattach;
+-int       tty_mode;
+-int       tty_oldmode = -1;
+ 
+ char      HostName[MAXSTR];
+ pid_t     MasterPid;
+@@ -766,7 +764,6 @@ int main(int argc, char **argv)
+ 
+ 		/* ttyname implies isatty */
+ 		SetTtyname(true, &st);
+-		tty_mode = (int)st.st_mode & 0777;
+ 
+ 		fl = fcntl(0, F_GETFL, 0);
+ 		if (fl != -1 && (fl & (O_RDWR | O_RDONLY | O_WRONLY)) == O_RDWR)
+@@ -1570,15 +1567,6 @@ void Panic(int err, const char *fmt, ...)
+ 			if (D_userpid)
+ 				Kill(D_userpid, SIG_BYE);
+ 		}
+-	if (tty_oldmode >= 0) {
+-#if defined(HAVE_SETEUID)
+-		if (setuid(own_uid))
+-			xseteuid(own_uid);	/* may be a loop. sigh. */
+-#else
+-		setuid(own_uid);
+-#endif
+-		chmod(attach_tty, tty_oldmode);
+-	}
+ 	eexit(1);
+ }
+ 
+diff --git a/screen.h b/screen.h
+index 308c365..410b4f4 100644
+--- a/screen.h
++++ b/screen.h
+@@ -291,8 +291,6 @@ extern int nversion;
+ extern uid_t own_uid;
+ extern int queryflag;
+ extern int rflag;
+-extern int tty_mode;
+-extern int tty_oldmode;
+ extern pid_t MasterPid;
+ extern int MsgMinWait;
+ extern int MsgWait;
+-- 
+2.49.0
+
diff --git a/0005-Avoid-file-existence-test-information-leaks-to-fix-C.patch b/0005-Avoid-file-existence-test-information-leaks-to-fix-C.patch
new file mode 100644
index 0000000..2aeab06
--- /dev/null
+++ b/0005-Avoid-file-existence-test-information-leaks-to-fix-C.patch
@@ -0,0 +1,130 @@
+From 49473441c17006856268f37249e62a99a7901741 Mon Sep 17 00:00:00 2001
+From: Matthias Gerstner <matthias.gerstner at suse.de>
+Date: Wed, 7 May 2025 11:25:25 +0200
+Subject: [PATCH 5/6] Avoid file existence test information leaks to fix
+ CVE-2025-46804
+
+In setuid-root context the current error messages give away whether
+certain paths not accessible by the real user exist and what type they
+have. To prevent this only output generic error messages in setuid-root
+context.
+
+In some situations, when an error is pertaining a directory and the
+directory is owner by the real user then we can still output more
+detailed diagnostics.
+
+This change can lead to less helpful error messages when Screen is
+install setuid-root. More complex changes would be needed to avoid this
+(e.g.  only open the `SocketPath` with raised privileges when
+multi-attach is requested).
+
+There might still be lingering some code paths that allow such
+information leaks, since `SocketPath` is a global variable that is used
+across the code base. The majority of issues should be caught with this
+fix, however.
+---
+ screen.c | 54 ++++++++++++++++++++++++++++++++++++++++++------------
+ socket.c |  9 +++++++--
+ 2 files changed, 49 insertions(+), 14 deletions(-)
+
+diff --git a/screen.c b/screen.c
+index fb61c7f..eabbdc2 100644
+--- a/screen.c
++++ b/screen.c
+@@ -862,22 +862,47 @@ int main(int argc, char **argv)
+ #endif
+ 	}
+ 
+-	if (stat(SocketPath, &st) == -1)
+-		Panic(errno, "Cannot access %s", SocketPath);
+-	else if (!S_ISDIR(st.st_mode))
+-		Panic(0, "%s is not a directory.", SocketPath);
++	if (stat(SocketPath, &st) == -1) {
++		if (eff_uid == real_uid) {
++			Panic(errno, "Cannot access %s", SocketPath);
++		} else {
++			Panic(0, "Error accessing %s", SocketPath);
++		}
++	}
++	else if (!S_ISDIR(st.st_mode)) {
++		if (eff_uid == real_uid || st.st_uid == real_uid) {
++			Panic(0, "%s is not a directory.", SocketPath);
++		} else {
++			Panic(0, "Error accessing %s", SocketPath);
++		}
++	}
+ 	if (multi) {
+-		if (st.st_uid != multi_uid)
+-			Panic(0, "%s is not the owner of %s.", multi, SocketPath);
++		if (st.st_uid != multi_uid) {
++			if (eff_uid == real_uid || st.st_uid == real_uid) {
++				Panic(0, "%s is not the owner of %s.", multi, SocketPath);
++			} else {
++				Panic(0, "Error accessing %s", SocketPath);
++			}
++		}
+ 	} else {
+ #ifdef SOCKET_DIR	/* if SOCKETDIR is not defined, the socket is in $HOME.
+ 			   in that case it does not make sense to compare uids. */
+-		if (st.st_uid != real_uid)
+-			Panic(0, "You are not the owner of %s.", SocketPath);
++		if (st.st_uid != real_uid) {
++			if (eff_uid == real_uid) {
++				Panic(0, "You are not the owner of %s.", SocketPath);
++			} else {
++				Panic(0, "Error accessing %s", SocketPath);
++			}
++		}
+ #endif
+ 	}
+-	if ((st.st_mode & 0777) != 0700)
+-		Panic(0, "Directory %s must have mode 700.", SocketPath);
++	if ((st.st_mode & 0777) != 0700) {
++		if (eff_uid == real_uid || st.st_uid == real_uid) {
++			Panic(0, "Directory %s must have mode 700.", SocketPath);
++		} else {
++			Panic(0, "Error accessing %s", SocketPath);
++		}
++	}
+ 	if (SocketMatch && strchr(SocketMatch, '/'))
+ 		Panic(0, "Bad session name '%s'", SocketMatch);
+ 	SocketName = SocketPath + strlen(SocketPath) + 1;
+@@ -902,8 +927,13 @@ int main(int argc, char **argv)
+ 			else
+ 				exit(9 + (fo || oth ? 1 : 0) + fo);
+ 		}
+-		if (fo == 0)
+-			Panic(0, "No Sockets found in %s.\n", SocketPath);
++		if (fo == 0) {
++			if (eff_uid == real_uid || st.st_uid == real_uid) {
++				Panic(0, "No Sockets found in %s.\n", SocketPath);
++			} else {
++				Panic(0, "Error accessing %s", SocketPath);
++			}
++		}
+ 		Msg(0, "%d Socket%s in %s.", fo, fo > 1 ? "s" : "", SocketPath);
+ 		eexit(0);
+ 	}
+diff --git a/socket.c b/socket.c
+index 5709a24..d0b361a 100644
+--- a/socket.c
++++ b/socket.c
+@@ -148,8 +148,13 @@ int FindSocket(int *fdp, int *nfoundp, int *notherp, char *match)
+ 	xseteuid(real_uid);
+ 	xsetegid(real_gid);
+ 
+-	if ((dirp = opendir(SocketPath)) == NULL)
+-		Panic(errno, "Cannot opendir %s", SocketPath);
++	if ((dirp = opendir(SocketPath)) == NULL) {
++		if (eff_uid == real_uid) {
++			Panic(errno, "Cannot opendir %s", SocketPath);
++		} else {
++			Panic(0, "Error accessing %s", SocketPath);
++		}
++	}
+ 
+ 	slist = NULL;
+ 	slisttail = &slist;
+-- 
+2.49.0
+
diff --git a/0006-socket.c-don-t-send-signals-with-root-privileges-to-.patch b/0006-socket.c-don-t-send-signals-with-root-privileges-to-.patch
new file mode 100644
index 0000000..b24b2c0
--- /dev/null
+++ b/0006-socket.c-don-t-send-signals-with-root-privileges-to-.patch
@@ -0,0 +1,115 @@
+From d993aacb892ee7aa83c0e21174c8b65b191802d5 Mon Sep 17 00:00:00 2001
+From: Matthias Gerstner <matthias.gerstner at suse.de>
+Date: Wed, 7 May 2025 12:30:39 +0200
+Subject: [PATCH 6/6] socket.c: don't send signals with root privileges to fix
+ CVE-2025-46805
+
+The CheckPid() function was introduced to address CVE-2023-24626, to
+prevent sending SIGCONT and SIGHUP to arbitrary PIDs in the system. This
+fix still suffers from a TOCTOU race condition. The client can replace
+itself by a privileged process, or try to cycle PIDs until a privileged
+process receives the original PID.
+
+To prevent this, always send signals using the real privileges. Keep
+CheckPid() for error diagnostics. If sending the actual signal fails
+later on then there will be no more error reporting.
+
+It seems the original bugfix already introduced a regression when
+attaching to another's user session that is not owned by root. In this
+case the target sessions runs with real uid X, while for sending a
+signal to the `pid` provided by the client real uid Y (or root
+privileges) are required.
+
+This is hard to properly fix without this regression. On Linux pidfds
+could be used to allow safely sending signals to other PIDs as root
+without involving race conditions. In this case the client PID should
+also be obtained via the UNIX domain socket's SO_PEERCRED option,
+though.
+---
+ socket.c | 21 +++++++++++++--------
+ 1 file changed, 13 insertions(+), 8 deletions(-)
+
+diff --git a/socket.c b/socket.c
+index d0b361a..c715519 100644
+--- a/socket.c
++++ b/socket.c
+@@ -91,6 +91,11 @@ static void AskPassword(Message *);
+ static bool CheckPassword(const char *password);
+ static void PasswordProcessInput(char *, size_t);
+ 
++static void KillUnpriv(pid_t pid, int sig) {
++	UserContext();
++	UserReturn(kill(pid, sig));
++}
++
+ #define SOCKMODE (S_IWRITE | S_IREAD | (displays ? S_IEXEC : 0) | (multi ? 1 : 0))
+ 
+ /*
+@@ -611,7 +616,7 @@ static int CreateTempDisplay(Message *m, int recvfd, Window *win)
+ 				Msg(errno, "Could not perform necessary sanity "
+ 					   "checks on pts device.");
+ 				close(i);
+-				Kill(pid, SIG_BYE);
++				KillUnpriv(pid, SIG_BYE);
+ 				return -1;
+ 			}
+ 			if (strcmp(ttyname_in_ns, m->m_tty)) {
+@@ -620,7 +625,7 @@ static int CreateTempDisplay(Message *m, int recvfd, Window *win)
+ 				    ttyname_in_ns,
+ 				    m->m_tty[0] != '\0' ? m->m_tty : "(null)");
+ 				close(i);
+-				Kill(pid, SIG_BYE);
++				KillUnpriv(pid, SIG_BYE);
+ 				return -1;
+ 			}
+ 			/* m->m_tty so far contains the actual name of the pts
+@@ -638,24 +643,24 @@ static int CreateTempDisplay(Message *m, int recvfd, Window *win)
+ 			    "Attach: passed fd does not match tty: %s - %s!",
+ 			    m->m_tty, myttyname ? myttyname : "NULL");
+ 			close(i);
+-			Kill(pid, SIG_BYE);
++			KillUnpriv(pid, SIG_BYE);
+ 			return -1;
+ 		}
+ 	} else if ((i = secopen(m->m_tty, O_RDWR | O_NONBLOCK, 0)) < 0) {
+ 		Msg(errno, "Attach: Could not open %s!", m->m_tty);
+-		Kill(pid, SIG_BYE);
++		KillUnpriv(pid, SIG_BYE);
+ 		return -1;
+ 	}
+ 
+ 	if (attach)
+-		Kill(pid, SIGCONT);
++		KillUnpriv(pid, SIGCONT);
+ 
+ 	if (attach) {
+ 		if (display || win) {
+ 			int unused_result = write(i, "Attaching from inside of screen?\n", 33);
+ 			(void)unused_result; /* unused */
+ 			close(i);
+-			Kill(pid, SIG_BYE);
++			KillUnpriv(pid, SIG_BYE);
+ 			Msg(0, "Attach msg ignored: coming from inside.");
+ 			return -1;
+ 		}
+@@ -678,7 +683,7 @@ static int CreateTempDisplay(Message *m, int recvfd, Window *win)
+ 		(void)unused_result; /* unused */
+ 		close(i);
+ 		Msg(0, "Attach: could not make display for user %s", user);
+-		Kill(pid, SIG_BYE);
++		KillUnpriv(pid, SIG_BYE);
+ 		return -1;
+ 	}
+ 	if (attach) {
+@@ -884,7 +889,7 @@ void ReceiveMsg(void)
+ 				Msg(0, "Query attempt with bad pid(%d)!", m.m.command.apid);
+ 			}
+ 			else {
+-				Kill(m.m.command.apid, (queryflag >= 0) ? SIGCONT : SIG_BYE);	/* Send SIG_BYE if an error happened */
++				KillUnpriv(m.m.command.apid, (queryflag >= 0) ? SIGCONT : SIG_BYE);	/* Send SIG_BYE if an error happened */
+ 				queryflag = -1;
+ 			}
+ 		}
+-- 
+2.49.0
+
================================================================

---- gitweb:

http://git.pld-linux.org/gitweb.cgi/packages/screen.git/commitdiff/06b56d959517296e2d87a47310d0cf8318096d5e



More information about the pld-cvs-commit mailing list