Package: ansible-core
Version: 2.17.0,2.17.1,2.17.2,2.17.3
Severity: important
Tags: patch upstream
X-Debbugs-Cc: m...@mattgrant.net.nz

Dear Maintainer,

Ansible is not updating mtimes on the files it changes on a system. 
This breaks normal POSIX behaviour, and means make type configuration
reloads don't work.  I found this when changing my firewall Shorewall
configuration, and then find that iptables was not updated!  Bind9 zone
file reloading is also affected.

This 'oversight' in their programming is a criticla bug.

Upstream Bug reports are #83235 (one liner partial fix and applied as
in attached patch), and #83805)  I am working with upstream to get
these crticial fixes integrated.

I found this fix backporting latest Ansible to Bookworm for my local usage.

Cheers,

Matthew Grant

-- System Information:
Debian Release: 12.6, and Sid unstable
  APT prefers stable-updates
  APT policy: (500, 'stable-updates'), (500, 'stable-security'), (500, 'stable')
Architecture: amd64 (x86_64)

Kernel: Linux 6.1.103-amd64-mag-lts (SMP w/32 CPU threads; PREEMPT)
Kernel taint flags: TAINT_PROPRIETARY_MODULE, TAINT_OOT_MODULE
Locale: LANG=en_NZ.UTF-8, LC_CTYPE=en_NZ.UTF-8 (charmap=UTF-8), LANGUAGE not set
Shell: /bin/sh linked to /usr/bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled

Versions of packages ansible-core depends on:
ii  openssh-client        1:9.2p1-2+deb12u3
ii  python3               3.11.2-1+b1
ii  python3-cryptography  38.0.4-3
ii  python3-distutils     3.11.2-3
ii  python3-dnspython     2.3.0-1
ii  python3-httplib2      0.20.4-3
ii  python3-jinja2        3.1.2-1
pn  python3-netaddr       <none>
ii  python3-packaging     23.0-1
ii  python3-pycryptodome  3.11.0+dfsg1-4
ii  python3-resolvelib    0.9.0-2
ii  python3-yaml          6.0-3+b2

Versions of packages ansible-core recommends:
pn  ansible              <none>
pn  python3-argcomplete  <none>
pn  python3-jmespath     <none>
pn  python3-kerberos     <none>
pn  python3-libcloud     <none>
ii  python3-passlib      1.7.4-3
pn  python3-selinux      <none>
pn  python3-winrm        <none>
pn  python3-xmltodict    <none>

Versions of packages ansible-core suggests:
pn  cowsay   <none>
pn  sshpass  <none>
Description: atomic_move() mtime fix
 Fix mtime not updating on ansible template or copy
 .
 This fixes the issue of mtimes on ansible 2.17+ not having the
 mtime/atime update when a tmplated or copied file is altered.
 This can lead to issues with software that uses a make type
 algorithm to dect changes on reload, such as Bind 9.x or Shorewall
 the latter leading to possible security issues with firewalls not
 reloading as expected!
Author: Matthew Grant <m...@mattgrant.net.nz>
Forwarded: upstream Ansible Bugs #83235 (applied upstream), #83805
Last-Update: 2024-08-16
---
This patch header follows DEP-3: http://dep.debian.net/deps/dep3/

Index: ansible-core/lib/ansible/module_utils/basic.py
===================================================================
--- ansible-core.orig/lib/ansible/module_utils/basic.py
+++ ansible-core/lib/ansible/module_utils/basic.py
@@ -1598,6 +1598,7 @@ class AnsibleModule(object):
                 dest_stat = os.stat(b_dest)
                 os.chown(b_src, dest_stat.st_uid, dest_stat.st_gid)
                 shutil.copystat(b_dest, b_src)
+                os.utime(b_src, (time.time(), time.time()))
             except OSError as e:
                 if e.errno != errno.EPERM:
                     raise
@@ -1645,14 +1646,14 @@ class AnsibleModule(object):
                             os.close(tmp_dest_fd)
                             # leaves tmp file behind when sudo and not root
                             try:
-                                shutil.move(b_src, b_tmp_dest_name, 
copy_function=shutil.copy if keep_dest_attrs else shutil.copy2)
+                                shutil.move(b_src, b_tmp_dest_name, 
copy_function=shutil.copy2 if keep_dest_attrs else shutil.copy)
                             except OSError:
                                 # cleanup will happen by 'rm' of tmpdir
                                 # copy2 will preserve some metadata
                                 if keep_dest_attrs:
-                                    shutil.copy(b_src, b_tmp_dest_name)
-                                else:
                                     shutil.copy2(b_src, b_tmp_dest_name)
+                                else:
+                                    shutil.copy(b_src, b_tmp_dest_name)
 
                             if self.selinux_enabled():
                                 self.set_context_if_different(
@@ -1661,6 +1662,8 @@ class AnsibleModule(object):
                                 tmp_stat = os.stat(b_tmp_dest_name)
                                 if keep_dest_attrs and dest_stat and 
(tmp_stat.st_uid != dest_stat.st_uid or tmp_stat.st_gid != dest_stat.st_gid):
                                     os.chown(b_tmp_dest_name, 
dest_stat.st_uid, dest_stat.st_gid)
+                                if keep_dest_attrs:
+                                    os.utime(b_tmp_dest_name, (time.time(), 
time.time()))
                             except OSError as e:
                                 if e.errno != errno.EPERM:
                                     raise

Reply via email to