-
Notifications
You must be signed in to change notification settings - Fork 3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix #725 and #729. /tmp/pip-build issues #734
Changes from all commits
61cc16d
9c5b58f
d89b580
502ae9b
d3d817c
bfd651d
485f87d
4533c4e
c96548f
eeaa64d
e7bf29e
61c444e
dc3a359
8baeeba
7f13624
5c10fc5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,7 +4,9 @@ | |
import site | ||
import os | ||
import tempfile | ||
import getpass | ||
from pip.backwardcompat import get_python_lib | ||
import pip.exceptions | ||
|
||
|
||
def running_under_virtualenv(): | ||
|
@@ -25,6 +27,31 @@ def virtualenv_no_global(): | |
if running_under_virtualenv() and os.path.isfile(no_global_file): | ||
return True | ||
|
||
def _get_build_prefix(): | ||
""" Returns a safe build_prefix """ | ||
path = os.path.join(tempfile.gettempdir(), 'pip-build-%s' % \ | ||
getpass.getuser()) | ||
if sys.platform == 'win32': | ||
""" on windows(tested on 7) temp dirs are isolated """ | ||
return path | ||
try: | ||
os.mkdir(path) | ||
except OSError: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why this try/except ? why not just There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because I am ensuring there isn't a TOCTOU[0] bug here. If you did a os.path.isdir(path) that would would be vulnerable. [0] http://en.wikipedia.org/wiki/Time_of_check_to_time_of_use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok, good, got it. |
||
file_uid = None | ||
try: | ||
fd = os.open(path, os.O_RDONLY | os.O_NOFOLLOW) | ||
file_uid = os.fstat(fd).st_uid | ||
os.close(fd) | ||
except OSError: | ||
file_uid = None | ||
if file_uid != os.getuid(): | ||
msg = "The temporary folder for building (%s) is not owned by your user!" \ | ||
% path | ||
print (msg) | ||
print("pip will not work until the temporary folder is " + \ | ||
"either deleted or owned by your user account.") | ||
raise pip.exceptions.InstallationError(msg) | ||
return path | ||
|
||
if running_under_virtualenv(): | ||
build_prefix = os.path.join(sys.prefix, 'build') | ||
|
@@ -33,7 +60,7 @@ def virtualenv_no_global(): | |
# Use tempfile to create a temporary folder for build | ||
# Note: we are NOT using mkdtemp so we can have a consistent build dir | ||
# Note: using realpath due to tmp dirs on OSX being symlinks | ||
build_prefix = os.path.realpath(os.path.join(tempfile.gettempdir(), 'pip-build')) | ||
build_prefix = os.path.realpath(_get_build_prefix()) | ||
|
||
## FIXME: keep src in cwd for now (it is not a temporary folder) | ||
try: | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
""" | ||
locations.py tests | ||
|
||
""" | ||
import os | ||
import sys | ||
import shutil | ||
import tempfile | ||
import getpass | ||
from mock import Mock | ||
import pip | ||
|
||
class TestLocations: | ||
def setup(self): | ||
self.tempdir = tempfile.mkdtemp() | ||
self.st_uid = 9999 | ||
self.username = "example" | ||
self.patch() | ||
|
||
def tearDown(self): | ||
self.revert_patch() | ||
shutil.rmtree(self.tempdir, ignore_errors=True) | ||
|
||
def patch(self): | ||
""" first store and then patch python methods pythons """ | ||
self.tempfile_gettempdir = tempfile.gettempdir | ||
self.old_os_fstat = os.fstat | ||
self.old_os_getuid = os.getuid | ||
self.old_getpass_getuser = getpass.getuser | ||
|
||
# now patch | ||
tempfile.gettempdir = lambda : self.tempdir | ||
getpass.getuser = lambda : self.username | ||
os.getuid = lambda : self.st_uid | ||
os.fstat = lambda fd : self.get_mock_fstat(fd) | ||
|
||
def revert_patch(self): | ||
""" revert the patches to python methods """ | ||
tempfile.gettempdir = self.tempfile_gettempdir | ||
getpass.getuser = self.old_getpass_getuser | ||
os.getuid = self.old_os_getuid | ||
os.fstat = self.old_os_fstat | ||
|
||
def get_mock_fstat(self, fd): | ||
""" returns a basic mock fstat call result. | ||
Currently only the st_uid attribute has been set. | ||
""" | ||
result = Mock() | ||
result.st_uid = self.st_uid | ||
return result | ||
|
||
def get_build_dir_location(self): | ||
""" returns a string pointing to the | ||
current build_prefix. | ||
""" | ||
return os.path.join(self.tempdir, 'pip-build-%s' % self.username) | ||
|
||
def test_dir_created(self): | ||
""" test that the build_prefix directory is generated when | ||
_get_build_prefix is called. | ||
""" | ||
|
||
assert not os.path.exists(self.get_build_dir_location() ), \ | ||
"the build_prefix directory should not exist yet!" | ||
from pip import locations | ||
locations._get_build_prefix() | ||
assert os.path.exists(self.get_build_dir_location() ), \ | ||
"the build_prefix directory should now exist!" | ||
|
||
def test_error_raised_when_owned_by_another(self): | ||
""" test calling _get_build_prefix when there is a temporary | ||
directory owned by another user raises an InstallationError. | ||
""" | ||
from pip import locations | ||
os.getuid = lambda : 1111 | ||
os.mkdir(self.get_build_dir_location() ) | ||
try: | ||
locations._get_build_prefix() | ||
raise AssertionError("An InstallationError should have been raised!") | ||
except pip.exceptions.InstallationError: | ||
pass |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
help me out, why the quick return for windows?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
os.getuid() and other calls used later in the function do not work on windows.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
windows temp dirs are user isolated/protected anyway, atleast on some versions of windows.
on windows 7, you get something like this:
how about a comment mentioning that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay. I don't use windows so I had no idea.