From 5c1a76a992e563632fb90179e56afaf3027f55de Mon Sep 17 00:00:00 2001 From: RHEL Packaging Agent Date: Wed, 2 Sep 2026 06:46:13 +0000 Subject: [PATCH] Fix CVE-2026-72694: symlink-following chown in mrtg daemon mode Backport fix for CVE-2026-72694 from Fedora rawhide. The patch addresses a symlink-following chown vulnerability (CWE-59) in mrtg's daemon mode pid file handling. When mrtg is started as root with --daemon --user, the pid file creation and chown operations could be exploited via symlinks. The fix makes create_pid() refuse symlinks, uses O_WRONLY|O_CREAT|O_EXCL for atomic file creation, and uses fchown on the open file handle instead of path-based chown. CVE: CVE-2026-72694 Upstream patches: - https://src.fedoraproject.org/rpms/mrtg/raw/rawhide/f/mrtg-2.17.10-CVE-2026-72694.patch Resolves: RHEL-236053 This commit was backported by Ymir, a Red Hat Enterprise Linux software maintenance AI agent. Assisted-by: Ymir --- mrtg-2.17.10-CVE-2026-72694.patch | 113 ++++++++++++++++++++++++++++++ mrtg.spec | 10 ++- 2 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 mrtg-2.17.10-CVE-2026-72694.patch diff --git a/mrtg-2.17.10-CVE-2026-72694.patch b/mrtg-2.17.10-CVE-2026-72694.patch new file mode 100644 index 0000000..dd37da1 --- /dev/null +++ b/mrtg-2.17.10-CVE-2026-72694.patch @@ -0,0 +1,113 @@ +From 416106e719c1098d2615189d0710b94864eb08ec Mon Sep 17 00:00:00 2001 +From: Tobias Oetiker +Date: Tue, 30 Jun 2026 23:34:40 +0200 +Subject: [PATCH] Fix symlink-following chown of pid file in daemon mode + (CWE-59) (#123) + +When mrtg is started as root in daemon mode (--daemon --user), it +created the pid file and chown'ed it to the target user *before* +dropping privileges. Both create_pid()'s `-e`/`open(">...")` and the +subsequent `chown` follow symlinks, so a local attacker who can +pre-place a symlink at the pid path (e.g. a pid file in a writable +directory) could make root chown an arbitrary existing file to the +daemon user, or create a root-owned file at an attacker-chosen path. + +Rather than reorder the privilege drop (which would break the common +case of a root-owned pid directory, where the unprivileged daemon +cannot create the file itself), keep creating the file while +privileged but do it safely: + +- create_pid() refuses symlinks and creates the file with + O_WRONLY|O_CREAT|O_EXCL, closing the symlink-follow / TOCTOU window. +- It chowns the open filehandle (fchown) instead of the path, so the + ownership change cannot be redirected through a swapped-in symlink. + The caller no longer does a separate path-based chown. +- demonize_me()'s later pid write refuses symlinks too. + +Reported by Aisle Research via Vitezslav Crhonek. + +Co-authored-by: Claude Opus 4.8 +--- + bin/mrtg | 8 +++++--- + lib/mrtg2/MRTG_lib.pm | 32 ++++++++++++++++++++++++++------ + 2 files changed, 31 insertions(+), 9 deletions(-) + +diff --git a/bin/mrtg b/bin/mrtg +index ba520ca..3a4efe5 100755 +--- a/bin/mrtg ++++ b/bin/mrtg +@@ -252,9 +252,11 @@ sub main { + + # Run as a daemon, specified on command line (required for FHS compliant daemon) + if (defined $opts{"daemon"}) { +- # Create a pidfile, then chown it so we can use it once we change user +- &create_pid($pidfile); +- chown $uid, $gid, $pidfile; ++ # Create the pidfile securely and, while still privileged, hand it to ++ # the user we are about to become so the daemon can update it later. ++ # create_pid refuses symlinks and chowns the open handle (not the path), ++ # so a hostile pid path cannot be used to chown an arbitrary file. ++ &create_pid($pidfile, $uid, $gid); + } + + ($(,$)) = ($gid,$gid) ; +diff --git a/lib/mrtg2/MRTG_lib.pm b/lib/mrtg2/MRTG_lib.pm +index 1c12f6c..6359b01 100644 +--- a/lib/mrtg2/MRTG_lib.pm ++++ b/lib/mrtg2/MRTG_lib.pm +@@ -16,6 +16,7 @@ package MRTG_lib; + + require 5.005; + use strict; ++use Fcntl qw(O_WRONLY O_CREAT O_EXCL); + use vars qw($OS $SL $PS @EXPORT @ISA $VERSION %timestrpospattern); + + +@@ -1233,14 +1234,31 @@ sub expistr ($) { + return "$wday, $mday $month ".($year+1900)." $hour:$min:$sec GMT"; + } + +-sub create_pid ($) { +- my $pidfile = shift; ++sub create_pid ($;$$) { ++ my ($pidfile, $uid, $gid) = @_; + return if ($OS eq 'NT' ); ++ ++ # Security: refuse to operate on a symlink. When mrtg is started as root ++ # in daemon mode with a writable pid path, an attacker who pre-places a ++ # symlink here could otherwise make us create or chown an arbitrary file ++ # (CWE-59). A plain stat/-e on the path would follow the link, so check ++ # the link itself first. ++ if (-l $pidfile) { ++ warn "refusing to use pid file $pidfile: it is a symbolic link\n"; ++ return; ++ } + return if -e $pidfile; +- if ( open(PIDFILE,">$pidfile")) { +- close PIDFILE; ++ ++ # O_CREAT|O_EXCL creates the file atomically and fails if anything ++ # (including a symlink that was raced in after the check above) already ++ # exists at the path, closing the symlink-follow / TOCTOU window. ++ if ( sysopen(my $fh, $pidfile, O_WRONLY|O_CREAT|O_EXCL, 0644) ) { ++ # chown the open handle (fchown) rather than the path, so the ++ # ownership change cannot be redirected through a swapped-in symlink. ++ chown $uid, $gid, $fh if defined $uid and defined $gid; ++ close $fh; + } else { +- warn "cannot write to $pidfile: $!\n"; ++ warn "cannot create pid file $pidfile: $!\n"; + } + } + +@@ -1286,7 +1304,9 @@ sub demonize_me ($) { + } else { + if (defined $pidfile){ + $main::Cleanfile3 = $pidfile; +- if (open(PIDFILE,">$pidfile")) { ++ if (-l $pidfile) { ++ warn "refusing to write pid file $pidfile: it is a symbolic link\n"; ++ } elsif (open(PIDFILE,">$pidfile")) { + print PIDFILE "$$\n"; + close PIDFILE; + } else { diff --git a/mrtg.spec b/mrtg.spec index 994bc6d..8ecd186 100644 --- a/mrtg.spec +++ b/mrtg.spec @@ -12,7 +12,7 @@ Summary: Multi Router Traffic Grapher Name: mrtg Version: 2.17.10 -Release: 12%{?dist} +Release: 13%{?dist} URL: http://oss.oetiker.ch/mrtg/ Source0: http://oss.oetiker.ch/mrtg/pub/mrtg-%{version}.tar.gz Source1: http://oss.oetiker.ch/mrtg/pub/mrtg-%{version}.tar.gz.md5 @@ -40,6 +40,8 @@ Patch1: mrtg-2.17.2-socket6-fix.patch # Patch2: some devices return 2**32-2 on ifSpeed (e. g. IBM FibreChannel switches) Patch2: mrtg-2.17.4-cfgmaker-ifhighspeed.patch Patch3: mrtg-configure-c99.patch +# https://github.com/oetiker/mrtg/commit/30e19216bfadc0148f347cb0a42fd5e2016e6269 +Patch4: mrtg-2.17.10-CVE-2026-72694.patch License: GPL-2.0-or-later Requires(post): systemd-units Requires(preun): systemd-units @@ -86,6 +88,7 @@ Custom SELinux policy module %patch -P 1 -p1 -b .socket6 %patch -P 2 -p1 -b .ifhighspeed %patch -P 3 -p1 -b .c99 +%patch -P 4 -p1 -b .CVE-2026-72694 for i in doc/mrtg-forum.1 doc/mrtg-squid.1 CHANGES; do iconv -f iso-8859-1 -t utf-8 < "$i" > "${i}_" @@ -212,6 +215,11 @@ fi %endif %changelog +* Wed Sep 02 2026 RHEL Packaging Agent - 2.17.10-13 +- Fix symlink-following chown vulnerability in daemon mode pid file + handling (CVE-2026-72694) + Resolves: RHEL-236053 + * Mon Jan 26 2026 Vitezslav Crhonek - 2.17.10-12 - Add support for Image Mode Resolves: RHEL-142231