Fix for atomic_move on RHEL5
When becoming an unprivileged user using non-sudo on a platform where
getlogin() failed in our situation we were not able to detect that the
user had switched. This meant that all of our logic to use move vs copy
if the user had switched was attempting the wrong thing. This change
tries the to do the right thing but then falls back to an acceptable
second choice if it doesn't work.
The bug wasn't easily detected because:
* sudo was not affected because sudo records that the user's have been
switched so we were able to detect that.
* getlogin() works on most platforms. RHEL5 with python-2.4 seems to be
the only platform we still care about where getlogin() fails for this
case.
* It had to be becoming an unprivileged user. When becoming
a privileged user, the user would be able to successfully perform the
best case tasks.
(cherry picked from commit 02e3f4b526
)
This commit is contained in:
parent
e223349edc
commit
8439d1813e
1 changed files with 9 additions and 16 deletions
|
@ -1926,18 +1926,6 @@ class AnsibleModule(object):
|
||||||
|
|
||||||
creating = not os.path.exists(b_dest)
|
creating = not os.path.exists(b_dest)
|
||||||
|
|
||||||
try:
|
|
||||||
login_name = os.getlogin()
|
|
||||||
except OSError:
|
|
||||||
# not having a tty can cause the above to fail, so
|
|
||||||
# just get the LOGNAME environment variable instead
|
|
||||||
login_name = os.environ.get('LOGNAME', None)
|
|
||||||
|
|
||||||
# if the original login_name doesn't match the currently
|
|
||||||
# logged-in user, or if the SUDO_USER environment variable
|
|
||||||
# is set, then this user has switched their credentials
|
|
||||||
switched_user = login_name and login_name != pwd.getpwuid(os.geteuid())[0] or os.environ.get('SUDO_USER')
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Optimistically try a rename, solves some corner cases and can avoid useless work, throws exception if not atomic.
|
# Optimistically try a rename, solves some corner cases and can avoid useless work, throws exception if not atomic.
|
||||||
os.rename(b_src, b_dest)
|
os.rename(b_src, b_dest)
|
||||||
|
@ -1976,12 +1964,13 @@ class AnsibleModule(object):
|
||||||
# close tmp file handle before file operations to prevent text file busy errors on vboxfs synced folders (windows host)
|
# close tmp file handle before file operations to prevent text file busy errors on vboxfs synced folders (windows host)
|
||||||
os.close(tmp_dest_fd)
|
os.close(tmp_dest_fd)
|
||||||
# leaves tmp file behind when sudo and not root
|
# leaves tmp file behind when sudo and not root
|
||||||
if switched_user and os.geteuid() != 0:
|
try:
|
||||||
|
shutil.move(b_src, b_tmp_dest_name)
|
||||||
|
except OSError:
|
||||||
# cleanup will happen by 'rm' of tempdir
|
# cleanup will happen by 'rm' of tempdir
|
||||||
# copy2 will preserve some metadata
|
# copy2 will preserve some metadata
|
||||||
shutil.copy2(b_src, b_tmp_dest_name)
|
shutil.copy2(b_src, b_tmp_dest_name)
|
||||||
else:
|
|
||||||
shutil.move(b_src, b_tmp_dest_name)
|
|
||||||
if self.selinux_enabled():
|
if self.selinux_enabled():
|
||||||
self.set_context_if_different(
|
self.set_context_if_different(
|
||||||
b_tmp_dest_name, context, False)
|
b_tmp_dest_name, context, False)
|
||||||
|
@ -2013,8 +2002,12 @@ class AnsibleModule(object):
|
||||||
umask = os.umask(0)
|
umask = os.umask(0)
|
||||||
os.umask(umask)
|
os.umask(umask)
|
||||||
os.chmod(b_dest, DEFAULT_PERM & ~umask)
|
os.chmod(b_dest, DEFAULT_PERM & ~umask)
|
||||||
if switched_user:
|
try:
|
||||||
os.chown(b_dest, os.geteuid(), os.getegid())
|
os.chown(b_dest, os.geteuid(), os.getegid())
|
||||||
|
except OSError:
|
||||||
|
# We're okay with trying our best here. If the user is not
|
||||||
|
# root (or old Unices) they won't be able to chown.
|
||||||
|
pass
|
||||||
|
|
||||||
if self.selinux_enabled():
|
if self.selinux_enabled():
|
||||||
# rename might not preserve context
|
# rename might not preserve context
|
||||||
|
|
Loading…
Reference in a new issue