Repository: ansible/ansible

Issue:
privilege escalation disables pipelining on v2.
Given this playbok:

```

---
- hosts: all
  become: yes
  tasks:
  - name: whoami
    command: whoami
```

results in:

```
TASK: [whoami] **************************************************************** 
<127.0.0.2> ESTABLISH CONNECTION FOR USER: florian
<127.0.0.2> REMOTE_MODULE command whoami
<127.0.0.2> EXEC ssh -C -vvv -o ControlMaster=auto -o ControlPersist=60s -o ControlPath="/home/florian/.ansible/cp/ansible-ssh-%h-%p-%r" -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 127.0.0.2 /bin/sh -c 'sudo -k && sudo -H -S -p "[sudo via ansible, key=jqmrrbsnthlwyfrbstqmracbgofyxwii] password: " -u root /bin/sh -c '"'"'echo BECOME-SUCCESS-jqmrrbsnthlwyfrbstqmracbgofyxwii; LANG=en_US.UTF-8 LC_CTYPE=en_US.UTF-8 /usr/bin/python'"'"''
changed: [127.0.0.2] => {"changed": true, "cmd": ["whoami"], "delta": "0:00:00.005402", "end": "2015-09-14 17:35:15.974257", "rc": 0, "start": "2015-09-14 17:35:15.968855", "stderr": "", "stdout": "root", "warnings": []}
```

on ansible 1.9.3 and in:

```
TASK [whoami] ******************************************************************
<127.0.0.2> ESTABLISH SSH CONNECTION FOR USER: florian
<127.0.0.2> SSH: default arguments: (-o)(ControlMaster=auto)(-o)(ControlPersist=60s)
<127.0.0.2> SSH: found only ControlPersist; added ControlPath: (-o)(ControlPath="/home/florian/.ansible/cp/ansible-ssh-%h-%p-%r")
<127.0.0.2> SSH: ansible_password/ansible_ssh_pass not set: (-o)(KbdInteractiveAuthentication=no)(-o)(PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey)(-o)(PasswordAuthentication=no)
<127.0.0.2> SSH: ANSIBLE_TIMEOUT/timeout set: (-o)(ConnectTimeout=10)
<127.0.0.2> EXEC ssh -C -tt -vvv -o ControlMaster=auto -o ControlPersist=60s -o ControlPath="/home/florian/.ansible/cp/ansible-ssh-%h-%p-%r" -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 127.0.0.2 (umask 22 && mkdir -p "$HOME/.ansible/tmp/ansible-tmp-1442245068.18-77212961840115" && echo "$HOME/.ansible/tmp/ansible-tmp-1442245068.18-77212961840115")
<127.0.0.2> ESTABLISH SSH CONNECTION FOR USER: florian
<127.0.0.2> PUT /tmp/tmpwfWCyg TO /home/florian/.ansible/tmp/ansible-tmp-1442245068.18-77212961840115/command
<127.0.0.2> ESTABLISH SSH CONNECTION FOR USER: florian
<127.0.0.2> EXEC ssh -C -vvv -o ControlMaster=auto -o ControlPersist=60s -o ControlPath="/home/florian/.ansible/cp/ansible-ssh-%h-%p-%r" -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 127.0.0.2 /bin/sh -c 'sudo -H -p "[sudo via ansible, key=gaqecjfqopbwjhtanclwdxvcwvrwgmsx] password: " -S -u root /bin/sh -c '"'"'echo BECOME-SUCCESS-gaqecjfqopbwjhtanclwdxvcwvrwgmsx; LANG=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8 LC_CTYPE=en_US.UTF-8 /usr/bin/python ; rm -rf "/home/florian/.ansible/tmp/ansible-tmp-1442245068.18-77212961840115/" > /dev/null 2>&1'"'"''
changed: [127.0.0.2] => {"changed": true, "cmd": ["whoami"], "delta": "0:00:00.005378", "end": "2015-09-14 17:37:48.272441", "rc": 0, "start": "2015-09-14 17:37:48.267063", "stderr": "", "stdout": "root", "stdout_lines": ["root"], "warnings": []}
```

on ansible v2. The PUT command seems to be an indication that pipelining is not use according to @jimi-c.

Transport is openssh with version: OpenSSH_6.9p1 Debian-2, OpenSSL 1.0.2d 9 Jul 2015
Operating system is: Linux apollo13 4.1.0-2-amd64 #1 SMP Debian 4.1.6-1 (2015-08-23) x86_64 GNU/Linux (Debian unstable)



Discussion:
Using this makes it even easier to see: `ansible -i hosts localhost -bm ping -vvvvvv --ask-become-pass` (make sure that you are not using a local connection for localhost!)


Resolving patch:
diff --git a/lib/ansible/plugins/action/__init__.py b/lib/ansible/plugins/action/__init__.py
--- a/lib/ansible/plugins/action/__init__.py
+++ b/lib/ansible/plugins/action/__init__.py
@@ -142,7 +142,7 @@ def _late_needs_tmp_path(self, tmp, module_style):
         if tmp and "tmp" in tmp:
             # tmp has already been created
             return False
-        if not self._connection.has_pipelining or not C.ANSIBLE_SSH_PIPELINING or C.DEFAULT_KEEP_REMOTE_FILES or self._play_context.become:
+        if not self._connection.has_pipelining or not C.ANSIBLE_SSH_PIPELINING or C.DEFAULT_KEEP_REMOTE_FILES or self._play_context.become_method == 'su':
             # tmp is necessary to store the module source code
             # or we want to keep the files on the target system
             return True


Test patch: