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}" +}
