Repository: ansible/ansible

Issue:
become: getcwd: cannot access parent directories: Permission denied
##### ISSUE TYPE
 - Bug Report

##### COMPONENT NAME
become functionality

##### ANSIBLE VERSION
```
ansible 2.2.0.0
  config file = /Users/myuser/script/homelab/ansible.cfg
  configured module search path = Default w/o overrides
```

##### CONFIGURATION
```
$ egrep -v '(^#|^$)' ansible.cfg
[defaults] 
log_path=ansible.log
roles_path = ./
transport = ssh
forks=5
callback_plugins = callback_plugins/
timeout = 30
[ssh_connection]
ssh_args = -o ForwardAgent=yes
pipelining=True
scp_if_ssh=True
```

##### OS / ENVIRONMENT
Orchestrator: Macos 10.11, target 10.12

##### SUMMARY
When using become with non-privileged user, tasks are failing with
```
{"changed": false, "failed": true, "module_stderr": "shell-init: error retrieving current directory: getcwd: cannot access parent directories: Permission denied\njob-working-directory: error retrieving current directory: getcwd: cannot access parent directories: Permission denied\nTraceback (most recent call last):\n  File \"<stdin>\", line 10, in <module>\n  File \"/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.py\", line 364, in abspath\n    cwd = os.getcwd()\nOSError: [Errno 13] Permission denied\n", "module_stdout": "", "msg": "MODULE FAILURE"}
```

apply to single task on or on include: for example osx_defaults
Problem is I think, ansible should chdir to a world-readable directory before 'become' like / or /tmp. else python is trying its own actions later and failed because of permissions.

Note: ansible user is non-root user with sudo capacity. both this user and root user have private home non-readable by other users.

##### STEPS TO REPRODUCE

```yaml
- hosts: mac 
  tasks:
    - name: Show Hidden Files
      osx_defaults: domain=com.apple.finder key=AppleShowAllFiles type=bool value=true state=present
      become: yes 
      become_user: local_user

```

##### EXPECTED RESULTS

task should apply in user context without failure.

##### ACTUAL RESULTS

