Repository: ansible/ansible

Issue:
2.5.0a1 has permission failures for tasks with escalation and deep remote_tmp directories
<!---
Verify first that your issue/request is not already reported on GitHub.
Also test if the latest release, and master branch are affected too.
-->

##### ISSUE TYPE
 - Bug Report

##### COMPONENT NAME
Privilege escalation and/or remote_tmp

##### ANSIBLE VERSION
<!--- Paste verbatim output from "ansible --version" between quotes below -->
```
$ PYTHONPATH=~/ansible-2.5.0a1/lib ~/ansible-2.5.0a1/bin/ansible --version
ansible 2.5.0a1
  config file = /home/centos/ansible.cfg
  configured module search path = [u'/home/centos/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /home/centos/ansible-2.5.0a1/lib/ansible
  executable location = /home/centos/ansible-2.5.0a1/bin/ansible
  python version = 2.7.5 (default, Nov  6 2016, 00:28:07) [GCC 4.8.5 20150623 (Red Hat 4.8.5-11)]
$
```

##### CONFIGURATION
DEFAULT_REMOTE_TMP(/home/centos/ansible.cfg) = /tmp/.ansible/tmp

##### OS / ENVIRONMENT
CentOS 7.3

##### SUMMARY
Prior to 2.5, tasks run with privilege escalation did not use remote_tmp for their temporary files.  At 2.5, remote_tmp is used for tasks run with escalation.  The problem surfaces when remote_tmp has multiple levels, since the temporary directory path is created with a 77 umask, and in the setfacl command only the file and its housing directory are opened to the escalation user.  The intervening directory path levels are not opened, and therefore the escalation user cannot traverse the path to see the temporary file.

I looked in https://docs.ansible.com/ansible/devel/porting_guide_2.5.html and did not see any details on this change.  If it's intended, I'd recommend adding information to the porting guide so that users are aware they need to pre-create that directory with appropriate permissions.

##### STEPS TO REPRODUCE
inventory.ini
```
target ansible_connection=local
```

playbook.yml
```yaml
---
- hosts: all
  tasks:
  - debug:
      var: ansible_version.full
  - name: By default user
    stat:
      path: /etc/passwd
  - name: By another user
    become: true
    become_user: another
    stat:
      path: /etc/passwd
```

Invocation:
```
ansible-playbook -i inventory.ini playbook.yml -vvv
```

##### EXPECTED RESULTS
In 2.4 - note the location of the temporary stat.py file in the two tasks:
```
$ ansible-playbook -i inventory.ini playbook.yml -vvv
ansible-playbook 2.4.2.0
  config file = /home/centos/ansible.cfg
  configured module search path = [u'/home/centos/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/site-packages/ansible
  executable location = /usr/bin/ansible-playbook
  python version = 2.7.5 (default, Nov  6 2016, 00:28:07) [GCC 4.8.5 20150623 (Red Hat 4.8.5-11)]
Using /home/centos/ansible.cfg as config file
Parsed /home/centos/inventory.ini inventory source with ini plugin

PLAYBOOK: playbook.yml *************************************************************************************************
1 plays in playbook.yml

PLAY [all] *************************************************************************************************************

TASK [Gathering Facts] *************************************************************************************************
Using module file /usr/lib/python2.7/site-packages/ansible/modules/system/setup.py
<target> ESTABLISH LOCAL CONNECTION FOR USER: centos
<target> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /tmp/.ansible/tmp/ansible-tmp-1517594420.44-45608866704030 `" && echo ansible-tmp-1517594420.44-45608866704030="` echo /tmp/.ansible/tmp/ansible-tmp-1517594420.44-45608866704030 `" ) && sleep 0'
<target> PUT /tmp/tmpwDBrJn TO /tmp/.ansible/tmp/ansible-tmp-1517594420.44-45608866704030/setup.py
<target> EXEC /bin/sh -c 'chmod u+x /tmp/.ansible/tmp/ansible-tmp-1517594420.44-45608866704030/ /tmp/.ansible/tmp/ansible-tmp-1517594420.44-45608866704030/setup.py && sleep 0'
<target> EXEC /bin/sh -c '/usr/bin/python /tmp/.ansible/tmp/ansible-tmp-1517594420.44-45608866704030/setup.py; rm -rf "/tmp/.ansible/tmp/ansible-tmp-1517594420.44-45608866704030/" > /dev/null 2>&1 && sleep 0'
ok: [target]
META: ran handlers

TASK [debug] ***********************************************************************************************************
task path: /home/centos/playbook.yml:4
ok: [target] => {
    "ansible_version.full": "2.4.2.0"
}

TASK [By default user] *************************************************************************************************
task path: /home/centos/playbook.yml:6
Using module file /usr/lib/python2.7/site-packages/ansible/modules/files/stat.py
<target> ESTABLISH LOCAL CONNECTION FOR USER: centos
<target> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /tmp/.ansible/tmp/ansible-tmp-1517594420.94-194928894376484 `" && echo ansible-tmp-1517594420.94-194928894376484="` echo /tmp/.ansible/tmp/ansible-tmp-1517594420.94-194928894376484 `" ) && sleep 0'
<target> PUT /tmp/tmpm4dXn2 TO /tmp/.ansible/tmp/ansible-tmp-1517594420.94-194928894376484/stat.py
<target> EXEC /bin/sh -c 'chmod u+x /tmp/.ansible/tmp/ansible-tmp-1517594420.94-194928894376484/ /tmp/.ansible/tmp/ansible-tmp-1517594420.94-194928894376484/stat.py && sleep 0'
<target> EXEC /bin/sh -c '/usr/bin/python /tmp/.ansible/tmp/ansible-tmp-1517594420.94-194928894376484/stat.py; rm -rf "/tmp/.ansible/tmp/ansible-tmp-1517594420.94-194928894376484/" > /dev/null 2>&1 && sleep 0'
ok: [target] => {
    "changed": false,
    "invocation": {
        "module_args": {
            "checksum_algorithm": "sha1",
            "follow": false,
            "get_attributes": true,
            "get_checksum": true,
            "get_md5": true,
            "get_mime": true,
            "path": "/etc/passwd"
        }
    },
    "stat": {
        "atime": 1517593281.3711314,
        "attr_flags": "",
        "attributes": [],
        "block_size": 4096,
        "blocks": 8,
        "charset": "us-ascii",
        "checksum": "ba2e16c70901bb87f3ee0e9567a37d4b832506be",
        "ctime": 1517593278.6579702,
        "dev": 64769,
        "device_type": 0,
        "executable": false,
        "exists": true,
        "gid": 0,
        "gr_name": "root",
        "inode": 580,
        "isblk": false,
        "ischr": false,
        "isdir": false,
        "isfifo": false,
        "isgid": false,
        "islnk": false,
        "isreg": true,
        "issock": false,
        "isuid": false,
        "md5": "68535ce1aeea50ae3f728be5f91bcbac",
        "mimetype": "text/plain",
        "mode": "0644",
        "mtime": 1517593278.65697,
        "nlink": 1,
        "path": "/etc/passwd",
        "pw_name": "root",
        "readable": true,
        "rgrp": true,
        "roth": true,
        "rusr": true,
        "size": 1294,
        "uid": 0,
        "version": "1926096780",
        "wgrp": false,
        "woth": false,
        "writeable": false,
        "wusr": true,
        "xgrp": false,
        "xoth": false,
        "xusr": false
    }
}

TASK [By another user] *************************************************************************************************
task path: /home/centos/playbook.yml:9
Using module file /usr/lib/python2.7/site-packages/ansible/modules/files/stat.py
<target> ESTABLISH LOCAL CONNECTION FOR USER: centos
<target> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /tmp/ansible-tmp-1517594421.13-240886974687097 `" && echo ansible-tmp-1517594421.13-240886974687097="` echo /tmp/ansible-tmp-1517594421.13-240886974687097 `" ) && sleep 0'
<target> PUT /tmp/tmprihIRB TO /tmp/ansible-tmp-1517594421.13-240886974687097/stat.py
<target> EXEC /bin/sh -c 'setfacl -m u:another:r-x /tmp/ansible-tmp-1517594421.13-240886974687097/ /tmp/ansible-tmp-1517594421.13-240886974687097/stat.py && sleep 0'
<target> EXEC /bin/sh -c 'sudo -H -S -n -u another /bin/sh -c '"'"'echo BECOME-SUCCESS-wjbvthoyqutbuubbinqjdaqqdxxeafvs; /usr/bin/python /tmp/ansible-tmp-1517594421.13-240886974687097/stat.py'"'"' && sleep 0'
<target> EXEC /bin/sh -c 'rm -f -r /tmp/ansible-tmp-1517594421.13-240886974687097/ > /dev/null 2>&1 && sleep 0'
ok: [target] => {
    "changed": false,
    "invocation": {
        "module_args": {
            "checksum_algorithm": "sha1",
            "follow": false,
            "get_attributes": true,
            "get_checksum": true,
            "get_md5": true,
            "get_mime": true,
            "path": "/etc/passwd"
        }
    },
    "stat": {
        "atime": 1517593281.3711314,
        "attr_flags": "",
        "attributes": [],
        "block_size": 4096,
        "blocks": 8,
        "charset": "us-ascii",
        "checksum": "ba2e16c70901bb87f3ee0e9567a37d4b832506be",
        "ctime": 1517593278.6579702,
        "dev": 64769,
        "device_type": 0,
        "executable": false,
        "exists": true,
        "gid": 0,
        "gr_name": "root",
        "inode": 580,
        "isblk": false,
        "ischr": false,
        "isdir": false,
        "isfifo": false,
        "isgid": false,
        "islnk": false,
        "isreg": true,
        "issock": false,
        "isuid": false,
        "md5": "68535ce1aeea50ae3f728be5f91bcbac",
        "mimetype": "text/plain",
        "mode": "0644",
        "mtime": 1517593278.65697,
        "nlink": 1,
        "path": "/etc/passwd",
        "pw_name": "root",
        "readable": true,
        "rgrp": true,
        "roth": true,
        "rusr": true,
        "size": 1294,
        "uid": 0,
        "version": "1926096780",
        "wgrp": false,
        "woth": false,
        "writeable": false,
        "wusr": true,
        "xgrp": false,
        "xoth": false,
        "xusr": false
    }
}
META: ran handlers
META: ran handlers

PLAY RECAP *************************************************************************************************************
target                     : ok=4    changed=0    unreachable=0    failed=0

$
```

##### ACTUAL RESULTS
In 2.5.0a1 - note the (new) location of the temporary stat.py file for the task with escalation:
```
$ PYTHONPATH=~/ansible-2.5.0a1/lib ~/ansible-2.5.0a1/bin/ansible-playbook -i inventory.ini playbook.yml -vvv
ansible-playbook 2.5.0a1
  config file = /home/centos/ansible.cfg
  configured module search path = [u'/home/centos/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /home/centos/ansible-2.5.0a1/lib/ansible
  executable location = /home/centos/ansible-2.5.0a1/bin/ansible-playbook
  python version = 2.7.5 (default, Nov  6 2016, 00:28:07) [GCC 4.8.5 20150623 (Red Hat 4.8.5-11)]
Using /home/centos/ansible.cfg as config file
Parsed /home/centos/inventory.ini inventory source with ini plugin

PLAYBOOK: playbook.yml *************************************************************************************************
1 plays in playbook.yml

PLAY [all] *************************************************************************************************************

TASK [Gathering Facts] *************************************************************************************************
task path: /home/centos/playbook.yml:2
Using module file /home/centos/ansible-2.5.0a1/lib/ansible/modules/system/setup.py
<target> ESTABLISH LOCAL CONNECTION FOR USER: centos
<target> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /tmp/.ansible/tmp/ansible-tmp-1517594570.5-104128906955238 `" && echo ansible-tmp-1517594570.5-104128906955238="` echo /tmp/.ansible/tmp/ansible-tmp-1517594570.5-104128906955238 `" ) && sleep 0'
<target> PUT /home/centos/.ansible/tmp/ansible-local-10392d8N5Y7/tmpz8S7wZ TO /tmp/.ansible/tmp/ansible-tmp-1517594570.5-104128906955238/setup.py
<target> EXEC /bin/sh -c 'chmod u+x /tmp/.ansible/tmp/ansible-tmp-1517594570.5-104128906955238/ /tmp/.ansible/tmp/ansible-tmp-1517594570.5-104128906955238/setup.py && sleep 0'
<target> EXEC /bin/sh -c '/usr/bin/python /tmp/.ansible/tmp/ansible-tmp-1517594570.5-104128906955238/setup.py && sleep 0'
ok: [target]
META: ran handlers

TASK [debug] ***********************************************************************************************************
task path: /home/centos/playbook.yml:4
ok: [target] => {
    "ansible_version.full": "2.5.0a1",
    "failed": false
}

TASK [By default user] *************************************************************************************************
task path: /home/centos/playbook.yml:6
Using module file /home/centos/ansible-2.5.0a1/lib/ansible/modules/files/stat.py
<target> ESTABLISH LOCAL CONNECTION FOR USER: centos
<target> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /tmp/.ansible/tmp/ansible-tmp-1517594571.1-261063266807317 `" && echo ansible-tmp-1517594571.1-261063266807317="` echo /tmp/.ansible/tmp/ansible-tmp-1517594571.1-261063266807317 `" ) && sleep 0'
<target> PUT /home/centos/.ansible/tmp/ansible-local-10392d8N5Y7/tmpxOtm2T TO /tmp/.ansible/tmp/ansible-tmp-1517594571.1-261063266807317/stat.py
<target> EXEC /bin/sh -c 'chmod u+x /tmp/.ansible/tmp/ansible-tmp-1517594571.1-261063266807317/ /tmp/.ansible/tmp/ansible-tmp-1517594571.1-261063266807317/stat.py && sleep 0'
<target> EXEC /bin/sh -c '/usr/bin/python /tmp/.ansible/tmp/ansible-tmp-1517594571.1-261063266807317/stat.py && sleep 0'
ok: [target] => {
    "changed": false,
    "failed": false,
    "invocation": {
        "module_args": {
            "checksum_algorithm": "sha1",
            "follow": false,
            "get_attributes": true,
            "get_checksum": true,
            "get_md5": null,
            "get_mime": true,
            "path": "/etc/passwd"
        }
    },
    "stat": {
        "atime": 1517593281.3711314,
        "attr_flags": "",
        "attributes": [],
        "block_size": 4096,
        "blocks": 8,
        "charset": "us-ascii",
        "checksum": "ba2e16c70901bb87f3ee0e9567a37d4b832506be",
        "ctime": 1517593278.6579702,
        "dev": 64769,
        "device_type": 0,
        "executable": false,
        "exists": true,
        "gid": 0,
        "gr_name": "root",
        "inode": 580,
        "isblk": false,
        "ischr": false,
        "isdir": false,
        "isfifo": false,
        "isgid": false,
        "islnk": false,
        "isreg": true,
        "issock": false,
        "isuid": false,
        "mimetype": "text/plain",
        "mode": "0644",
        "mtime": 1517593278.65697,
        "nlink": 1,
        "path": "/etc/passwd",
        "pw_name": "root",
        "readable": true,
        "rgrp": true,
        "roth": true,
        "rusr": true,
        "size": 1294,
        "uid": 0,
        "version": "1926096780",
        "wgrp": false,
        "woth": false,
        "writeable": false,
        "wusr": true,
        "xgrp": false,
        "xoth": false,
        "xusr": false
    }
}

TASK [By another user] *************************************************************************************************
task path: /home/centos/playbook.yml:9
Using module file /home/centos/ansible-2.5.0a1/lib/ansible/modules/files/stat.py
<target> ESTABLISH LOCAL CONNECTION FOR USER: centos
<target> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /tmp/.ansible/tmp/ansible-tmp-1517594571.34-218737698964584 `" && echo ansible-tmp-1517594571.34-218737698964584="` echo /tmp/.ansible/tmp/ansible-tmp-1517594571.34-218737698964584 `" ) && sleep 0'
<target> PUT /home/centos/.ansible/tmp/ansible-local-10392d8N5Y7/tmpERvLJE TO /tmp/.ansible/tmp/ansible-tmp-1517594571.34-218737698964584/stat.py
<target> EXEC /bin/sh -c 'setfacl -m u:another:r-x /tmp/.ansible/tmp/ansible-tmp-1517594571.34-218737698964584/ /tmp/.ansible/tmp/ansible-tmp-1517594571.34-218737698964584/stat.py && sleep 0'
<target> EXEC /bin/sh -c 'sudo -H -S -n -u another /bin/sh -c '"'"'echo BECOME-SUCCESS-zjbjrcfigbhkmdbggzgemcopkctdayce; /usr/bin/python /tmp/.ansible/tmp/ansible-tmp-1517594571.34-218737698964584/stat.py'"'"' && sleep 0'
fatal: [target]: FAILED! => {
    "changed": false,
    "failed": true,
    "module_stderr": "/usr/bin/python: can't open file '/tmp/.ansible/tmp/ansible-tmp-1517594571.34-218737698964584/stat.py': [Errno 13] Permission denied\n",
    "module_stdout": "",
    "msg": "MODULE FAILURE",
    "rc": 2
}
        to retry, use: --limit @/home/centos/playbook.retry

PLAY RECAP *************************************************************************************************************
target                     : ok=3    changed=0    unreachable=0    failed=1

$
```

And, as expected, if the remote_tmp directory is pre-created with open permissions, things work smoothly:
```
$ rm -rf /tmp/.ansible
$ mkdir -p /tmp/.ansible/tmp
$ chmod -R go+rx /tmp/.ansible
$ PYTHONPATH=~/ansible-2.5.0a1/lib ~/ansible-2.5.0a1/bin/ansible-playbook -i inventory.ini playbook.yml -vvv
ansible-playbook 2.5.0a1
  config file = /home/centos/ansible.cfg
  configured module search path = [u'/home/centos/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /home/centos/ansible-2.5.0a1/lib/ansible
  executable location = /home/centos/ansible-2.5.0a1/bin/ansible-playbook
  python version = 2.7.5 (default, Nov  6 2016, 00:28:07) [GCC 4.8.5 20150623 (Red Hat 4.8.5-11)]
Using /home/centos/ansible.cfg as config file
Parsed /home/centos/inventory.ini inventory source with ini plugin

PLAYBOOK: playbook.yml *************************************************************************************************
1 plays in playbook.yml

PLAY [all] *************************************************************************************************************

TASK [Gathering Facts] *************************************************************************************************
task path: /home/centos/playbook.yml:2
Using module file /home/centos/ansible-2.5.0a1/lib/ansible/modules/system/setup.py
<target> ESTABLISH LOCAL CONNECTION FOR USER: centos
<target> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /tmp/.ansible/tmp/ansible-tmp-1517595030.28-44435638468763 `" && echo ansible-tmp-1517595030.28-44435638468763="` echo /tmp/.ansible/tmp/ansible-tmp-1517595030.28-44435638468763 `" ) && sleep 0'
<target> PUT /home/centos/.ansible/tmp/ansible-local-10475LsnczJ/tmpFqXxn3 TO /tmp/.ansible/tmp/ansible-tmp-1517595030.28-44435638468763/setup.py
<target> EXEC /bin/sh -c 'chmod u+x /tmp/.ansible/tmp/ansible-tmp-1517595030.28-44435638468763/ /tmp/.ansible/tmp/ansible-tmp-1517595030.28-44435638468763/setup.py && sleep 0'
<target> EXEC /bin/sh -c '/usr/bin/python /tmp/.ansible/tmp/ansible-tmp-1517595030.28-44435638468763/setup.py && sleep 0'
ok: [target]
META: ran handlers

TASK [debug] ***********************************************************************************************************
task path: /home/centos/playbook.yml:4
ok: [target] => {
    "ansible_version.full": "2.5.0a1",
    "failed": false
}

TASK [By default user] *************************************************************************************************
task path: /home/centos/playbook.yml:6
Using module file /home/centos/ansible-2.5.0a1/lib/ansible/modules/files/stat.py
<target> ESTABLISH LOCAL CONNECTION FOR USER: centos
<target> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /tmp/.ansible/tmp/ansible-tmp-1517595030.9-99646778340200 `" && echo ansible-tmp-1517595030.9-99646778340200="` echo /tmp/.ansible/tmp/ansible-tmp-1517595030.9-99646778340200 `" ) && sleep 0'
<target> PUT /home/centos/.ansible/tmp/ansible-local-10475LsnczJ/tmpSZoeva TO /tmp/.ansible/tmp/ansible-tmp-1517595030.9-99646778340200/stat.py
<target> EXEC /bin/sh -c 'chmod u+x /tmp/.ansible/tmp/ansible-tmp-1517595030.9-99646778340200/ /tmp/.ansible/tmp/ansible-tmp-1517595030.9-99646778340200/stat.py && sleep 0'
<target> EXEC /bin/sh -c '/usr/bin/python /tmp/.ansible/tmp/ansible-tmp-1517595030.9-99646778340200/stat.py && sleep 0'
ok: [target] => {
    "changed": false,
    "failed": false,
    "invocation": {
        "module_args": {
            "checksum_algorithm": "sha1",
            "follow": false,
            "get_attributes": true,
            "get_checksum": true,
            "get_md5": null,
            "get_mime": true,
            "path": "/etc/passwd"
        }
    },
    "stat": {
        "atime": 1517593281.3711314,
        "attr_flags": "",
        "attributes": [],
        "block_size": 4096,
        "blocks": 8,
        "charset": "us-ascii",
        "checksum": "ba2e16c70901bb87f3ee0e9567a37d4b832506be",
        "ctime": 1517593278.6579702,
        "dev": 64769,
        "device_type": 0,
        "executable": false,
        "exists": true,
        "gid": 0,
        "gr_name": "root",
        "inode": 580,
        "isblk": false,
        "ischr": false,
        "isdir": false,
        "isfifo": false,
        "isgid": false,
        "islnk": false,
        "isreg": true,
        "issock": false,
        "isuid": false,
        "mimetype": "text/plain",
        "mode": "0644",
        "mtime": 1517593278.65697,
        "nlink": 1,
        "path": "/etc/passwd",
        "pw_name": "root",
        "readable": true,
        "rgrp": true,
        "roth": true,
        "rusr": true,
        "size": 1294,
        "uid": 0,
        "version": "1926096780",
        "wgrp": false,
        "woth": false,
        "writeable": false,
        "wusr": true,
        "xgrp": false,
        "xoth": false,
        "xusr": false
    }
}

TASK [By another user] *************************************************************************************************
task path: /home/centos/playbook.yml:9
Using module file /home/centos/ansible-2.5.0a1/lib/ansible/modules/files/stat.py
<target> ESTABLISH LOCAL CONNECTION FOR USER: centos
<target> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /tmp/.ansible/tmp/ansible-tmp-1517595031.16-129894368361590 `" && echo ansible-tmp-1517595031.16-129894368361590="` echo /tmp/.ansible/tmp/ansible-tmp-1517595031.16-129894368361590 `" ) && sleep 0'
<target> PUT /home/centos/.ansible/tmp/ansible-local-10475LsnczJ/tmpgKwcoI TO /tmp/.ansible/tmp/ansible-tmp-1517595031.16-129894368361590/stat.py
<target> EXEC /bin/sh -c 'setfacl -m u:another:r-x /tmp/.ansible/tmp/ansible-tmp-1517595031.16-129894368361590/ /tmp/.ansible/tmp/ansible-tmp-1517595031.16-129894368361590/stat.py && sleep 0'
<target> EXEC /bin/sh -c 'sudo -H -S -n -u another /bin/sh -c '"'"'echo BECOME-SUCCESS-wbygvqvwbpclvulchtoknxdeumtvjsta; /usr/bin/python /tmp/.ansible/tmp/ansible-tmp-1517595031.16-129894368361590/stat.py'"'"' && sleep 0'
ok: [target] => {
    "changed": false,
    "failed": false,
    "invocation": {
        "module_args": {
            "checksum_algorithm": "sha1",
            "follow": false,
            "get_attributes": true,
            "get_checksum": true,
            "get_md5": null,
            "get_mime": true,
            "path": "/etc/passwd"
        }
    },
    "stat": {
        "atime": 1517593281.3711314,
        "attr_flags": "",
        "attributes": [],
        "block_size": 4096,
        "blocks": 8,
        "charset": "us-ascii",
        "checksum": "ba2e16c70901bb87f3ee0e9567a37d4b832506be",
        "ctime": 1517593278.6579702,
        "dev": 64769,
        "device_type": 0,
        "executable": false,
        "exists": true,
        "gid": 0,
        "gr_name": "root",
        "inode": 580,
        "isblk": false,
        "ischr": false,
        "isdir": false,
        "isfifo": false,
        "isgid": false,
        "islnk": false,
        "isreg": true,
        "issock": false,
        "isuid": false,
        "mimetype": "text/plain",
        "mode": "0644",
        "mtime": 1517593278.65697,
        "nlink": 1,
        "path": "/etc/passwd",
        "pw_name": "root",
        "readable": true,
        "rgrp": true,
        "roth": true,
        "rusr": true,
        "size": 1294,
        "uid": 0,
        "version": "1926096780",
        "wgrp": false,
        "woth": false,
        "writeable": false,
        "wusr": true,
        "xgrp": false,
        "xoth": false,
        "xusr": false
    }
}
META: ran handlers
META: ran handlers

PLAY RECAP *************************************************************************************************************
target                     : ok=4    changed=0    unreachable=0    failed=0

$
```


Discussion:
Files identified in the description:
None

If these files are inaccurate, please update the `component name` section of the description or use the `!component` bot command.

[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: components_banner --->
cc'ing @abadger @bcoca
The same behavior exists in 2.5.0b1.
@bcoca Looks like you need to call setfacl on a higher directory to make unified temp work.
I mean, call fixup_perms2() on a higher directory so that it calls setfacl on the higher dir.
@bcoca I'm wrong.  Since DEFAULT_REMOTE_TMP(/home/centos/ansible.cfg) = /tmp/.ansible/tmp is being set, then we don't want to call fixup_perms on the higher level directories.  Seems like this is a case where we need to fallback on the system temp but 2.5 is using the remote_temp setting instead.
That code should work the same, quick look the fallback when remote_user is non-admin still there, but we did change to include configurable list (more than 'root'). Queued for testing.
I have been unable to reproduce this,  my tests show it using a system dir (correctly), looked at verbose output above and that seems to still be correct:

```
/usr/bin/python /tmp/.ansible/tmp/ansible-tmp-1517594420.94-194928894376484/stat.py; 
rm -rf `"/tmp/.ansible/tmp/ansible-tmp-1517594420.94-194928894376484/
```

even on the failed one, this is a 'system temp directory'
```
"module_stderr": "/usr/bin/python: can't open file '/tmp/.ansible/tmp/ansible-tmp-1517594571.34-218737698964584/stat.py': [Errno 13] Permission denied\n",

```

So the problem seems ONLY to affect when the remote_tmp IS a system tmp dir and was already created for the specific user with restrictive permissions, but this should not happen during normal operations.

Resolving patch:
diff --git a/lib/ansible/plugins/shell/__init__.py b/lib/ansible/plugins/shell/__init__.py
--- a/lib/ansible/plugins/shell/__init__.py
+++ b/lib/ansible/plugins/shell/__init__.py
@@ -24,8 +24,10 @@
 import time
 
 import ansible.constants as C
+from ansible.errors import AnsibleError
 from ansible.module_utils.six import text_type
 from ansible.module_utils.six.moves import shlex_quote
+from ansible.module_utils._text import to_native
 from ansible.plugins import AnsiblePlugin
 
 _USER_HOME_PATH_RE = re.compile(r'^~[_.A-Za-z0-9][-_.A-Za-z0-9]*$')
@@ -52,6 +54,19 @@ def set_options(self, task_keys=None, var_options=None, direct=None):
         # set env
         self.env.update(self.get_option('environment'))
 
+        # Normalize the temp directory strings. We don't use expanduser/expandvars because those
+        # can vary between remote user and become user.  Therefore the safest practice will be for
+        # this to always be specified as full paths)
+        normalized_system_temps = [d.rstrip('/') for d in self.get_option('system_temps')]
+
+        # Make sure all system_temps are absolute otherwise they'd be relative to the login dir
+        # which is almost certainly going to fail in a cornercase.
+        if not all(os.path.isabs(d) for d in normalized_system_temps):
+            raise AnsibleError('The configured system_temps contains a relative path: {0}. All'
+                               ' system_temps must be absolute'.format(to_native(normalized_system_temps)))
+
+        self.set_option('system_temps', normalized_system_temps)
+
     def env_prefix(self, **kwargs):
         return ' '.join(['%s=%s' % (k, shlex_quote(text_type(v))) for k, v in kwargs.items()])
 
@@ -113,7 +128,9 @@ def mkdtemp(self, basefile=None, system=False, mode=0o700, tmpdir=None):
         # passed in tmpdir if it is valid or the first one from the setting if not.
 
         if system:
-            if tmpdir.startswith(tuple(self.get_option('system_temps'))):
+            tmpdir = tmpdir.rstrip('/')
+
+            if tmpdir in self.get_option('system_temps'):
                 basetmpdir = tmpdir
             else:
                 basetmpdir = self.get_option('system_temps')[0]
diff --git a/lib/ansible/plugins/shell/powershell.py b/lib/ansible/plugins/shell/powershell.py
--- a/lib/ansible/plugins/shell/powershell.py
+++ b/lib/ansible/plugins/shell/powershell.py
@@ -1823,6 +1823,13 @@ class ShellModule(ShellBase):
 
     # TODO: add binary module support
 
+    def set_options(self, task_keys=None, var_options=None, direct=None):
+
+        super(ShellModule, self).set_options(task_keys=task_keys, var_options=var_options, direct=direct)
+
+        # set env
+        self.env.update(self.get_option('environment'))
+
     def assert_safe_env_key(self, key):
         if not self.safe_envkey.match(key):
             raise AnsibleError("Invalid PowerShell environment key: %s" % key)


Test patch: