From bad7a6a0dd083d91338781097da71b96aebfd3c0 Mon Sep 17 00:00:00 2001 From: Pavel Cahyna Date: Mon, 12 Jan 2026 12:45:34 +0100 Subject: [PATCH] Backport fix of --no-overwrite-dir Upstream commit 4e742fc8674064a9fa00d4483d06aca48d5b0463 Resolves: RHEL-105969 --- tar-1.35-CVE-2025-45582.patch | 374 +++++++++++++----- ...te-dir-no-overwrite-even-temporarily.patch | 203 ++++++++++ tar.spec | 2 + 3 files changed, 482 insertions(+), 97 deletions(-) create mode 100644 tar-1.35-no-overwrite-dir-no-overwrite-even-temporarily.patch diff --git a/tar-1.35-CVE-2025-45582.patch b/tar-1.35-CVE-2025-45582.patch index be62be3..d192fcb 100644 --- a/tar-1.35-CVE-2025-45582.patch +++ b/tar-1.35-CVE-2025-45582.patch @@ -1,6 +1,6 @@ -diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnulib-cache.m4 -x .git -x '*.in' -x configure -x .gitmodules --unidirectional-new-file -ur tar-1.35-rhel-10.1/aclocal.m4 tar-1.35-rhel-10.2-clean/aclocal.m4 ---- tar-1.35-rhel-10.1/aclocal.m4 2025-12-03 14:00:07.905275300 +0100 -+++ tar-1.35-rhel-10.2-clean/aclocal.m4 2025-12-19 16:56:06.180341993 +0100 +diff -x '*~' -x autom4te.cache -x gnulib -x paxutils -x build-aux -x gnulib.modules -x gnulib-cache.m4 -x .git -x .gitmodules -x '*.in' --unidirectional-new-file -ur tar-1.35-rhel-10.2-e290431e-clean/aclocal.m4 tar-1.35-rhel-10.2-clean/aclocal.m4 +--- a/aclocal.m4 2026-01-12 10:58:21.423872843 +0100 ++++ b/aclocal.m4 2026-01-12 11:21:32.618583108 +0100 @@ -1339,6 +1339,7 @@ m4_include([m4/open-slash.m4]) m4_include([m4/open.m4]) @@ -9,9 +9,190 @@ diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnuli m4_include([m4/opendir.m4]) m4_include([m4/parse-datetime.m4]) m4_include([m4/pathmax.m4]) -diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnulib-cache.m4 -x .git -x '*.in' -x configure -x .gitmodules --unidirectional-new-file -ur tar-1.35-rhel-10.1/doc/tar.texi tar-1.35-rhel-10.2-clean/doc/tar.texi ---- tar-1.35-rhel-10.1/doc/tar.texi 2025-12-03 13:55:36.036944349 +0100 -+++ tar-1.35-rhel-10.2-clean/doc/tar.texi 2025-12-03 14:40:02.627364006 +0100 +diff -x '*~' -x autom4te.cache -x gnulib -x paxutils -x build-aux -x gnulib.modules -x gnulib-cache.m4 -x .git -x .gitmodules -x '*.in' --unidirectional-new-file -ur tar-1.35-rhel-10.2-e290431e-clean/configure tar-1.35-rhel-10.2-clean/configure +--- a/configure 2026-01-12 10:58:23.019911469 +0100 ++++ b/configure 2026-01-12 11:21:34.258632323 +0100 +@@ -1070,6 +1070,8 @@ + PARSE_DATETIME_BISON + GL_COND_OBJ_OPENDIR_FALSE + GL_COND_OBJ_OPENDIR_TRUE ++GL_COND_OBJ_OPENAT2_FALSE ++GL_COND_OBJ_OPENAT2_TRUE + GL_COND_OBJ_OPENAT_FALSE + GL_COND_OBJ_OPENAT_TRUE + GL_COND_OBJ_OPEN_FALSE +@@ -1587,6 +1589,7 @@ + NEXT_FCNTL_H + GL_GNULIB_MDA_OPEN + GL_GNULIB_MDA_CREAT ++GL_GNULIB_OPENAT2 + GL_GNULIB_OPENAT + GL_GNULIB_OPEN + GL_GNULIB_NONBLOCKING +@@ -1598,6 +1601,7 @@ + REPLACE_OPEN + REPLACE_FCNTL + REPLACE_CREAT ++HAVE_OPENAT2 + HAVE_OPENAT + HAVE_FCNTL + GL_COND_OBJ_FCHOWNAT_FALSE +@@ -4535,6 +4539,9 @@ + as_fn_append ac_func_c_list " mprotect HAVE_MPROTECT" + as_fn_append ac_func_c_list " mkdirat HAVE_MKDIRAT" + as_fn_append ac_func_c_list " mknod HAVE_MKNOD" ++as_fn_append ac_func_c_list " openat2 HAVE_OPENAT2" ++as_fn_append ac_func_c_list " fstatfs HAVE_FSTATFS" ++as_fn_append ac_header_c_list " sys/vfs.h sys_vfs_h HAVE_SYS_VFS_H" + as_fn_append ac_func_c_list " pipe HAVE_PIPE" + as_fn_append ac_header_c_list " priv.h priv_h HAVE_PRIV_H" + as_fn_append ac_header_c_list " malloc.h malloc_h HAVE_MALLOC_H" +@@ -8292,6 +8299,7 @@ + # Code from module openat-die: + # Code from module openat-h: + # Code from module openat-safer: ++ # Code from module openat2: + # Code from module opendir: + # Code from module opendirat: + # Code from module parse-datetime: +@@ -15189,6 +15197,7 @@ + + HAVE_FCNTL=1; + HAVE_OPENAT=1; ++ HAVE_OPENAT2=0; + REPLACE_CREAT=0; + REPLACE_FCNTL=0; + REPLACE_OPEN=0; +@@ -15217,6 +15226,10 @@ + + + ++ GL_GNULIB_OPENAT2=0 ++ ++ ++ + GL_GNULIB_MDA_CREAT=1 + + +@@ -17899,8 +17912,8 @@ + LIBS=$save_LIBS + test $gl_pthread_api = yes && break + done +- echo "$as_me:17902: gl_pthread_api=$gl_pthread_api" >&5 +- echo "$as_me:17903: LIBPTHREAD=$LIBPTHREAD" >&5 ++ echo "$as_me:17915: gl_pthread_api=$gl_pthread_api" >&5 ++ echo "$as_me:17916: LIBPTHREAD=$LIBPTHREAD" >&5 + + gl_pthread_in_glibc=no + # On Linux with glibc >= 2.34, libc contains the fully functional +@@ -17926,7 +17939,7 @@ + + ;; + esac +- echo "$as_me:17929: gl_pthread_in_glibc=$gl_pthread_in_glibc" >&5 ++ echo "$as_me:17942: gl_pthread_in_glibc=$gl_pthread_in_glibc" >&5 + + # Test for libpthread by looking for pthread_kill. (Not pthread_self, + # since it is defined as a macro on OSF/1.) +@@ -18080,7 +18093,7 @@ + + fi + fi +- echo "$as_me:18083: LIBPMULTITHREAD=$LIBPMULTITHREAD" >&5 ++ echo "$as_me:18096: LIBPMULTITHREAD=$LIBPMULTITHREAD" >&5 + fi + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether POSIX threads API is available" >&5 + printf %s "checking whether POSIX threads API is available... " >&6; } +@@ -22254,6 +22267,9 @@ + + + ++ ++ ++ + : ${YACC='bison -o y.tab.c'} + + +@@ -39815,6 +39831,76 @@ + + + ++ ++ ++ ++ ++ case $ac_cv_func_openat2 in #( ++ yes) : ++ HAVE_OPENAT2=1 ;; #( ++ *) : ++ ;; ++esac ++ ++ ++ if test $HAVE_OPENAT2 = 0; then ++ GL_COND_OBJ_OPENAT2_TRUE= ++ GL_COND_OBJ_OPENAT2_FALSE='#' ++else ++ GL_COND_OBJ_OPENAT2_TRUE='#' ++ GL_COND_OBJ_OPENAT2_FALSE= ++fi ++: ++ if test -z "${GL_COND_OBJ_OPENAT2_TRUE}" && test -z "${GL_COND_OBJ_OPENAT2_FALSE}"; then ++ GL_COND_OBJ_OPENAT2_TRUE='#' ++ GL_COND_OBJ_OPENAT2_FALSE='#' ++ fi ++ ++ if test -z "$GL_COND_OBJ_OPENAT_TRUE"; then : ++ ++ ++ ++ ++ case $ac_cv_func_fstatfs,$ac_cv_header_sys_vfs_h in #( ++ yes,yes) : ++ ac_fn_c_check_member "$LINENO" "struct statfs" "f_type" "ac_cv_member_struct_statfs_f_type" "$ac_includes_default ++ #include ++ ++" ++if test "x$ac_cv_member_struct_statfs_f_type" = xyes ++then : ++ ++printf "%s\n" "#define HAVE_STRUCT_STATFS_F_TYPE 1" >>confdefs.h ++ ++ ++fi ++ ;; #( ++ *) : ++ ;; ++esac ++ ++ ++fi ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ GL_GNULIB_OPENAT2=1 ++ ++ ++ ++ ++ ++printf "%s\n" "#define GNULIB_TEST_OPENAT2 1" >>confdefs.h ++ ++ ++ ++ + + + ac_fn_c_check_func "$LINENO" "opendir" "ac_cv_func_opendir" +diff -x '*~' -x autom4te.cache -x gnulib -x paxutils -x build-aux -x gnulib.modules -x gnulib-cache.m4 -x .git -x .gitmodules -x '*.in' --unidirectional-new-file -ur tar-1.35-rhel-10.2-e290431e-clean/doc/tar.texi tar-1.35-rhel-10.2-clean/doc/tar.texi +--- a/doc/tar.texi 2026-01-12 10:53:18.080261058 +0100 ++++ b/doc/tar.texi 2026-01-12 11:00:38.055598907 +0100 @@ -12952,26 +12952,31 @@ When @command{tar} extracts from an archive, by default it writes into files relative to the working directory. If the archive was generated @@ -78,9 +259,9 @@ diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnuli @item Do not let untrusted users access files extracted from untrusted archives without checking first for problems such as setuid programs. -diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnulib-cache.m4 -x .git -x '*.in' -x configure -x .gitmodules --unidirectional-new-file -ur tar-1.35-rhel-10.1/gnu/fcntl.in.h tar-1.35-rhel-10.2-clean/gnu/fcntl.in.h ---- tar-1.35-rhel-10.1/gnu/fcntl.in.h 2025-12-03 13:59:51.584775360 +0100 -+++ tar-1.35-rhel-10.2-clean/gnu/fcntl.in.h 2025-12-03 15:02:17.653435608 +0100 +diff -x '*~' -x autom4te.cache -x gnulib -x paxutils -x build-aux -x gnulib.modules -x gnulib-cache.m4 -x .git -x .gitmodules -x '*.in' --unidirectional-new-file -ur tar-1.35-rhel-10.2-e290431e-clean/gnu/fcntl.in.h tar-1.35-rhel-10.2-clean/gnu/fcntl.in.h +--- a/gnu/fcntl.in.h 2026-01-12 10:53:53.929214788 +0100 ++++ b/gnu/fcntl.in.h 2026-01-12 11:01:04.788453365 +0100 @@ -238,6 +238,46 @@ # endif #endif @@ -144,9 +325,9 @@ diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnuli #endif /* _@GUARD_PREFIX@_FCNTL_H */ #endif /* _@GUARD_PREFIX@_FCNTL_H */ #endif -diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnulib-cache.m4 -x .git -x '*.in' -x configure -x .gitmodules --unidirectional-new-file -ur tar-1.35-rhel-10.1/gnu/Makefile.am tar-1.35-rhel-10.2-clean/gnu/Makefile.am ---- tar-1.35-rhel-10.1/gnu/Makefile.am 2025-12-03 14:00:01.585081698 +0100 -+++ tar-1.35-rhel-10.2-clean/gnu/Makefile.am 2025-12-03 15:02:27.665724946 +0100 +diff -x '*~' -x autom4te.cache -x gnulib -x paxutils -x build-aux -x gnulib.modules -x gnulib-cache.m4 -x .git -x .gitmodules -x '*.in' --unidirectional-new-file -ur tar-1.35-rhel-10.2-e290431e-clean/gnu/Makefile.am tar-1.35-rhel-10.2-clean/gnu/Makefile.am +--- a/gnu/Makefile.am 2026-01-12 10:54:04.333486876 +0100 ++++ b/gnu/Makefile.am 2026-01-12 11:01:15.084777442 +0100 @@ -86,6 +86,7 @@ # modechange \ # obstack \ @@ -183,9 +364,9 @@ diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnuli ## begin gnulib module opendir if GL_COND_OBJ_OPENDIR -diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnulib-cache.m4 -x .git -x '*.in' -x configure -x .gitmodules --unidirectional-new-file -ur tar-1.35-rhel-10.1/gnu/openat2.c tar-1.35-rhel-10.2-clean/gnu/openat2.c ---- tar-1.35-rhel-10.1/gnu/openat2.c 1970-01-01 01:00:00.000000000 +0100 -+++ tar-1.35-rhel-10.2-clean/gnu/openat2.c 2025-12-03 15:02:17.941443932 +0100 +diff -x '*~' -x autom4te.cache -x gnulib -x paxutils -x build-aux -x gnulib.modules -x gnulib-cache.m4 -x .git -x .gitmodules -x '*.in' --unidirectional-new-file -ur tar-1.35-rhel-10.2-e290431e-clean/gnu/openat2.c tar-1.35-rhel-10.2-clean/gnu/openat2.c +--- a/gnu/openat2.c 1970-01-01 01:00:00.000000000 +0100 ++++ b/gnu/openat2.c 2026-01-12 11:01:04.592447169 +0100 @@ -0,0 +1,596 @@ +/* Open a file, with more flags than openat + Copyright 2025 Free Software Foundation, Inc. @@ -783,9 +964,9 @@ diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnuli + } + return r; +} -diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnulib-cache.m4 -x .git -x '*.in' -x configure -x .gitmodules --unidirectional-new-file -ur tar-1.35-rhel-10.1/m4/fcntl_h.m4 tar-1.35-rhel-10.2-clean/m4/fcntl_h.m4 ---- tar-1.35-rhel-10.1/m4/fcntl_h.m4 2025-12-03 13:59:52.312797661 +0100 -+++ tar-1.35-rhel-10.2-clean/m4/fcntl_h.m4 2025-12-03 15:02:18.381456650 +0100 +diff -x '*~' -x autom4te.cache -x gnulib -x paxutils -x build-aux -x gnulib.modules -x gnulib-cache.m4 -x .git -x .gitmodules -x '*.in' --unidirectional-new-file -ur tar-1.35-rhel-10.2-e290431e-clean/m4/fcntl_h.m4 tar-1.35-rhel-10.2-clean/m4/fcntl_h.m4 +--- a/m4/fcntl_h.m4 2026-01-12 10:53:54.545230950 +0100 ++++ b/m4/fcntl_h.m4 2026-01-12 11:01:05.428473586 +0100 @@ -1,6 +1,6 @@ -# serial 20 -# Configure fcntl.h. @@ -821,9 +1002,9 @@ diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnuli REPLACE_CREAT=0; AC_SUBST([REPLACE_CREAT]) REPLACE_FCNTL=0; AC_SUBST([REPLACE_FCNTL]) REPLACE_OPEN=0; AC_SUBST([REPLACE_OPEN]) -diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnulib-cache.m4 -x .git -x '*.in' -x configure -x .gitmodules --unidirectional-new-file -ur tar-1.35-rhel-10.1/m4/gnulib-comp.m4 tar-1.35-rhel-10.2-clean/m4/gnulib-comp.m4 ---- tar-1.35-rhel-10.1/m4/gnulib-comp.m4 2025-12-03 13:59:54.620868365 +0100 -+++ tar-1.35-rhel-10.2-clean/m4/gnulib-comp.m4 2025-12-03 15:02:20.701523703 +0100 +diff -x '*~' -x autom4te.cache -x gnulib -x paxutils -x build-aux -x gnulib.modules -x gnulib-cache.m4 -x .git -x .gitmodules -x '*.in' --unidirectional-new-file -ur tar-1.35-rhel-10.2-e290431e-clean/m4/gnulib-comp.m4 tar-1.35-rhel-10.2-clean/m4/gnulib-comp.m4 +--- a/m4/gnulib-comp.m4 2026-01-12 10:53:56.897292603 +0100 ++++ b/m4/gnulib-comp.m4 2026-01-12 11:01:07.740546556 +0100 @@ -237,6 +237,7 @@ # Code from module openat-die: # Code from module openat-h: @@ -862,9 +1043,9 @@ diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnuli m4/opendir.m4 m4/parse-datetime.m4 m4/pathmax.m4 -diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnulib-cache.m4 -x .git -x '*.in' -x configure -x .gitmodules --unidirectional-new-file -ur tar-1.35-rhel-10.1/m4/openat2.m4 tar-1.35-rhel-10.2-clean/m4/openat2.m4 ---- tar-1.35-rhel-10.1/m4/openat2.m4 1970-01-01 01:00:00.000000000 +0100 -+++ tar-1.35-rhel-10.2-clean/m4/openat2.m4 2025-12-03 15:02:18.549461506 +0100 +diff -x '*~' -x autom4te.cache -x gnulib -x paxutils -x build-aux -x gnulib.modules -x gnulib-cache.m4 -x .git -x .gitmodules -x '*.in' --unidirectional-new-file -ur tar-1.35-rhel-10.2-e290431e-clean/m4/openat2.m4 tar-1.35-rhel-10.2-clean/m4/openat2.m4 +--- a/m4/openat2.m4 1970-01-01 01:00:00.000000000 +0100 ++++ b/m4/openat2.m4 2026-01-12 11:01:04.596447295 +0100 @@ -0,0 +1,33 @@ +# openat2.m4 +# serial 1 @@ -899,31 +1080,30 @@ diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnuli + #include + ]])]) +]) -diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnulib-cache.m4 -x .git -x '*.in' -x configure -x .gitmodules --unidirectional-new-file -ur tar-1.35-rhel-10.1/NEWS tar-1.35-rhel-10.2-clean/NEWS ---- tar-1.35-rhel-10.1/NEWS 2025-12-03 13:55:36.028944104 +0100 -+++ tar-1.35-rhel-10.2-clean/NEWS 2025-12-03 14:40:02.623363898 +0100 -@@ -1,6 +1,17 @@ --GNU tar NEWS - User visible changes. 2023-07-18 -+GNU tar NEWS - User visible changes. 2025-11-13 +diff -x '*~' -x autom4te.cache -x gnulib -x paxutils -x build-aux -x gnulib.modules -x gnulib-cache.m4 -x .git -x .gitmodules -x '*.in' --unidirectional-new-file -ur tar-1.35-rhel-10.2-e290431e-clean/NEWS tar-1.35-rhel-10.2-clean/NEWS +--- a/NEWS 2026-01-12 10:57:17.342316401 +0100 ++++ b/NEWS 2026-01-12 11:00:38.051598778 +0100 +@@ -1,10 +1,16 @@ +-GNU tar NEWS - User visible changes. 2025-07-26 ++GNU tar NEWS - User visible changes. 2026-01-09 Please send GNU tar bug reports to -+version 1.35.90 (git) -+ -+* Bug fixes -+ + version 1.35.90 (git) + + * Bug fixes + +** When extracting, tar no longer follows symbolic links to targets + outside the working directory. + +** tar no longer fails merely if an extraction directory is unreadable + on Linux kernels. + -+ - version 1.35 - Sergey Poznyakoff, 2023-07-18 - - * Fail when building GNU tar, if the platform supports 64-bit time_t -diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnulib-cache.m4 -x .git -x '*.in' -x configure -x .gitmodules --unidirectional-new-file -ur tar-1.35-rhel-10.1/src/common.h tar-1.35-rhel-10.2-clean/src/common.h ---- tar-1.35-rhel-10.1/src/common.h 2025-12-03 13:55:36.040944472 +0100 -+++ tar-1.35-rhel-10.2-clean/src/common.h 2025-12-03 14:40:02.631364114 +0100 + ** --no-overwrite-dir no longer changes permissions of existing directories, + not even temporarily. This matches the documentation better and avoids + some permissions glitches. +diff -x '*~' -x autom4te.cache -x gnulib -x paxutils -x build-aux -x gnulib.modules -x gnulib-cache.m4 -x .git -x .gitmodules -x '*.in' --unidirectional-new-file -ur tar-1.35-rhel-10.2-e290431e-clean/src/common.h tar-1.35-rhel-10.2-clean/src/common.h +--- a/src/common.h 2026-01-12 10:53:18.296266888 +0100 ++++ b/src/common.h 2026-01-12 11:00:38.163602399 +0100 @@ -401,7 +401,7 @@ /* Flags for reading, searching, and fstatatting files. */ @@ -960,9 +1140,9 @@ diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnuli int chdir_count (void); void close_diag (char const *name); -diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnulib-cache.m4 -x .git -x '*.in' -x configure -x .gitmodules --unidirectional-new-file -ur tar-1.35-rhel-10.1/src/compare.c tar-1.35-rhel-10.2-clean/src/compare.c ---- tar-1.35-rhel-10.1/src/compare.c 2025-12-03 13:55:36.040944472 +0100 -+++ tar-1.35-rhel-10.2-clean/src/compare.c 2025-12-03 14:40:02.631364114 +0100 +diff -x '*~' -x autom4te.cache -x gnulib -x paxutils -x build-aux -x gnulib.modules -x gnulib-cache.m4 -x .git -x .gitmodules -x '*.in' --unidirectional-new-file -ur tar-1.35-rhel-10.2-e290431e-clean/src/compare.c tar-1.35-rhel-10.2-clean/src/compare.c +--- a/src/compare.c 2026-01-12 10:53:18.296266888 +0100 ++++ b/src/compare.c 2026-01-12 11:00:38.163602399 +0100 @@ -218,7 +218,9 @@ } else @@ -1015,9 +1195,9 @@ diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnuli if (fd < 0) { -diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnulib-cache.m4 -x .git -x '*.in' -x configure -x .gitmodules --unidirectional-new-file -ur tar-1.35-rhel-10.1/src/create.c tar-1.35-rhel-10.2-clean/src/create.c ---- tar-1.35-rhel-10.1/src/create.c 2025-12-03 13:55:36.040944472 +0100 -+++ tar-1.35-rhel-10.2-clean/src/create.c 2025-12-03 14:40:02.631364114 +0100 +diff -x '*~' -x autom4te.cache -x gnulib -x paxutils -x build-aux -x gnulib.modules -x gnulib-cache.m4 -x .git -x .gitmodules -x '*.in' --unidirectional-new-file -ur tar-1.35-rhel-10.2-e290431e-clean/src/create.c tar-1.35-rhel-10.2-clean/src/create.c +--- a/src/create.c 2026-01-12 10:57:17.346316499 +0100 ++++ b/src/create.c 2026-01-12 11:00:38.163602399 +0100 @@ -1376,8 +1376,10 @@ { if (! st.orig_file_name) @@ -1214,9 +1394,9 @@ diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnuli } else if (S_ISSOCK (st->stat.st_mode)) { -diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnulib-cache.m4 -x .git -x '*.in' -x configure -x .gitmodules --unidirectional-new-file -ur tar-1.35-rhel-10.1/src/exclist.c tar-1.35-rhel-10.2-clean/src/exclist.c ---- tar-1.35-rhel-10.1/src/exclist.c 2025-12-03 13:55:36.040944472 +0100 -+++ tar-1.35-rhel-10.2-clean/src/exclist.c 2025-12-03 14:40:02.631364114 +0100 +diff -x '*~' -x autom4te.cache -x gnulib -x paxutils -x build-aux -x gnulib.modules -x gnulib-cache.m4 -x .git -x .gitmodules -x '*.in' --unidirectional-new-file -ur tar-1.35-rhel-10.2-e290431e-clean/src/exclist.c tar-1.35-rhel-10.2-clean/src/exclist.c +--- a/src/exclist.c 2026-01-12 10:53:18.296266888 +0100 ++++ b/src/exclist.c 2026-01-12 11:00:38.163602399 +0100 @@ -79,7 +79,7 @@ return; for (file = excfile_head; file; file = file->next) @@ -1240,9 +1420,9 @@ diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnuli if ((result = excluded_file_name (ep->excluded, rname))) break; -diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnulib-cache.m4 -x .git -x '*.in' -x configure -x .gitmodules --unidirectional-new-file -ur tar-1.35-rhel-10.1/src/extract.c tar-1.35-rhel-10.2-clean/src/extract.c ---- tar-1.35-rhel-10.1/src/extract.c 2025-12-03 13:55:36.040944472 +0100 -+++ tar-1.35-rhel-10.2-clean/src/extract.c 2025-12-19 16:50:16.334289994 +0100 +diff -x '*~' -x autom4te.cache -x gnulib -x paxutils -x build-aux -x gnulib.modules -x gnulib-cache.m4 -x .git -x .gitmodules -x '*.in' --unidirectional-new-file -ur tar-1.35-rhel-10.2-e290431e-clean/src/extract.c tar-1.35-rhel-10.2-clean/src/extract.c +--- a/src/extract.c 2026-01-12 10:57:17.346316499 +0100 ++++ b/src/extract.c 2026-01-12 11:00:38.163602399 +0100 @@ -246,7 +246,8 @@ if (result == 0 || implemented (errno)) return result; @@ -1399,7 +1579,7 @@ diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnuli if (status == 0) { current_mode = mode & ~ current_umask; -@@ -1200,21 +1221,24 @@ +@@ -1175,21 +1196,24 @@ } } @@ -1427,7 +1607,7 @@ diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnuli if (0 <= fd) { if (openflag & O_EXCL) -@@ -1380,7 +1404,8 @@ +@@ -1355,7 +1379,8 @@ if (!delayed_link_table) return false; @@ -1437,7 +1617,7 @@ diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnuli { if (errno != ENOENT) stat_error (name); -@@ -1406,8 +1431,16 @@ +@@ -1381,8 +1406,16 @@ int fd; struct stat st; @@ -1455,7 +1635,7 @@ diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnuli if (errno == EEXIST && find_delayed_link_source (file_name)) { /* The placeholder file has already been created. This means -@@ -1429,7 +1462,7 @@ +@@ -1404,7 +1437,7 @@ open_error (file_name); return -1; } @@ -1464,7 +1644,7 @@ diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnuli if (fstat (fd, &st) != 0) { -@@ -1506,15 +1539,23 @@ +@@ -1481,15 +1514,23 @@ do { @@ -1493,7 +1673,7 @@ diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnuli { struct delayed_link dl1; dl1.ino = st1.st_ino; -@@ -1534,15 +1575,15 @@ +@@ -1509,15 +1550,15 @@ return 0; } @@ -1517,7 +1697,7 @@ diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnuli errno = e; } while ((rc = maybe_recoverable (file_name, false, &interdir_made)) -@@ -1569,7 +1610,10 @@ +@@ -1544,7 +1585,10 @@ || contains_dot_dot (current_stat_info.link_name))) return create_placeholder_file (file_name, true, &interdir_made); @@ -1529,7 +1709,7 @@ diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnuli switch (maybe_recoverable (file_name, false, &interdir_made)) { case RECOVER_OK: -@@ -1609,8 +1653,10 @@ +@@ -1584,8 +1628,10 @@ mode_t mode = (current_stat_info.stat.st_mode & (MODE_RWX | S_IFBLK | S_IFCHR) & ~ (0 < same_owner_option ? S_IRWXG | S_IRWXO : 0)); @@ -1542,7 +1722,7 @@ diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnuli switch (maybe_recoverable (file_name, false, &interdir_made)) { case RECOVER_OK: -@@ -1639,7 +1685,10 @@ +@@ -1614,7 +1660,10 @@ mode_t mode = (current_stat_info.stat.st_mode & MODE_RWX & ~ (0 < same_owner_option ? S_IRWXG | S_IRWXO : 0)); @@ -1554,7 +1734,7 @@ diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnuli switch (maybe_recoverable (file_name, false, &interdir_made)) { case RECOVER_OK: -@@ -1862,7 +1911,7 @@ +@@ -1837,7 +1886,7 @@ apply_delayed_link (struct delayed_link *ds) { struct string_list *sources = ds->sources; @@ -1563,7 +1743,7 @@ diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnuli chdir_do (ds->change_dir); -@@ -1874,25 +1923,30 @@ +@@ -1849,25 +1898,30 @@ /* Make sure the placeholder file is still there. If not, don't create a link, as the placeholder was probably removed by a later extraction. */ @@ -1600,7 +1780,7 @@ diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnuli symlink_error (ds->target, source); else { -@@ -1968,9 +2022,14 @@ +@@ -1943,9 +1997,14 @@ bool rename_directory (char *src, char *dst) { @@ -1618,7 +1798,7 @@ diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnuli { int e = errno; -@@ -1979,8 +2038,13 @@ +@@ -1954,8 +2013,13 @@ case ENOENT: if (make_directories (dst, NULL) == 0) { @@ -1634,9 +1814,9 @@ diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnuli e = errno; } break; -diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnulib-cache.m4 -x .git -x '*.in' -x configure -x .gitmodules --unidirectional-new-file -ur tar-1.35-rhel-10.1/src/misc.c tar-1.35-rhel-10.2-clean/src/misc.c ---- tar-1.35-rhel-10.1/src/misc.c 2025-12-03 13:55:36.040944472 +0100 -+++ tar-1.35-rhel-10.2-clean/src/misc.c 2025-12-03 14:40:02.635364223 +0100 +diff -x '*~' -x autom4te.cache -x gnulib -x paxutils -x build-aux -x gnulib.modules -x gnulib-cache.m4 -x .git -x .gitmodules -x '*.in' --unidirectional-new-file -ur tar-1.35-rhel-10.2-e290431e-clean/src/misc.c tar-1.35-rhel-10.2-clean/src/misc.c +--- a/src/misc.c 2026-01-12 10:53:18.296266888 +0100 ++++ b/src/misc.c 2026-01-12 11:00:38.163602399 +0100 @@ -269,6 +269,30 @@ return name; } @@ -2160,9 +2340,9 @@ diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnuli if (fd < 0) { if (!must_exist && errno == ENOENT) -diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnulib-cache.m4 -x .git -x '*.in' -x configure -x .gitmodules --unidirectional-new-file -ur tar-1.35-rhel-10.1/src/names.c tar-1.35-rhel-10.2-clean/src/names.c ---- tar-1.35-rhel-10.1/src/names.c 2025-12-03 13:55:36.040944472 +0100 -+++ tar-1.35-rhel-10.2-clean/src/names.c 2025-12-03 14:40:02.635364223 +0100 +diff -x '*~' -x autom4te.cache -x gnulib -x paxutils -x build-aux -x gnulib.modules -x gnulib-cache.m4 -x .git -x .gitmodules -x '*.in' --unidirectional-new-file -ur tar-1.35-rhel-10.2-e290431e-clean/src/names.c tar-1.35-rhel-10.2-clean/src/names.c +--- a/src/names.c 2026-01-12 10:53:18.296266888 +0100 ++++ b/src/names.c 2026-01-12 11:00:38.167602527 +0100 @@ -1797,8 +1797,9 @@ } if (S_ISDIR (st.stat.st_mode)) @@ -2175,9 +2355,9 @@ diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnuli if (dir_fd < 0) open_diag (name->name); else -diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnulib-cache.m4 -x .git -x '*.in' -x configure -x .gitmodules --unidirectional-new-file -ur tar-1.35-rhel-10.1/src/tar.c tar-1.35-rhel-10.2-clean/src/tar.c ---- tar-1.35-rhel-10.1/src/tar.c 2025-12-03 13:55:36.044944594 +0100 -+++ tar-1.35-rhel-10.2-clean/src/tar.c 2025-12-03 14:40:02.635364223 +0100 +diff -x '*~' -x autom4te.cache -x gnulib -x paxutils -x build-aux -x gnulib.modules -x gnulib-cache.m4 -x .git -x .gitmodules -x '*.in' --unidirectional-new-file -ur tar-1.35-rhel-10.2-e290431e-clean/src/tar.c tar-1.35-rhel-10.2-clean/src/tar.c +--- a/src/tar.c 2026-01-12 10:53:18.300266996 +0100 ++++ b/src/tar.c 2026-01-12 11:00:38.167602527 +0100 @@ -2614,16 +2614,29 @@ if (recursive_unlink_option) old_files_option = UNLINK_FIRST_OLD_FILES; @@ -2217,9 +2397,9 @@ diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnuli } fstatat_flags = dereference_option ? 0 : AT_SYMLINK_NOFOLLOW; -diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnulib-cache.m4 -x .git -x '*.in' -x configure -x .gitmodules --unidirectional-new-file -ur tar-1.35-rhel-10.1/src/unlink.c tar-1.35-rhel-10.2-clean/src/unlink.c ---- tar-1.35-rhel-10.1/src/unlink.c 2025-12-03 13:55:36.044944594 +0100 -+++ tar-1.35-rhel-10.2-clean/src/unlink.c 2025-12-03 14:40:02.635364223 +0100 +diff -x '*~' -x autom4te.cache -x gnulib -x paxutils -x build-aux -x gnulib.modules -x gnulib-cache.m4 -x .git -x .gitmodules -x '*.in' --unidirectional-new-file -ur tar-1.35-rhel-10.2-e290431e-clean/src/unlink.c tar-1.35-rhel-10.2-clean/src/unlink.c +--- a/src/unlink.c 2026-01-12 10:53:18.300266996 +0100 ++++ b/src/unlink.c 2026-01-12 11:00:38.167602527 +0100 @@ -117,7 +117,10 @@ else fname = p->file_name; @@ -2262,9 +2442,9 @@ diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnuli dunlink_reclaim (p); dunlink_count--; p = next; -diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnulib-cache.m4 -x .git -x '*.in' -x configure -x .gitmodules --unidirectional-new-file -ur tar-1.35-rhel-10.1/src/update.c tar-1.35-rhel-10.2-clean/src/update.c ---- tar-1.35-rhel-10.1/src/update.c 2025-12-03 13:55:36.044944594 +0100 -+++ tar-1.35-rhel-10.2-clean/src/update.c 2025-12-03 14:40:02.635364223 +0100 +diff -x '*~' -x autom4te.cache -x gnulib -x paxutils -x build-aux -x gnulib.modules -x gnulib-cache.m4 -x .git -x .gitmodules -x '*.in' --unidirectional-new-file -ur tar-1.35-rhel-10.2-e290431e-clean/src/update.c tar-1.35-rhel-10.2-clean/src/update.c +--- a/src/update.c 2026-01-12 10:53:18.300266996 +0100 ++++ b/src/update.c 2026-01-12 11:00:38.167602527 +0100 @@ -49,7 +49,8 @@ static void append_file (char *file_name) @@ -2275,9 +2455,9 @@ diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnuli if (handle < 0) { -diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnulib-cache.m4 -x .git -x '*.in' -x configure -x .gitmodules --unidirectional-new-file -ur tar-1.35-rhel-10.1/src/xattrs.c tar-1.35-rhel-10.2-clean/src/xattrs.c ---- tar-1.35-rhel-10.1/src/xattrs.c 2025-12-03 13:55:36.044944594 +0100 -+++ tar-1.35-rhel-10.2-clean/src/xattrs.c 2025-12-03 14:40:02.635364223 +0100 +diff -x '*~' -x autom4te.cache -x gnulib -x paxutils -x build-aux -x gnulib.modules -x gnulib-cache.m4 -x .git -x .gitmodules -x '*.in' --unidirectional-new-file -ur tar-1.35-rhel-10.2-e290431e-clean/src/xattrs.c tar-1.35-rhel-10.2-clean/src/xattrs.c +--- a/src/xattrs.c 2026-01-12 10:53:18.300266996 +0100 ++++ b/src/xattrs.c 2026-01-12 11:00:38.167602527 +0100 @@ -299,7 +299,8 @@ /* No "default" IEEE 1003.1e ACL set for directory. At this moment, FILE_NAME may already have inherited default acls from parent @@ -2339,9 +2519,9 @@ diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnuli sysname = "lsetfileconat"; } -diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnulib-cache.m4 -x .git -x '*.in' -x configure -x .gitmodules --unidirectional-new-file -ur tar-1.35-rhel-10.1/tests/extrac31.at tar-1.35-rhel-10.2-clean/tests/extrac31.at ---- tar-1.35-rhel-10.1/tests/extrac31.at 1970-01-01 01:00:00.000000000 +0100 -+++ tar-1.35-rhel-10.2-clean/tests/extrac31.at 2025-12-03 14:40:02.639364330 +0100 +diff -x '*~' -x autom4te.cache -x gnulib -x paxutils -x build-aux -x gnulib.modules -x gnulib-cache.m4 -x .git -x .gitmodules -x '*.in' --unidirectional-new-file -ur tar-1.35-rhel-10.2-e290431e-clean/tests/extrac31.at tar-1.35-rhel-10.2-clean/tests/extrac31.at +--- a/tests/extrac31.at 1970-01-01 01:00:00.000000000 +0100 ++++ b/tests/extrac31.at 2026-01-12 11:00:38.167602527 +0100 @@ -0,0 +1,55 @@ +# Test suite for GNU tar. -*- Autotest -*- +# Copyright 2025 Free Software Foundation, Inc. @@ -2398,24 +2578,24 @@ diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnuli +tar: Exiting with failure status due to previous errors +]) +AT_CLEANUP -diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnulib-cache.m4 -x .git -x '*.in' -x configure -x .gitmodules --unidirectional-new-file -ur tar-1.35-rhel-10.1/tests/Makefile.am tar-1.35-rhel-10.2-clean/tests/Makefile.am ---- tar-1.35-rhel-10.1/tests/Makefile.am 2025-12-03 13:55:36.044944594 +0100 -+++ tar-1.35-rhel-10.2-clean/tests/Makefile.am 2025-12-03 14:40:02.635364223 +0100 -@@ -126,6 +126,7 @@ - extrac24.at\ +diff -x '*~' -x autom4te.cache -x gnulib -x paxutils -x build-aux -x gnulib.modules -x gnulib-cache.m4 -x .git -x .gitmodules -x '*.in' --unidirectional-new-file -ur tar-1.35-rhel-10.2-e290431e-clean/tests/Makefile.am tar-1.35-rhel-10.2-clean/tests/Makefile.am +--- a/tests/Makefile.am 2026-01-12 10:57:17.346316499 +0100 ++++ b/tests/Makefile.am 2026-01-12 11:00:38.167602527 +0100 +@@ -127,6 +127,7 @@ extrac25.at\ extrac27.at\ + extrac30.at\ + extrac31.at\ filerem01.at\ filerem02.at\ dirrem01.at\ -diff -x '*~' -x autom4te.cache -x gnulib -x build-aux -x gnulib.modules -x gnulib-cache.m4 -x .git -x '*.in' -x configure -x .gitmodules --unidirectional-new-file -ur tar-1.35-rhel-10.1/tests/testsuite.at tar-1.35-rhel-10.2-clean/tests/testsuite.at ---- tar-1.35-rhel-10.1/tests/testsuite.at 2025-12-03 13:55:36.052944840 +0100 -+++ tar-1.35-rhel-10.2-clean/tests/testsuite.at 2025-12-03 14:40:02.643364439 +0100 -@@ -350,6 +350,7 @@ - m4_include([extrac24.at]) +diff -x '*~' -x autom4te.cache -x gnulib -x paxutils -x build-aux -x gnulib.modules -x gnulib-cache.m4 -x .git -x .gitmodules -x '*.in' --unidirectional-new-file -ur tar-1.35-rhel-10.2-e290431e-clean/tests/testsuite.at tar-1.35-rhel-10.2-clean/tests/testsuite.at +--- a/tests/testsuite.at 2026-01-12 10:57:17.346316499 +0100 ++++ b/tests/testsuite.at 2026-01-12 11:00:38.171602657 +0100 +@@ -351,6 +351,7 @@ m4_include([extrac25.at]) m4_include([extrac27.at]) + m4_include([extrac30.at]) +m4_include([extrac31.at]) m4_include([backup01.at]) diff --git a/tar-1.35-no-overwrite-dir-no-overwrite-even-temporarily.patch b/tar-1.35-no-overwrite-dir-no-overwrite-even-temporarily.patch new file mode 100644 index 0000000..d9cdbd7 --- /dev/null +++ b/tar-1.35-no-overwrite-dir-no-overwrite-even-temporarily.patch @@ -0,0 +1,203 @@ +From e290431ef27897afea228052425478f82d69fa29 Mon Sep 17 00:00:00 2001 +From: Paul Eggert +Date: Sat, 26 Jul 2025 21:41:23 -0700 +Subject: [PATCH] --no-overwrite-dir no overwrite even temporarily + +Problem and fix reported by Pavel Cahyna in +https://lists.gnu.org/r/bug-tar/2025-01/msg00000.html +* src/extract.c (extract_dir): With --no-overwrite-dir, +skip the chmod if the directory already exists. +* tests/extrac23.at (--no-overwrite-dir on empty directory): +Move the part of the test that looks at a nonempty directory ... +* tests/extrac30.at: ... to this new file, because the test now +must be run as non-root. Adjust the test to match the new behavior. +* tests/Makefile.am (TESTSUITE_AT), tests/testsuite.at: Add it. +--- + NEWS | 11 ++++++++++- + src/extract.c | 25 ------------------------ + tests/Makefile.am | 1 + + tests/extrac23.at | 16 +--------------- + tests/extrac30.at | 47 ++++++++++++++++++++++++++++++++++++++++++++++ + tests/testsuite.at | 1 + + 6 files changed, 60 insertions(+), 41 deletions(-) + create mode 100644 tests/extrac30.at + +diff --git a/NEWS b/NEWS +index 4af60eff..9d346192 100644 +--- a/NEWS ++++ b/NEWS +@@ -1,5 +1,14 @@ +-GNU tar NEWS - User visible changes. 2023-07-18 ++GNU tar NEWS - User visible changes. 2025-07-26 + Please send GNU tar bug reports to ++ ++version 1.35.90 (git) ++ ++* Bug fixes ++ ++** --no-overwrite-dir no longer changes permissions of existing directories, ++ not even temporarily. This matches the documentation better and avoids ++ some permissions glitches. ++ + + version 1.35 - Sergey Poznyakoff, 2023-07-18 + +diff --git a/src/extract.c b/src/extract.c +index 3e3932b1..72ef7ee2 100644 +--- a/src/extract.c ++++ b/src/extract.c +@@ -1105,31 +1105,6 @@ extract_dir (char *file_name, int typeflag) + repair_delayed_set_stat (file_name, &st); + return 0; + } +- else if (old_files_option == NO_OVERWRITE_DIR_OLD_FILES) +- { +- /* Temporarily change the directory mode to a safe +- value, to be able to create files in it, should +- the need be. +- */ +- mode = safe_dir_mode (&st); +- status = fd_chmod (-1, file_name, mode, +- AT_SYMLINK_NOFOLLOW, DIRTYPE); +- if (status == 0) +- { +- /* Store the actual directory mode, to be restored +- later. +- */ +- current_stat_info.stat = st; +- current_mode = mode & ~ current_umask; +- current_mode_mask = MODE_RWX; +- atflag = AT_SYMLINK_NOFOLLOW; +- break; +- } +- else +- { +- chmod_error_details (file_name, mode); +- } +- } + break; + } + } +diff --git a/tests/Makefile.am b/tests/Makefile.am +index f7464044..ad69e1b2 100644 +--- a/tests/Makefile.am ++++ b/tests/Makefile.am +@@ -126,6 +126,7 @@ TESTSUITE_AT = \ + extrac24.at\ + extrac25.at\ + extrac27.at\ ++ extrac30.at\ + filerem01.at\ + filerem02.at\ + dirrem01.at\ +diff --git a/tests/extrac23.at b/tests/extrac23.at +index cb63ebb2..efc9a326 100644 +--- a/tests/extrac23.at ++++ b/tests/extrac23.at +@@ -15,15 +15,12 @@ + # + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . +-AT_SETUP([--no-overwrite-dir]) ++AT_SETUP([--no-overwrite-dir on empty directory]) + AT_KEYWORDS([extract extrac23 no-overwrite-dir]) + + # Description: Implementation of the --no-overwrite-dir option was flawed in + # tar versions up to 1.32.90. This option is intended to preserve metadata + # of existing directories. In fact it worked only for non-empty directories. +-# Moreover, if the actual directory was owned by the user tar runs as and the +-# S_IWUSR bit was not set in its actual permissions, tar failed to create files +-# in it. + # + # Reported by: Michael Kaufmann + # References: <20200207112934.Horde.anXzYhAj2CHiwUrw5CuT0G-@webmail.michael-kaufmann.ch>, +@@ -38,21 +35,10 @@ chmod 777 dir + tar -xf a.tar --no-overwrite-dir + genfile --stat=mode.777 dir + +-# Test if temporary permissions are set correctly to allow the owner +-# to write to the directory. +-genfile --file dir/file +-tar cf a.tar dir +-rm dir/file +-chmod 400 dir +-tar -xf a.tar --no-overwrite-dir +-genfile --stat=mode.777 dir +-chmod 700 dir + find dir + ], + [0], + [777 +-400 + dir +-dir/file + ]) + AT_CLEANUP +diff --git a/tests/extrac30.at b/tests/extrac30.at +new file mode 100644 +index 00000000..8c879c95 +--- /dev/null ++++ b/tests/extrac30.at +@@ -0,0 +1,47 @@ ++# Test suite for GNU tar. -*- Autotest -*- ++# Copyright 2020-2025 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 . ++AT_SETUP([--no-overwrite-dir on unwritable directory]) ++AT_KEYWORDS([extract extrac30 no-overwrite-dir]) ++ ++# Make sure that tar does not change permissions on directories if ++# --no-overwrite-dir tells it not to, not even temporarily. ++ ++AT_TAR_CHECK([ ++AT_UNPRIVILEGED_PREREQ ++ ++# Test that the user cannot write to a unwritable directory ++# if --no-overwrite-dir is used. ++mkdir dir ++chmod 755 dir ++genfile --file dir/file ++tar cf a.tar dir ++rm dir/file ++chmod 555 dir ++tar -xf a.tar --no-overwrite-dir ++genfile --stat=mode.777 dir ++chmod 755 dir ++find dir ++], ++[0], ++[555 ++dir ++], ++[tar: dir/file: Cannot open: Permission denied ++tar: Exiting with failure status due to previous errors ++]) ++AT_CLEANUP +diff --git a/tests/testsuite.at b/tests/testsuite.at +index 91754212..90480d18 100644 +--- a/tests/testsuite.at ++++ b/tests/testsuite.at +@@ -350,6 +350,7 @@ m4_include([extrac23.at]) + m4_include([extrac24.at]) + m4_include([extrac25.at]) + m4_include([extrac27.at]) ++m4_include([extrac30.at]) + + m4_include([backup01.at]) + +-- +2.39.5 + diff --git a/tar.spec b/tar.spec index 221eefe..f7481f7 100644 --- a/tar.spec +++ b/tar.spec @@ -31,6 +31,8 @@ Patch14: tar-1.35-add-forgotten-tests-from-upstream.patch Patch15: tar-1.35-revert-fix-savannah-bug-633567.patch # Source: https://cgit.git.savannah.gnu.org/cgit/tar.git/diff/?id=5114218025b4562392dd260e2533d3fa2bc0220e Patch16: tar-1.35-Fix-Savane-bug-64581.patch +# Source: https://cgit.git.savannah.gnu.org/cgit/tar.git/diff/?id=4e742fc8674064a9fa00d4483d06aca48d5b0463 +Patch22: tar-1.35-no-overwrite-dir-no-overwrite-even-temporarily.patch #tar commits from upstream # 56fb4a96ca43c247261b8c04dd65592f990f98ac # 7c241126f14975c7f5df4268b434f276fc7f8842