```
$ time ansible-playbook -i inventory--limit mac test-become.yml -vvvv

Using /Users/myuser/script/homelab/ansible.cfg as config file
Loading callback plugin default of type stdout, v2.0 from /opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/ansible/plugins/callback/__init__.pyc

PLAYBOOK: test-become.yml ******************************************************
1 plays in test-become.yml

PLAY [mac] *********************************************************************

TASK [setup] *******************************************************************
Using module file /opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/ansible/modules/core/system/setup.py
<x.y.1.7> ESTABLISH SSH CONNECTION FOR USER: deploy
<x.y.1.7> SSH: EXEC ssh -vvv -o ForwardAgent=yes -o 'IdentityFile="/Users/myuser/.ssh/keys/sshkey1"' -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gs
sapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=deploy -o ConnectTimeout=30 x.y.1.7 '/bin/sh -c '"'"'/usr/bin/python && sleep 0'"'"''
ok: [air]

TASK [Show Hidden Files] *******************************************************
task path: /Users/myuser/script/homelab/test-become.yml:4
Using module file /opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/ansible/modules/extras/system/osx_defaults.py
<x.y.1.7> ESTABLISH SSH CONNECTION FOR USER: deploy
<x.y.1.7> SSH: EXEC ssh -vvv -o ForwardAgent=yes -o 'IdentityFile="/Users/myuser/.ssh/keys/sshkey1"' -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gs
sapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=deploy -o ConnectTimeout=30 x.y.1.7 '/bin/sh -c '"'"'sudo -H -S -n -u myuser /bin/sh -c '"'"'"'"'"'"'"'"'echo BECOME-
SUCCESS-tiiyfmjvqivumyjnytpqwfmmhubpibav; /usr/bin/python'"'"'"'"'"'"'"'"' && sleep 0'"'"''
fatal: [air]: FAILED! => {
    "changed": false, 
    "failed": true, 
    "invocation": {
        "module_name": "osx_defaults"
    }, 
    "module_stderr": "OpenSSH_6.9p1, LibreSSL 2.1.8\r\ndebug1: Reading configuration data /Users/myuser/.ssh/config\r\ndebug3: kex names ok: [diffie-hellman-group-exchange-sha256,diffie-
hellman-group-exchange-sha1,diffie-hellman-group14-sha1]\r\ndebug1: /Users/myuser/.ssh/config line 286: Applying options for *\r\ndebug1: Reading configuration data /etc/ssh/ssh_config\r
\ndebug1: /etc/ssh/ssh_config line 56: Applying options for *\r\ndebug1: auto-mux: Trying existing master\r\ndebug1: Control socket \"/Users/myuser/.ssh/ctl-deploy-x.y.1.7-22\" does not
 exist\r\ndebug2: ssh_connect: needpriv 0\r\ndebug1: Connecting to x.y.1.7 [x.y.1.7] port 22.\r\ndebug2: fd 3 setting O_NONBLOCK\r\ndebug1: fd 3 clearing O_NONBLOCK\r\ndebug1: Connecti
on established.\r\ndebug3: timeout: 28887 ms remain after connect\r\ndebug1: identity file /Users/myuser/.ssh/keys/sshkey1 type 4\r\ndebug1: key_load_public: No such file or directory
\r\ndebug1: identity file /Users/myuser/.ssh/keys/sshkey1-cert type -1\r\ndebug1: Enabling compatibility mode for protocol 2.0\r\ndebug1: Local version string SSH-2.0-OpenSSH_6.9\r\nd
ebug1: Remote protocol version 2.0, remote software version OpenSSH_7.3\r\ndebug1: match: OpenSSH_7.3 pat OpenSSH* compat 0x04000000\r\ndebug2: fd 3 setting O_NONBLOCK\r\ndebug1: Authent
icating to x.y.1.7:22 as 'deploy'\r\ndebug3: hostkeys_foreach: reading file \"/Users/myuser/.ssh/known_hosts\"\r\ndebug3: record_hostkey: found key type ECDSA in file /Users/myuser/.ssh
/known_hosts:40\r\ndebug3: load_hostkeys: loaded 1 keys from x.y.1.7\r\ndebug3: order_hostkeyalgs: prefer hostkeyalgs: ecdsa-sha2-nistp256-cert-v01@openssh.com,ecdsa-sha2-nistp384-cert-
v01@openssh.com,ecdsa-sha2-nistp521-cert-v01@openssh.com,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521\r\ndebug1: SSH2_MSG_KEXINIT sent\r\ndebug1: SSH2_MSG_KEXINIT received
\r\ndebug2: kex_parse_kexinit: curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sh
a1,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1\r\ndebug2: kex_parse_kexinit: ecdsa-sha2-nistp256-cert-v01@openssh.com,ecdsa-sha2-nistp384-cert-v01@openssh.com,ecdsa-sha2-nistp
521-cert-v01@openssh.com,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,ssh-ed25519-cert-v01@openssh.com,ssh-rsa-cert-v01@openssh.com,ssh-dss-cert-v01@openssh.com,ssh-rsa-ce
rt-v00@openssh.com,ssh-dss-cert-v00@openssh.com,ssh-ed25519,ssh-rsa,ssh-dss\r\ndebug2: kex_parse_kexinit: aes256-ctr,aes192-ctr,aes128-ctr\r\ndebug2: kex_parse_kexinit: aes256-ctr,aes192
-ctr,aes128-ctr\r\ndebug2: kex_parse_kexinit: umac-64-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,umac-
64@openssh.com,umac-128@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha1,hmac-md5-etm@openssh.com,hmac-ripemd160-etm@openssh.com,hmac-sha1-96-etm@openssh.com,hmac-md5-96-etm@openssh.com
,hmac-md5,hmac-ripemd160,hmac-ripemd160@openssh.com,hmac-sha1-96,hmac-md5-96\r\ndebug2: kex_parse_kexinit: umac-64-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-256-etm@openssh.com,
hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,umac-64@openssh.com,umac-128@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha1,hmac-md5-etm@openssh.com,hmac-ripemd160-etm@openssh
.com,hmac-sha1-96-etm@openssh.com,hmac-md5-96-etm@openssh.com,hmac-md5,hmac-ripemd160,hmac-ripemd160@openssh.com,hmac-sha1-96,hmac-md5-96\r\ndebug2: kex_parse_kexinit: none,zlib@openssh.
com,zlib\r\ndebug2: kex_parse_kexinit: none,zlib@openssh.com,zlib\r\ndebug2: kex_parse_kexinit: \r\ndebug2: kex_parse_kexinit: \r\ndebug2: kex_parse_kexinit: first_kex_follows 0 \r\ndebu
g2: kex_parse_kexinit: reserved 0 \r\ndebug2: kex_parse_kexinit: curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha25
6,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha256,diffie-hellman-group14-sha1\r\ndebug2: kex_parse_kexinit: ssh-rsa,rsa-sha2-512,rsa-sha2-256,ec
dsa-sha2-nistp256,ssh-ed25519\r\ndebug2: kex_parse_kexinit: chacha20-poly1305@openssh.com,aes128-ctr,aes192-ctr,aes256-ctr,aes128-gcm@openssh.com,aes256-gcm@openssh.com\r\ndebug2: kex_pa
rse_kexinit: chacha20-poly1305@openssh.com,aes128-ctr,aes192-ctr,aes256-ctr,aes128-gcm@openssh.com,aes256-gcm@openssh.com\r\ndebug2: kex_parse_kexinit: umac-64-etm@openssh.com,umac-128-e
tm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,umac-64@openssh.com,umac-128@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha1\r\ndeb
ug2: kex_parse_kexinit: umac-64-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,umac-64@openssh.com,umac-128@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha1\r\ndebug2: kex_parse_kexinit: none,zlib@openssh.com\r\ndebug2: kex_parse_kexinit: none,zlib@openssh.com\r\ndebug2: kex_parse_kexinit: \r\ndebug2: kex_parse_kexinit: \r\ndebug2: kex_parse_kexinit: first_kex_follows 0 \r\ndebug2: kex_parse_kexinit: reserved 0 \r\ndebug1: kex: server->client aes256-ctr umac-64-etm@openssh.com none\r\ndebug1: kex: client->server aes256-ctr umac-64-etm@openssh.com none\r\ndebug1: expecting SSH2_MSG_KEX_ECDH_REPLY\r\ndebug1: Server host key: ecdsa-sha2-nistp256 SHA256:Rg62+0HaDpRVOtfWgR1iggZzDrk+6v4LuzcdzS93BTk\r\ndebug3: hostkeys_foreach: reading file \"/Users/myuser/.ssh/known_hosts\"\r\ndebug3: record_hostkey: found key type ECDSA in file /Users/myuser/.ssh/known_hosts:40\r\ndebug3: load_hostkeys: loaded 1 keys from x.y.1.7\r\ndebug1: Host 'x.y.1.7' is known and matches the ECDSA host key.\r\ndebug1: Found key in /Users/myuser/.ssh/known_hosts:40\r\ndebug2: set_newkeys: mode 1\r\ndebug1: SSH2_MSG_NEWKEYS sent\r\ndebug1: expecting SSH2_MSG_NEWKEYS\r\ndebug2: set_newkeys: mode 0\r\ndebug1: SSH2_MSG_NEWKEYS received\r\ndebug1: SSH2_MSG_SERVICE_REQUEST sent\r\ndebug2: service_accept: ssh-userauth\r\ndebug1: SSH2_MSG_SERVICE_ACCEPT received\r\ndebug2: key: /Users/myuser/.ssh/keys/sshkey1 (0x7fb933d141f0), explicit\r\ndebug1: Authentications that can continue: publickey,keyboard-interactive\r\ndebug3: start over, passed a different list publickey,keyboard-interactive\r\ndebug3: preferred gssapi-with-mic,gssapi-keyex,hostbased,publickey\r\ndebug3: authmethod_lookup publickey\r\ndebug3: remaining preferred: ,gssapi-keyex,hostbased,publickey\r\ndebug3: authmethod_is_enabled publickey\r\ndebug1: Next authentication method: publickey\r\ndebug1: Offering ED25519 public key: /Users/myuser/.ssh/keys/sshkey1\r\ndebug3: send_pubkey_test\r\ndebug2: we sent a publickey packet, wait for reply\r\ndebug1: Server accepts key: pkalg ssh-ed25519 blen 51\r\ndebug2: input_userauth_pk_ok: fp SHA256:X/9fGyWVW1VJY8S+s4oTugq+zKgu8yuigFjBo+CgTzw\r\ndebug3: sign_and_send_pubkey: ED25519 SHA256:X/9fGyWVW1VJY8S+s4oTugq+zKgu8yuigFjBo+CgTzw\r\ndebug1: Authentication succeeded (publickey).\r\nAuthenticated to x.y.1.7 ([x.y.1.7]:22).\r\ndebug1: setting up multiplex master socket\r\ndebug3: muxserver_listen: temporary control path /Users/myuser/.ssh/ctl-deploy-x.y.1.7-22.TghyBP5n3Qzoagpa\r\ndebug2: fd 5 setting O_NONBLOCK\r\ndebug3: fd 5 is O_NONBLOCK\r\ndebug3: fd 5 is O_NONBLOCK\r\ndebug1: channel 0: new [/Users/myuser/.ssh/ctl-deploy-x.y.1.7-22]\r\ndebug3: muxserver_listen: mux listener channel 0 fd 5\r\ndebug2: fd 6 setting O_NONBLOCK\r\ndebug2: fd 7 setting O_NONBLOCK\r\ndebug2: fd 8 setting O_NONBLOCK\r\ndebug1: channel 1: new [client-session]\r\ndebug3: ssh_session2_open: channel_new: 1\r\ndebug2: channel 1: send open\r\ndebug1: Entering interactive session.\r\ndebug1: client_input_global_request: rtype hostkeys-00@openssh.com want_reply 0\r\ndebug2: callback start\r\ndebug1: Requesting authentication agent forwarding.\r\ndebug2: channel 1: request auth-agent-req@openssh.com confirm 0\r\ndebug2: fd 3 setting TCP_NODELAY\r\ndebug3: ssh_packet_set_tos: set IP_TOS 0x08\r\ndebug2: client_session2_setup: id 1\r\ndebug1: Sending environment.\r\ndebug3: Ignored env MANPATH\r\ndebug3: Ignored env TERM_PROGRAM\r\ndebug3: Ignored env D\r\ndebug3: Ignored env GPG_AGENT_INFO\r\ndebug3: Ignored env SHELL\r\ndebug3: Ignored env TERM\r\ndebug3: Ignored env G\r\ndebug3: Ignored env TMPDIR\r\ndebug3: Ignored env Apple_PubSub_Socket_Render\r\ndebug3: Ignored env CVSROOT\r\ndebug3: Ignored env TERM_PROGRAM_VERSION\r\ndebug3: Ignored env OLDPWD\r\ndebug3: Ignored env TERM_SESSION_ID\r\ndebug3: Ignored env USER\r\ndebug3: Ignored env SSH_AUTH_SOCK\r\ndebug3: Ignored env TERMCAP\r\ndebug3: Ignored env __CF_USER_TEXT_ENCODING\r\ndebug3: Ignored env PATH\r\ndebug3: Ignored env STY\r\ndebug3: Ignored env PWD\r\ndebug3: Ignored env EXINIT\r\ndebug3: Ignored env DBUS_LAUNCHD_SESSION_BUS_SOCKET\r\ndebug3: Ignored env TCLLIBPATH\r\ndebug3: Ignored env FIREBIRD_HOME\r\ndebug3: Ignored env mp\r\ndebug3: Ignored env XPC_FLAGS\r\ndebug3: Ignored env XPC_SERVICE_NAME\r\ndebug3: Ignored env m\r\ndebug3: Ignored env HOME\r\ndebug3: Ignored env SHLVL\r\ndebug3: Ignored env r\r\ndebug3: Ignored env LOGNAME\r\ndebug3: Ignored env WINDOW\r\ndebug3: Ignored env LC_CTYPE\r\ndebug3: Ignored env DISPLAY\r\ndebug3: Ignored env SECURITYSESSIONID\r\ndebug3: Ignored env _\r\ndebug1: Sending command: /bin/sh -c 'sudo -H -S -n -u myuser /bin/sh -c '\"'\"'echo BECOME-SUCCESS-tiiyfmjvqivumyjnytpqwfmmhubpibav; /usr/bin/python'\"'\"' && sleep 0'\r\ndebug2: channel 1: request exec confirm 1\r\ndebug2: callback done\r\ndebug2: channel 1: open confirm rwindow 0 rmax 32768\r\ndebug2: channel 1: rcvd adjust 2097152\r\ndebug2: channel_input_status_confirm: type 99 id 1\r\ndebug2: exec request accepted on channel 1\r\ndebug2: channel 1: rcvd ext data 108\r\ndebug2: channel 1: rcvd ext data 119\r\nshell-init: error retrieving current directory: getcwd: cannot access parent directories: Permission denied\njob-working-directory: error retrieving current directory: getcwd: cannot access parent directories: Permission denied\ndebug2: channel 1: written 227 to efd 8\r\ndebug2: channel 1: read<=0 rfd 6 len 0\r\ndebug2: channel 1: read failed\r\ndebug2: channel 1: close_read\r\ndebug2: channel 1: input open -> drain\r\ndebug2: channel 1: ibuf empty\r\ndebug2: channel 1: send eof\r\ndebug2: channel 1: input drain -> closed\r\ndebug2: channel 1: rcvd ext data 74\r\ndebug2: channel 1: rcvd ext data 115\r\nTraceback (most recent call last):\n  File \"<stdin>\", line 10, in <module>\n  File \"/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.py\", line 364, in abspath\ndebug2: channel 1: written 189 to efd 8\r\ndebug2: channel 1: rcvd ext data 22\r\ndebug2: channel 1: rcvd ext data 9\r\ndebug2: channel 1: rcvd ext data 29\r\n    cwd = os.getcwd()\nOSError: [Errno 13] Permission denied\ndebug2: channel 1: written 60 to efd 8\r\ndebug2: channel 1: rcvd eof\r\ndebug2: channel 1: output open -> drain\r\ndebug2: channel 1: obuf empty\r\ndebug2: channel 1: close_write\r\ndebug2: channel 1: output drain -> closed\r\ndebug1: client_input_channel_req: channel 1 rtype exit-status reply 0\r\ndebug2: channel 1: rcvd close\r\ndebug3: channel 1: will not send data after close\r\ndebug2: channel 1: almost dead\r\ndebug2: channel 1: gc: notify user\r\ndebug2: channel 1: gc: user detached\r\ndebug2: channel 1: send close\r\ndebug2: channel 1: is dead\r\ndebug2: channel 1: garbage collecting\r\ndebug1: channel 1: free: client-session, nchannels 2\r\ndebug3: channel 1: status: The following connections are open:\r\n  #1 client-session (t4 r0 i3/0 o3/0 fd -1/-1 cc -1)\r\n\r\ndebug1: channel 0: free: /Users/myuser/.ssh/ctl-deploy-x.y.1.7-22, nchannels 1\r\ndebug3: channel 0: status: The following connections are open:\r\n\r\ndebug1: fd 0 clearing O_NONBLOCK\r\ndebug1: fd 1 clearing O_NONBLOCK\r\ndebug1: fd 2 clearing O_NONBLOCK\r\nTransferred: sent 59336, received 3356 bytes, in 0.1 seconds\r\nBytes per second: sent 915284.7, received 51767.8\r\ndebug1: Exit status 1\r\n", 
    "module_stdout": "", 
    "msg": "MODULE FAILURE"
}
```



Discussion:
cc @mattclay @abadger - suspect more fixup_perms shenanigans here specific to osx...
I think this is a generic problem but I don't think there's a solution in code.  If ansible were to switch directories then anything that bases itself off of paths relative to the current working directory wouldn't make sense.
The traceback indicates the error is on line 10 of the ansiballz module wrapper, which is here:

https://github.com/ansible/ansible/blob/devel/lib/ansible/executor/module_common.py#L112

A call to `os.getcwd()` can fail on OS X with `errno.EACCES` if you don't have sufficient permissions.

@abadger What's the impact of ignoring that exception? We already handle `AttributeError` there.
Don't know.  As you can see from the comments, it fixed errors of module shadowing on some Linux distributions.  But other Linux distros did not have the problem.  I can't recall the issue but reading the comment makes me think you could test it by having a module in module_utils that shadowed a python stdlib library that we use or similar.
Notes from Initial debugging:
* This happens when the login user's home directory has restricted permissions.
* This does not happen on Linux
* pipelining (or probably another technique that takes care of the permissions handling in fixup_perms2) needs to be enabled.  This leads me to believe this is not a fixup_perms problem.

Checking now whether this only happens in the AnsiBallZ module wrapper or if it also happens inside of a module.
Does not affect retrieving the current working directory inside of a module.  So it is only at the wrapper level.

I think that on other systems, piping a script into python must not set __main__.__file__ (thus the AttributeError in the exception handler).  On osx this seems to be getting set so the script gets to call os.path.abspath() and then fails.  Going to try this with world readable tempfiles and no pipelining to confirm whether that's part of the problem.
Results are that it works with no pipelining but we don't get AttributeError on osx or Linux in this situation.  Maybe pipelining isn't setting up permissions on the temporary directories like the non-pipelining case.
ah.  When we're not pipelining, python is passed the full path to the script that it invokes.  So in that case, os.path.abspath() does not end up calling getcwd() as __main__.__file__ already contains an absolute pathname.
@mattclay I've distilled a test case for testing whether the scriptdir removal from sys.path is necessary on a platform.  If I find that OSX does not need that, I'll add OSError as a valid reason to skip scriptdir handling.

Resolving patch:
diff --git a/lib/ansible/executor/module_common.py b/lib/ansible/executor/module_common.py
--- a/lib/ansible/executor/module_common.py
+++ b/lib/ansible/executor/module_common.py
@@ -107,10 +107,21 @@
 # Ubuntu15.10 with python2.7  Works
 # Ubuntu15.10 with python3.4  Fails without this
 # Ubuntu16.04.1 with python3.5  Fails without this
+# To test on another platform:
+# * use the copy module (since this shadows the stdlib copy module)
+# * Turn off pipelining
+# * Make sure that the destination file does not exist
+# * ansible ubuntu16-test -m copy -a 'src=/etc/motd dest=/var/tmp/m'
+# This will traceback in shutil.  Looking at the complete traceback will show
+# that shutil is importing copy which finds the ansible module instead of the
+# stdlib module
 scriptdir = None
 try:
     scriptdir = os.path.dirname(os.path.abspath(__main__.__file__))
-except AttributeError:
+except (AttributeError, OSError):
+    # Some platforms don't set __file__ when reading from stdin
+    # OSX raises OSError if using abspath() in a directory we don't have
+    # permission to read.
     pass
 if scriptdir is not None:
     sys.path = [p for p in sys.path if p != scriptdir]


Test patch: