commit:     45720db27dbedc63a396faa3e6157765458e24b3
Author:     Hank Leininger <hlein <AT> korelogic <DOT> com>
AuthorDate: Sun May 18 19:46:06 2025 +0000
Commit:     Sam James <sam <AT> gentoo <DOT> org>
CommitDate: Sun Jun  1 04:55:08 2025 +0000
URL:        https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=45720db2

app-misc/screen: security fixes for the screen-v4 branch

Signed-off-by: Hank Leininger <hlein <AT> korelogic.com>
Bug: https://bugs.gentoo.org/955907
Part-of: https://github.com/gentoo/gentoo/pull/42149
Closes: https://github.com/gentoo/gentoo/pull/42149
Signed-off-by: Sam James <sam <AT> gentoo.org>

 .../files/screen-4.9.1-fix_CVE-2025-46802.patch    | 141 +++++++++++++++++++
 .../files/screen-4.9.1-fix_CVE-2025-46804.patch    | 126 +++++++++++++++++
 .../files/screen-4.9.1-fix_CVE-2025-46805.patch    | 119 ++++++++++++++++
 app-misc/screen/screen-4.9.1-r2.ebuild             | 152 +++++++++++++++++++++
 4 files changed, 538 insertions(+)

diff --git a/app-misc/screen/files/screen-4.9.1-fix_CVE-2025-46802.patch 
b/app-misc/screen/files/screen-4.9.1-fix_CVE-2025-46802.patch
new file mode 100644
index 000000000000..c43380ce0de6
--- /dev/null
+++ b/app-misc/screen/files/screen-4.9.1-fix_CVE-2025-46802.patch
@@ -0,0 +1,141 @@
+Adapted from 
https://git.savannah.gnu.org/cgit/screen.git/patch/?id=049b26b22e197ba3be9c46e5c193032e01a4724a
+
+From 049b26b22e197ba3be9c46e5c193032e01a4724a Mon Sep 17 00:00:00 2001
+From: Matthias Gerstner <[email protected]>
+Date: Mon, 12 May 2025 15:15:38 +0200
+Subject: fix CVE-2025-46802: attacher.c - prevent temporary 0666 mode on PTYs
+
+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 | 27 ---------------------------
+ screen.c   | 19 -------------------
+ 2 files changed, 46 deletions(-)
+
+diff --git a/attacher.c b/attacher.c
+index c35ae7a..16b151e 100644
+--- a/attacher.c
++++ b/attacher.c
+@@ -73,7 +73,6 @@ extern int MasterPid, attach_fd;
+ #ifdef MULTIUSER
+ extern char *multi;
+ extern int multiattach, multi_uid, own_uid;
+-extern int tty_mode, tty_oldmode;
+ # ifndef USE_SETEUID
+ static int multipipe[2];
+ # endif
+@@ -160,9 +159,6 @@ int how;
+ 
+       if (pipe(multipipe))
+       Panic(errno, "pipe");
+-      if (chmod(attach_tty, 0666))
+-      Panic(errno, "chmod %s", attach_tty);
+-      tty_oldmode = tty_mode;
+       eff_uid = -1;   /* make UserContext fork */
+       real_uid = multi_uid;
+       if ((ret = UserContext()) <= 0)
+@@ -174,11 +170,6 @@ int how;
+           Panic(errno, "UserContext");
+         close(multipipe[1]);
+         read(multipipe[0], &dummy, 1);
+-        if (tty_oldmode >= 0)
+-          {
+-            chmod(attach_tty, tty_oldmode);
+-            tty_oldmode = -1;
+-          }
+         ret = UserStatus();
+ #ifdef LOCK
+         if (ret == SIG_LOCK)
+@@ -224,9 +215,6 @@ int how;
+       xseteuid(multi_uid);
+       xseteuid(own_uid);
+ #endif
+-      if (chmod(attach_tty, 0666))
+-      Panic(errno, "chmod %s", attach_tty);
+-      tty_oldmode = tty_mode;
+     }
+ # endif /* USE_SETEUID */
+ #endif /* MULTIUSER */
+@@ -423,13 +411,6 @@ int how;
+       ContinuePlease = 0;
+ # ifndef USE_SETEUID
+       close(multipipe[1]);
+-# else
+-      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);
+ # endif
+     }
+ #endif
+@@ -505,14 +486,6 @@ AttacherFinit SIGDEFARG
+         close(s);
+       }
+     }
+-#ifdef MULTIUSER
+-  if (tty_oldmode >= 0)
+-    {
+-      if (setuid(own_uid))
+-        Panic(errno, "setuid");
+-      chmod(attach_tty, tty_oldmode);
+-    }
+-#endif
+   exit(0);
+   SIGRETURN;
+ }
+diff --git a/screen.c b/screen.c
+index 7653cd1..1a23e1a 100644
+--- a/screen.c
++++ b/screen.c
+@@ -230,8 +230,6 @@ char *multi_home;
+ int multi_uid;
+ int own_uid;
+ int multiattach;
+-int tty_mode;
+-int tty_oldmode = -1;
+ #endif
+ 
+ char HostName[MAXSTR];
+@@ -1009,9 +1007,6 @@ int main(int ac, char** av)
+ 
+     /* ttyname implies isatty */
+     SetTtyname(true, &st);
+-#ifdef MULTIUSER
+-    tty_mode = (int)st.st_mode & 0777;
+-#endif
+ 
+     fl = fcntl(0, F_GETFL, 0);
+     if (fl != -1 && (fl & (O_RDWR|O_RDONLY|O_WRONLY)) == O_RDWR)
+@@ -2170,20 +2165,6 @@ DEFINE_VARARGS_FN(Panic)
+       if (D_userpid)
+         Kill(D_userpid, SIG_BYE);
+     }
+-#ifdef MULTIUSER
+-  if (tty_oldmode >= 0) {
+-
+-# ifdef USE_SETEUID
+-    if (setuid(own_uid))
+-      xseteuid(own_uid);      /* may be a loop. sigh. */
+-# else
+-      setuid(own_uid);
+-# endif
+-
+-    debug1("Panic: changing back modes from %s\n", attach_tty);
+-    chmod(attach_tty, tty_oldmode);
+-  }
+-#endif
+   eexit(1);
+ }
+ 
+-- 
+cgit v1.1
+

diff --git a/app-misc/screen/files/screen-4.9.1-fix_CVE-2025-46804.patch 
b/app-misc/screen/files/screen-4.9.1-fix_CVE-2025-46804.patch
new file mode 100644
index 000000000000..6d013db44272
--- /dev/null
+++ b/app-misc/screen/files/screen-4.9.1-fix_CVE-2025-46804.patch
@@ -0,0 +1,126 @@
+Adapted from 
https://git.savannah.gnu.org/cgit/screen.git/patch/?id=e0eef5aac453fa98a2664416a56c50ad1d00cb30
+
+From e0eef5aac453fa98a2664416a56c50ad1d00cb30 Mon Sep 17 00:00:00 2001
+From: Matthias Gerstner <[email protected]>
+Date: Mon, 12 May 2025 15:26:11 +0200
+Subject: fix CVE-2025-46804: avoid file existence test information leaks
+
+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 | 45 ++++++++++++++++++++++++++++++++++-----------
+ socket.c |  9 +++++++--
+ 2 files changed, 41 insertions(+), 13 deletions(-)
+
+diff --git a/screen.c b/screen.c
+index 1a23e1a..6eec151 100644
+--- a/screen.c
++++ b/screen.c
+@@ -1122,15 +1122,28 @@ int main(int ac, char** av)
+ #endif
+   }
+ 
+-  if (stat(SockPath, &st) == -1)
+-    Panic(errno, "Cannot access %s", SockPath);
+-  else
+-    if (!S_ISDIR(st.st_mode))
++  if (stat(SockPath, &st) == -1) {
++    if (eff_uid == real_uid) {
++      Panic(errno, "Cannot access %s", SockPath);
++    } else {
++      Panic(0, "Error accessing %s", SockPath);
++    }
++  } else if (!S_ISDIR(st.st_mode)) {
++    if (eff_uid == real_uid || st.st_uid == real_uid) {
+       Panic(0, "%s is not a directory.", SockPath);
++    } else {
++      Panic(0, "Error accessing %s", SockPath);
++    }
++  }
+ #ifdef MULTIUSER
+   if (multi) {
+-    if ((int)st.st_uid != multi_uid)
+-      Panic(0, "%s is not the owner of %s.", multi, SockPath);
++    if ((int)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, SockPath);
++      } else {
++        Panic(0, "Error accessing %s", SockPath);
++      }
++    }
+   }
+   else
+ #endif
+@@ -1144,9 +1157,13 @@ int main(int ac, char** av)
+       Panic(0, "You are not the owner of %s.", SockPath);
+ #endif
+   }
+-
+-  if ((st.st_mode & 0777) != 0700)
+-    Panic(0, "Directory %s must have mode 700.", SockPath);
++  if ((st.st_mode & 0777) != 0700) {
++    if (eff_uid == real_uid || st.st_uid == real_uid) {
++      Panic(0, "Directory %s must have mode 700.", SockPath);
++    } else {
++      Panic(0, "Error accessing %s", SockPath);
++    }
++  }
+   if (SockMatch && index(SockMatch, '/'))
+     Panic(0, "Bad session name '%s'", SockMatch);
+   SockName = SockPath + strlen(SockPath) + 1;
+@@ -1184,8 +1201,14 @@ int main(int ac, char** av)
+       else
+         exit(9 + (fo || oth ? 1 : 0) + fo);
+     }
+-    if (fo == 0)
+-      Panic(0, "No Sockets found in %s.\n", SockPath);
++    if (fo == 0) {
++      if (eff_uid == real_uid || st.st_uid == real_uid) {
++        Panic(0, "No Sockets found in %s.\n", SockPath);
++      } else {
++        Panic(0, "Error accessing %s", SockPath);
++      }
++    }
++
+     Msg(0, "%d Socket%s in %s.", fo, fo > 1 ? "s" : "", SockPath);
+     eexit(0);
+   }
+diff --git a/socket.c b/socket.c
+index 54d8cb8..6c3502f 100644
+--- a/socket.c
++++ b/socket.c
+@@ -169,8 +169,13 @@ bool *is_sock;
+   xsetegid(real_gid);
+ #endif
+ 
+-  if ((dirp = opendir(SockPath)) == 0)
+-    Panic(errno, "Cannot opendir %s", SockPath);
++  if ((dirp = opendir(SockPath)) == 0) {
++    if (eff_uid == real_uid) {
++      Panic(errno, "Cannot opendir %s", SockPath);
++    } else {
++      Panic(0, "Error accessing %s", SockPath);
++    }
++  }
+ 
+   slist = 0;
+   slisttail = &slist;
+-- 
+cgit v1.1
+

diff --git a/app-misc/screen/files/screen-4.9.1-fix_CVE-2025-46805.patch 
b/app-misc/screen/files/screen-4.9.1-fix_CVE-2025-46805.patch
new file mode 100644
index 000000000000..a7bb6d3ae74b
--- /dev/null
+++ b/app-misc/screen/files/screen-4.9.1-fix_CVE-2025-46805.patch
@@ -0,0 +1,119 @@
+Adapted from 
https://git.savannah.gnu.org/cgit/screen.git/patch/?id=161f85b98b7e1d5e4893aeed20f4cdb5e3dfaaa4
+
+From 161f85b98b7e1d5e4893aeed20f4cdb5e3dfaaa4 Mon Sep 17 00:00:00 2001
+From: Matthias Gerstner <[email protected]>
+Date: Mon, 12 May 2025 15:38:19 +0200
+Subject: fix CVE-2025-46805: socket.c - don't send signals with root
+ privileges
+
+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 6c3502f..d6621fa 100644
+--- a/socket.c
++++ b/socket.c
+@@ -831,6 +831,11 @@ int pid;
+   return UserStatus();
+ }
+ 
++static void KillUnpriv(pid_t pid, int sig) {
++    UserContext();
++    UserReturn(kill(pid, sig));
++}
++
+ #ifdef hpux
+ /*
+  * From: "F. K. Bruner" <[email protected]>
+@@ -916,14 +921,14 @@ struct win *wi;
+             {
+             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))
+             {
+             Msg(errno, "Attach: passed fd does not match tty: %s - %s!", 
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 device in the
+@@ -940,19 +945,19 @@ struct win *wi;
+       {
+         Msg(errno, "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;
+     }
+ #ifdef MULTIUSER
+   if (attach)
+-    Kill(pid, SIGCONT);
++    KillUnpriv(pid, SIGCONT);
+ #endif
+ 
+ #if defined(ultrix) || defined(pyr) || defined(NeXT)
+@@ -965,7 +970,7 @@ struct win *wi;
+       {
+         write(i, "Attaching from inside of screen?\n", 33);
+         close(i);
+-        Kill(pid, SIG_BYE);
++        KillUnpriv(pid, SIG_BYE);
+         Msg(0, "Attach msg ignored: coming from inside.");
+         return -1;
+       }
+@@ -976,7 +981,7 @@ struct win *wi;
+         {
+             write(i, "Access to session denied.\n", 26);
+             close(i);
+-            Kill(pid, SIG_BYE);
++            KillUnpriv(pid, SIG_BYE);
+             Msg(0, "Attach: access denied for user %s.", user);
+             return -1;
+         }
+@@ -1294,7 +1299,7 @@ ReceiveMsg()
+             Msg(0, "Query attempt with bad pid(%d)!", m.m.command.apid);
+           }
+           else {
+-            Kill(m.m.command.apid,
++            KillUnpriv(m.m.command.apid,
+                (queryflag >= 0)
+                    ? SIGCONT
+                    : SIG_BYE); /* Send SIG_BYE if an error happened */
+-- 
+cgit v1.1
+

diff --git a/app-misc/screen/screen-4.9.1-r2.ebuild 
b/app-misc/screen/screen-4.9.1-r2.ebuild
new file mode 100644
index 000000000000..84ee80a20d3e
--- /dev/null
+++ b/app-misc/screen/screen-4.9.1-r2.ebuild
@@ -0,0 +1,152 @@
+# Copyright 1999-2025 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI=8
+
+inherit autotools flag-o-matic pam tmpfiles
+
+DESCRIPTION="screen manager with VT100/ANSI terminal emulation"
+HOMEPAGE="https://www.gnu.org/software/screen/";
+
+if [[ ${PV} != 9999 ]] ; then
+       SRC_URI="mirror://gnu/${PN}/${P}.tar.gz"
+       KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~loong ~m68k ~mips ~ppc 
~ppc64 ~riscv ~s390 ~sparc ~x86 ~amd64-linux ~x86-linux ~arm64-macos ~ppc-macos 
~x64-macos ~x64-solaris"
+else
+       inherit git-r3
+       EGIT_REPO_URI="https://git.savannah.gnu.org/git/screen.git";
+       EGIT_CHECKOUT_DIR="${WORKDIR}/${P}" # needed for setting S later on
+       S="${WORKDIR}"/${P}/src
+fi
+
+LICENSE="GPL-3+"
+SLOT="0"
+IUSE="debug nethack pam selinux multiuser"
+
+DEPEND=">=sys-libs/ncurses-5.2:=
+       virtual/libcrypt:=
+       pam? ( sys-libs/pam )"
+RDEPEND="${DEPEND}
+       acct-group/utmp
+       selinux? ( sec-policy/selinux-screen )"
+BDEPEND="sys-apps/texinfo"
+
+PATCHES=(
+       # Don't use utempter even if it is found on the system.
+       "${FILESDIR}"/${PN}-4.3.0-no-utempter.patch
+       "${FILESDIR}"/${PN}-4.9.1-utmp-exit.patch
+       "${FILESDIR}"/${PN}-4.9.1-add-missing-pty.h-header.patch
+       "${FILESDIR}"/${PN}-4.9.1-fix_CVE-2025-46802.patch
+       "${FILESDIR}"/${PN}-4.9.1-fix_CVE-2025-46804.patch
+       "${FILESDIR}"/${PN}-4.9.1-fix_CVE-2025-46805.patch
+)
+
+src_prepare() {
+       default
+
+       # sched.h is a system header and causes problems with some C libraries
+       mv sched.h _sched.h || die
+       sed -i '/include/ s:sched.h:_sched.h:' screen.h || die
+
+       # Fix manpage
+       sed -i \
+               -e "s:/usr/local/etc/screenrc:${EPREFIX}/etc/screenrc:g" \
+               -e "s:/usr/local/screens:${EPREFIX}/tmp/screen:g" \
+               -e "s:/local/etc/screenrc:${EPREFIX}/etc/screenrc:g" \
+               -e "s:/etc/utmp:${EPREFIX}/var/run/utmp:g" \
+               -e "s:/local/screens/S\\\-:${EPREFIX}/tmp/screen/S\\\-:g" \
+               doc/screen.1 || die
+
+       if [[ ${CHOST} == *-darwin* ]] || use elibc_musl; then
+               sed -i -e '/^#define UTMPOK/s/define/undef/' acconfig.h || die
+       fi
+
+       # disable musl dummy headers for utmp[x]
+       use elibc_musl && append-cppflags "-D_UTMP_H -D_UTMPX_H"
+
+       # reconfigure
+       eautoreconf
+}
+
+src_configure() {
+       # bug #944429 (revisit this on >= 5.0.0)
+       append-cflags -std=gnu17
+       append-lfs-flags
+       append-cppflags "-DMAXWIN=${MAX_SCREEN_WINDOWS:-100}"
+
+       if [[ ${CHOST} == *-solaris* ]]; then
+               # enable msg_header by upping the feature standard compatible
+               # with c99 mode
+               append-cppflags -D_XOPEN_SOURCE=600
+       fi
+
+       use nethack || append-cppflags "-DNONETHACK"
+       use debug && append-cppflags "-DDEBUG"
+
+       local myeconfargs=(
+               --with-socket-dir="${EPREFIX}/tmp/${PN}"
+               --with-sys-screenrc="${EPREFIX}/etc/screenrc"
+               --with-pty-mode=0620
+               --with-pty-group=5
+               --enable-rxvt_osc
+               --enable-telnet
+               --enable-colors256
+               $(use_enable pam)
+       )
+       econf "${myeconfargs[@]}"
+}
+
+src_compile() {
+       LC_ALL=POSIX emake comm.h term.h
+       emake osdef.h
+
+       emake -C doc screen.info
+       default
+}
+
+src_install() {
+       local DOCS=(
+               README ChangeLog INSTALL TODO NEWS* patchlevel.h
+               doc/{FAQ,README.DOTSCREEN,fdpat.ps,window_to_display.ps}
+       )
+
+       emake DESTDIR="${D}" SCREEN="${P}" install
+
+       local tmpfiles_perms tmpfiles_group
+
+       if use multiuser || use prefix ; then
+               fperms 4755 /usr/bin/${P}
+               tmpfiles_perms="0755"
+               tmpfiles_group="root"
+       else
+               fowners root:utmp /usr/bin/${P}
+               fperms 2755 /usr/bin/${P}
+               tmpfiles_perms="0775"
+               tmpfiles_group="utmp"
+       fi
+
+       newtmpfiles - screen.conf <<<"d /tmp/screen ${tmpfiles_perms} root 
${tmpfiles_group}"
+
+       insinto /usr/share/${PN}
+       doins terminfo/{screencap,screeninfo.src}
+
+       insinto /etc
+       doins "${FILESDIR}"/screenrc
+
+       if use pam; then
+               pamd_mimic_system screen auth
+       fi
+
+       dodoc "${DOCS[@]}"
+}
+
+pkg_postinst() {
+       if [[ -z ${REPLACING_VERSIONS} ]]; then
+               elog "Some dangerous key bindings have been removed or changed 
to more safe values."
+               elog "We enable some xterm hacks in our default screenrc, which 
might break some"
+               elog "applications. Please check /etc/screenrc for information 
on these changes."
+       fi
+
+       tmpfiles_process screen.conf
+
+       ewarn "This revision changes the screen socket location to 
${EROOT}/tmp/${PN}"
+}

Reply via email to