Ansible copy module fails with “Invalid cross-device link” followed by “Operation not permitted” when copying into hardened /etc directory with become
Hello,
I’m encountering a failure with the Ansible copy module when copying a file into a hardened system directory. I would like to confirm whether this is expected behavior or a configuration issue.
Environment
- Ansible core version:
2.16.14 - AWX execution environment
- Target OS: RHEL-based hardened image
- Connection user:
efv-ansible - Privilege escalation:
become: true(sudo, passwordless) - SELinux: Disabled
- Filesystem: standard ext4/xfs
- Destination path:
/etc/common/swid
- name: Copy SWID file
copy:
src: secure-standard-build.swidtag
dest: /etc/common/swid
owner: root
group: root
mode: '0600'
become: true
error on my AWX:
diff: []
exception: >
Traceback (most recent call last):
File "/tmp/ansible_ansible.legacy.copy_payload_x_qms_48/ansible_ansible.legacy.copy_payload.zip/ansible/module_utils/basic.py", line 1690, in atomic_move
os.rename(b_src, b_dest)
OSError: [Errno 18] Invalid cross-device link:
b'/home/efv-ansible/.ansible/tmp/ansible-tmp-1770408721.4119422-4350-152331924043449/source'
-> b'/etc/common/swid/secure-standard-build.swidtag'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/tmp/ansible_ansible.legacy.copy_payload_x_qms_48/ansible_ansible.legacy.copy_payload.zip/ansible/module_utils/basic.py", line 1741, in atomic_move
os.rename(b_tmp_dest_name, b_dest)
PermissionError: [Errno 1] Operation not permitted:
b'/etc/common/swid/.ansible_tmp1f2s3zacsecure-standard-build.swidtag'
-> b'/etc/common/swid/secure-standard-build.swidtag'
msg: >-
Unable to make
b'/home/efv-ansible/.ansible/tmp/ansible-tmp-1770408721.4119422-4350-152331924043449/source'
into to /etc/common/swid/secure-standard-build.swidtag, failed final
rename from
b'/etc/common/swid/.ansible_tmp1f2s3zacsecure-standard-build.swidtag':
[Errno 1] Operation not permitted:
b'/etc/common/swid/.ansible_tmp1f2s3zacsecure-standard-build.swidtag'
-> b'/etc/common/swid/secure-standard-build.swidtag'
invocation:
module_args:
src: >-
/home/efv-ansible/.ansible/tmp/ansible-tmp-1770408721.4119422-4350-152331924043449/source
dest: /etc/common/swid
owner: root
group: root
mode: '0600'
_original_basename:secure-standard-build.swidtag
follow: false
checksum: 1c23f81499fa5752a57539170b898f084500728d
backup: false
force: true
unsafe_writes: false
checksum: 1c23f81499fa5752a57539170b898f084500728d
_ansible_no_log: false
changed: false
Observations / Validation already done
- Destination directory exists and is writable by root
- No ACL restrictions
- Sudo escalation confirmed
sudo -l -U efv-ansible
(ALL) NOPASSWD: ALL
Current Understanding
From debugging, it appears:
- Ansible creates temporary files under:
/home/efv-ansible/.ansible/tmp - The copy module then performs an atomic rename into
/etc/... - The system rejects the rename operation with
Operation not permitted
This seems related to the temp file being created as the connection user rather than root prior to privilege escalation.