public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
* [rpms/tar] f44: Backport upstream patches for CVE-2026-18477
@ 2026-09-07 17:57 Pavel Cahyna
  0 siblings, 0 replies; only message in thread
From: Pavel Cahyna @ 2026-09-07 17:57 UTC (permalink / raw)
  To: git-commits

            A new commit has been pushed.

            Repo   : rpms/tar
            Branch : f44
            Commit : 91dab42dfb53efc3273e0a356357b55f3bbdf58f
            Author : Pavel Cahyna <pcahyna@redhat.com>
            Date   : 2026-09-07T17:22:22+02:00
            Stats  : +450/-0 in 2 file(s)
            URL    : https://src.fedoraproject.org/rpms/tar/c/91dab42dfb53efc3273e0a356357b55f3bbdf58f?branch=f44

            Log:
            Backport upstream patches for CVE-2026-18477

This fixes a bug where incremental restore with cyclic renames
between backups may create a temporary directory at an
archive-controlled path outside the extraction tree relative to CWD (or
absolute if starting with /).

The fix for CVE-2025-45582 already prevents exploiting this problem, so
it is more a correctness and hardening change.

Resolves: CVE-2026-18477
Resolves: fedora#2509846

---
diff --git a/tar-1.35-CVE-2026-18477.patch b/tar-1.35-CVE-2026-18477.patch
new file mode 100644
index 0000000..32d2ea8
--- /dev/null
+++ b/tar-1.35-CVE-2026-18477.patch
@@ -0,0 +1,445 @@
+diff --git a/NEWS b/NEWS
+index 45fedbf5..f4621d7f 100644
+--- a/NEWS
++++ b/NEWS
+@@ -13,6 +13,10 @@ version 1.35.90 (git)
+ ** When extracting, tar no longer follows symbolic links to targets
+    outside the working directory.
+ 
++** When extracting from an incremental dump, tar now strips leading '/'
++   from names of temporary directories specified by 'X' entries,
++   unless --absolute-names (-P) is used.
++
+ ** tar no longer fails merely if an extraction directory is unreadable
+    on Linux kernels.
+ 
+diff --git a/THANKS b/THANKS
+index b9e4ce54..f12d98c7 100644
+--- a/THANKS
++++ b/THANKS
+@@ -330,6 +330,7 @@ Manuel Munier		Manuel.Munier@loria.fr
+ Marc Boucher		marc@cam.org
+ Marc Ewing		marc@redhat.com
+ Marcin Matuszewski	marcin@frodo.nask.org.pl
++Marcin Wyczechowski	mwyczechowski@afine.com
+ Marcus Daniels		marcus@sysc.pdx.edu
+ Mark Bynum		bynum@cennas.nhmfl.gov
+ Mark Clements		mpc@mbsmm.com
+@@ -367,6 +368,7 @@ Michael Schmidt		michael@muc.de
+ Michael Schwingen	m.schwingen@stochastik.rwth-aachen.de
+ Michael Smolsky		fnsiguc@astro.weizmann.ac.il
+ Michal Žejdl		zejdl@suas.cz
++Michał Majchrowicz	mmajchrowicz@afine.com
+ Mike Muuss		mike@brl.mil
+ Mike Nolan		nolan@lpl.arizona.edu
+ Mike Rogers		mike@demon.net
+diff --git a/lib/Makefile.am b/lib/Makefile.am
+index 38645b2c..45152c49 100644
+--- a/lib/Makefile.am
++++ b/lib/Makefile.am
+@@ -30,6 +30,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/gnu -I../ -I../gnu
+ AM_CFLAGS = $(GNULIB_WARN_CFLAGS) $(WERROR_CFLAGS)
+ 
+ noinst_HEADERS = \
++ mkdtempat.h\
+  paxlib.h\
+  rmt.h\
+  system.h\
+@@ -38,6 +39,7 @@ noinst_HEADERS = \
+  xattr-at.h
+ 
+ libtar_a_SOURCES = \
++  mkdtempat.c\
+   paxerror.c paxexit-status.c paxlib.h paxnames.c \
+   rtapelib.c \
+   rmt.h \
+diff --git a/lib/mkdtempat.c b/lib/mkdtempat.c
+new file mode 100644
+index 00000000..e35b9bba
+--- /dev/null
++++ b/lib/mkdtempat.c
+@@ -0,0 +1,45 @@
++/* Copyright 2026 Free Software Foundation, Inc.
++
++   This program is free software; you can redistribute it and/or modify it
++   under the terms of the GNU General Public License as published by the
++   Free Software Foundation; either version 3 of the License, or (at your
++   option) any later version.
++
++   This program is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++   GNU General Public License for more details.
++
++   You should have received a copy of the GNU General Public License along
++   with this program. If not, see <http://www.gnu.org/licenses/>.
++
++   Written by Paul Eggert.  */
++
++#include <config.h>
++
++#include "mkdtempat.h"
++
++#include <tempname.h>
++
++#include <stddef.h>
++#include <sys/stat.h>
++
++static int
++try_dir (char *tmpl, void *flags)
++{
++  int *pdirfd = flags;
++  return mkdirat (*pdirfd, tmpl, S_IRUSR | S_IWUSR | S_IXUSR);
++}
++
++/* Relative to the directory DIRFD if XTEMPLATE is relative,
++   generate a unique temporary directory from XTEMPLATE.
++   The last six characters of XTEMPLATE must be "XXXXXX";
++   replace them with a string that makes the generated directory unique.
++   Create the directory mode 700, and return its name.
++   On failure, return NULL and set errno.  */
++char *
++mkdtempat (int dirfd, char *xtemplate)
++{
++  return (try_tempname_len (xtemplate, 0, &dirfd, try_dir, 6) < 0
++	  ? NULL : xtemplate);
++}
+diff --git a/lib/mkdtempat.h b/lib/mkdtempat.h
+new file mode 100644
+index 00000000..03a18dc1
+--- /dev/null
++++ b/lib/mkdtempat.h
+@@ -0,0 +1 @@
++char *mkdtempat (int, char *);
+diff --git a/src/incremen.c b/src/incremen.c
+index 194d5cb1..a808e1c4 100644
+--- a/src/incremen.c
++++ b/src/incremen.c
+@@ -19,6 +19,7 @@
+ 
+ #include <system.h>
+ #include <hash.h>
++#include <mkdtempat.h>
+ #include <quotearg.h>
+ #include "common.h"
+ 
+@@ -1653,13 +1654,16 @@ purge_directory (char const *directory_name)
+       if (*arc == 'X')
+ 	{
+ #define TEMP_DIR_TEMPLATE "tar.XXXXXX"
+-	  size_t len = strlen (arc + 1);
++	  char *d = safer_name_suffix (arc + 1, false, absolute_names_option);
++	  size_t len = strlen (d);
+ 	  temp_stub = xrealloc (temp_stub, len + 1 + sizeof TEMP_DIR_TEMPLATE);
+-	  memcpy (temp_stub, arc + 1, len);
+-	  temp_stub[len] = '/';
+-	  memcpy (temp_stub + len + 1, TEMP_DIR_TEMPLATE,
++	  char *copy_end = mempcpy (temp_stub, d, len);
++	  *copy_end = '/';
++	  memcpy (copy_end + !ISSLASH (copy_end[-1]), TEMP_DIR_TEMPLATE,
+ 		  sizeof TEMP_DIR_TEMPLATE);
+-	  if (!mkdtemp (temp_stub))
++	  struct fdbase f = fdbase (temp_stub);
++	  if (f.fd == BADFD
++	      || !mkdtempat (f.fd, temp_stub + (f.base - temp_stub)))
+ 	    {
+ 	      ERROR ((0, errno,
+ 		      _("Cannot create temporary directory using template %s"),
+diff --git a/tests/Makefile.am b/tests/Makefile.am
+index b9ed8270..6031d7a1 100644
+--- a/tests/Makefile.am
++++ b/tests/Makefile.am
+@@ -209,6 +209,8 @@ TESTSUITE_AT = \
+  rename04.at\
+  rename05.at\
+  rename06.at\
++ rename08.at\
++ rename09.at\
+  remfiles01.at\
+  remfiles02.at\
+  remfiles03.at\
+diff --git a/tests/rename08.at b/tests/rename08.at
+new file mode 100644
+index 00000000..5452fb4f
+--- /dev/null
++++ b/tests/rename08.at
+@@ -0,0 +1,131 @@
++# Process this file with autom4te to create testsuite. -*- Autotest -*-
++
++# Test suite for GNU tar.
++# Copyright 2006-2026 Free Software Foundation, Inc.
++
++# This file is part of GNU tar.
++
++# GNU tar is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 3 of the License, or
++# (at your option) any later version.
++
++# GNU tar is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++# GNU General Public License for more details.
++
++# You should have received a copy of the GNU General Public License
++# along with this program.  If not, see <http://www.gnu.org/licenses/>.
++
++# Description: Handling of cyclic renames in incremental archives.
++
++AT_SETUP([cyclic renames])
++AT_KEYWORDS([incremental rename rename08 cyclic-rename])
++
++AT_TAR_CHECK([
++AT_SORT_PREREQ
++
++mkdir foo
++genfile --file foo/file1
++genfile --file foo/file2
++
++mkdir foo/a
++genfile --file foo/a/filea
++
++mkdir foo/b
++genfile --file foo/b/fileb
++
++mkdir foo/c
++genfile --file foo/c/filec
++
++sleep 1
++
++echo "First dump"
++echo "First dump">&2
++tar -g incr -cf arch.1 -v foo 2>tmperr
++sort tmperr >&2
++
++# Shuffle directories:
++(cd foo
++mv a $$
++mv c a
++mv b c
++mv $$ b)
++
++echo "Second dump"
++echo "Second dump" >&2
++tar -g incr -cf arch.2 -v foo 2>tmperr
++sort tmperr >&2
++
++mkdir -p restoreparent/restore
++cd restoreparent
++tar xfg ../arch.1 /dev/null --warning=no-timestamp -C restore
++
++echo "Begin directory listing 1"
++( cd restore; find foo ) | sort
++echo "End directory listing 1"
++
++tar xfgv ../arch.2 /dev/null --warning=no-timestamp -C restore
++echo Begin directory listing 2
++( cd restore ; find foo ) | sort
++echo End directory listing 2
++],
++[0],
++[First dump
++foo/
++foo/a/
++foo/b/
++foo/c/
++foo/file1
++foo/file2
++foo/a/filea
++foo/b/fileb
++foo/c/filec
++Second dump
++foo/
++foo/a/
++foo/b/
++foo/c/
++Begin directory listing 1
++foo
++foo/a
++foo/a/filea
++foo/b
++foo/b/fileb
++foo/c
++foo/c/filec
++foo/file1
++foo/file2
++End directory listing 1
++foo/
++foo/a/
++foo/b/
++foo/c/
++Begin directory listing 2
++foo
++foo/a
++foo/a/filec
++foo/b
++foo/b/filea
++foo/c
++foo/c/fileb
++foo/file1
++foo/file2
++End directory listing 2
++],
++[First dump
++tar: foo/a: Directory is new
++tar: foo/b: Directory is new
++tar: foo/c: Directory is new
++tar: foo: Directory is new
++Second dump
++tar: foo/a: Directory has been renamed from 'foo/c'
++tar: foo/b: Directory has been renamed from 'foo/a'
++tar: foo/c: Directory has been renamed from 'foo/b'
++],
++[],[],[gnu, oldgnu, posix])
++
++AT_CLEANUP
++
++# End of rename03.at
+diff --git a/tests/rename09.at b/tests/rename09.at
+new file mode 100644
+index 00000000..8346ff0a
+--- /dev/null
++++ b/tests/rename09.at
+@@ -0,0 +1,129 @@
++# Process this file with autom4te to create testsuite. -*- Autotest -*-
++
++# Test suite for GNU tar.
++# Copyright 2006-2026 Free Software Foundation, Inc.
++
++# This file is part of GNU tar.
++
++# GNU tar is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 3 of the License, or
++# (at your option) any later version.
++
++# GNU tar is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++# GNU General Public License for more details.
++
++# You should have received a copy of the GNU General Public License
++# along with this program.  If not, see <http://www.gnu.org/licenses/>.
++
++# Description: Handling of cyclic renames in incremental archives.
++
++AT_SETUP([cyclic renames])
++AT_KEYWORDS([incremental rename rename09 cyclic-rename])
++
++AT_TAR_CHECK([
++AT_SORT_PREREQ
++
++mkdir foo
++genfile --file foo/file1
++genfile --file foo/file2
++
++mkdir foo/a
++genfile --file foo/a/filea
++
++mkdir foo/b
++genfile --file foo/b/fileb
++
++mkdir foo/c
++genfile --file foo/c/filec
++
++sleep 1
++
++echo "First dump"
++echo "First dump">&2
++tar -g incr -cf arch.1 -v foo 2>tmperr
++sort tmperr >&2
++
++# Shuffle directories:
++(cd foo
++mv a $$
++mv c a
++mv b c
++mv $$ b)
++
++echo "Second dump"
++echo "Second dump" >&2
++tar -g incr -cf arch.2 -v foo 2>tmperr
++sort tmperr >&2
++
++tar xfg arch.1 /dev/null --warning=no-timestamp --one-top-level=restore
++
++echo "Begin directory listing 1"
++( cd restore; find foo ) | sort
++echo "End directory listing 1"
++
++tar xfgv arch.2 /dev/null --warning=no-timestamp --one-top-level=restore
++echo Begin directory listing 2
++( cd restore ; find foo ) | sort
++echo End directory listing 2
++],
++[0],
++[First dump
++foo/
++foo/a/
++foo/b/
++foo/c/
++foo/file1
++foo/file2
++foo/a/filea
++foo/b/fileb
++foo/c/filec
++Second dump
++foo/
++foo/a/
++foo/b/
++foo/c/
++Begin directory listing 1
++foo
++foo/a
++foo/a/filea
++foo/b
++foo/b/fileb
++foo/c
++foo/c/filec
++foo/file1
++foo/file2
++End directory listing 1
++foo/
++foo/a/
++foo/b/
++foo/c/
++Begin directory listing 2
++foo
++foo/a
++foo/a/filec
++foo/b
++foo/b/filea
++foo/c
++foo/c/fileb
++foo/file1
++foo/file2
++End directory listing 2
++],
++[First dump
++tar: foo/a: Directory is new
++tar: foo/b: Directory is new
++tar: foo/c: Directory is new
++tar: foo: Directory is new
++Second dump
++tar: foo/a: Directory has been renamed from 'foo/c'
++tar: foo/b: Directory has been renamed from 'foo/a'
++tar: foo/c: Directory has been renamed from 'foo/b'
++],
++[],[],[gnu, oldgnu, posix])
++
++AT_CLEANUP
++
++# End of rename03.at
+diff --git a/tests/testsuite.at b/tests/testsuite.at
+index 0cc7adda..e4edaba5 100644
+--- a/tests/testsuite.at
++++ b/tests/testsuite.at
+@@ -401,6 +401,8 @@ m4_include([rename03.at])
+ m4_include([rename04.at])
+ m4_include([rename05.at])
+ m4_include([rename06.at])
++m4_include([rename08.at])
++m4_include([rename09.at])
+ m4_include([chtype.at])
+ 
+ AT_BANNER([Ignore failing reads])

diff --git a/tar.spec b/tar.spec
index 2e6b3a5..bc1a65d 100644
--- a/tar.spec
+++ b/tar.spec
@@ -82,6 +82,11 @@ Patch26: tar-1.35-CVE-2026-5704.patch
 # part of 941f62b2
 # Also "by the way" fixes CVE-2026-18508.
 Patch27: tar-1.35-fix-absolute-one-top-level.patch
+#Upstream commits
+# 0714d2f082104005a1c70ee6ec4175194943ea88
+# d479b2cc9160d9c2fb61afbc9ee70c2faadf80db
+# b17665b2c0548c77b6cd8d2d5b61e4c4fcc4f770
+Patch28: tar-1.35-CVE-2026-18477.patch
 
 BuildRequires: autoconf
 BuildRequires: automake

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2026-09-07 17:57 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-07 17:57 [rpms/tar] f44: Backport upstream patches for CVE-2026-18477 Pavel Cahyna

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox