[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
Re: [tor-bugs] #9444 [Tor bundles/installation]: Create deterministic TorBrowserBundles with Pluggable Transports
#9444: Create deterministic TorBrowserBundles with Pluggable Transports
------------------------------------------+--------------------------
Reporter: bastik | Owner: erinn
Type: task | Status: needs_review
Priority: normal | Milestone:
Component: Tor bundles/installation | Version:
Resolution: | Keywords: flashproxy
Actual Points: | Parent ID:
Points: |
------------------------------------------+--------------------------
Comment (by dcf):
These are noteworthy characteristics of the windows pluggable transports
build:
* Python packages are built within Wine.
* The Wine used is wine1.6 from the [https://launchpad.net/~ubuntu-
wine/+archive/ppa Ubuntu Wine Team PPA], not the wine1.4 that is in main
from [http://packages.ubuntu.com/search?keywords=wine precise onward].
* Windows Python is installed using the
[http://python.org/download/releases/2.7.5/ binary MSI installer]. py2exe
is also copied from a binary installer. Other Python packages (PyCrypto,
Twisted, etc.) are compiled from source.
* Wrapper executables for gcc, dllwrap, and swig are compiled early and
used by later build steps. These allow the Unixy cross-compiling tools to
be called by Python distutils running under Wine.
Here's a summary of things that had to be overcome in order to make the
windows build work, which motivate the above characteristics.
Python is hard to cross-compile, as mentioned in comment:18. So rather
it's installed using a binary MSI package. I cherry-picked a couple of
commits ([https://gitweb.torproject.org/builders/tor-browser-
bundle.git/commit/67639197f6001d3440774914b2da637849379155 67639197]
[https://gitweb.torproject.org/builders/tor-browser-
bundle.git/commit/9a2042d4b5d0963cc26f8beb97bfb92f6ce11284 9a2042d4]) to
get the Python version that was added to master since I made my branch.
Everything needs to be built under Wineâincluding pure Python packages
with no compiled extensions. The reason for this is that packages'
`setup.py` files make decisions based on things like the `os.name` and
`sys.platform` of the Python they are being built with, not that of the
cross host they are intended to run on. Some packages make decisions
regarding which source files to include or exclude; for example PyCrypto
starts by compiling a file called `winrand.c` when `sys.platform ==
'win32'`, and omits it otherwise.
The [http://packages.ubuntu.com/search?keywords=wine wine1.4] in Ubuntu
has an issue that often manifests when running Python code, leading to the
page fault that was seen in comment:18. There are a few bug reports:
* [http://bugs.winehq.org/show_bug.cgi?id=29764 blender 2.61 crashes on
start (python3.2)]
* [http://bugs.winehq.org/show_bug.cgi?id=30515 EVE Online crashes when
viewing certain ship models (T3 ships)]
The crash happens
[http://hg.python.org/cpython/file/694e2708b4a8/Modules/posixmodule.c#l1078
here in the _PyVerify_fd function]. This function is called by many Python
functions that deal with file descriptor numbers, for example `io.open`
and `os.fstat`. This code is enough to crash Python run under Wine 1.4:
{{{
>>> import os
>>> os.fstat(4)
wine: Unhandled page fault on read access to 0x3e892268 at address
0x1e044a38 (thread 000b), starting debugger...
Application tried to create a window, but no driver could be loaded.
Make sure that your X server is running and that $DISPLAY is set
correctly.
Unhandled exception: page fault on read access to 0x3e892268 in 32-bit
code (0x1e044a38).
Register dump:
CS:0073 SS:007b DS:007b ES:007b FS:0033 GS:003b
EIP:1e044a38 ESP:0042fbb0 EBP:001ce5f0 EFLAGS:00010202( R- -- I - - -
)
EAX:1ffffffc EBX:00000004 ECX:1e892268 EDX:00000003
ESI:00000000 EDI:00000004
Stack dump:
0x0042fbb0: 1e048370 00193c60 00000000 1e04839a
0x0042fbc0: 00000004 00000004 7bca6ff4 00110000
0x0042fbd0: 756d043d 00129030 001945a0 00158b58
0x0042fbe0: 00124a58 1e08e62b 00000000 756d043d
0x0042fbf0: 00159c90 001945a0 00000000 001d1c98
0x0042fc00: 1e08e62b 00159c90 001945a0 756d043d
Backtrace:
}}}
What goes wrong is that `_PyVerify_fd` tries to find out the size of a
data structure (`_msize(__pioinfo[0])`) that it expects to be heap-
allocated, but [http://bugs.winehq.org/show_bug.cgi?id=29764#c8 Wine does
it differently]. ([http://bugs.python.org/issue4804 This] is the Python
issue that introduced that behavior.) The crash is actually inside
`RtlSizeHeap` inside `_msize`; here is a Wine debug trace:
{{{
462888.985:0011:Call msvcrt._msize(1e892268) ret=1e044a0d
462888.985:0011:Call ntdll.RtlSizeHeap(00110000,00000000,1e892268)
ret=6c6f2247
462888.985:0011:warn:heap:validate_block_pointer Heap 0x110000: pointer
0x1e892268 is not inside heap
462888.985:0011:trace:heap:RtlSizeHeap (0x110000,70000062,0x1e892268):
returning ffffffff
462888.985:0011:Ret ntdll.RtlSizeHeap() retval=ffffffff ret=6c6f2247
462888.985:0011:warn:msvcrt:_msize :Probably called with non wine-
allocated memory, ret = -1
462888.985:0011:Ret msvcrt._msize() retval=ffffffff ret=1e044a0d
462888.985:0011:trace:seh:raise_exception code=c0000005 flags=0
addr=0x1e044a38 ip=1e044a38 tid=0011
}}}
I initially tried to patch around calls that end up in `_PyVerify_fd`, but
they are pervasive. A newer Wine fixes it. Installing the newer Wine
involves installing an
[http://keyserver.ubuntu.com:11371/pks/lookup?op=get&search=0x5A9A06AEF9CB8DB0
APT GPG key] and adding the PPA to `sources.list`.
Python distutils has a mingw32 compiler profile that is activated with
`--compiler=mingw32`. Sadly,
[http://hg.python.org/cpython/file/fbebc90abcd1/Lib/distutils/cygwinccompiler.py#l302
it hardcodes "gcc" and some compiler flags], and there is no way to change
them short of editing the distutils source. (See also the
[http://hg.python.org/cpython/file/fbebc90abcd1/Lib/distutils/cygwinccompiler.py#l138
similar cygwin profile], where it is made explicit in a comment: "Hard-
code GCC because that's what this is all about. XXX optimization, warnings
etc. should be customizable." The usual `CC` and `CFLAGS` environment
variables are honored
[http://hg.python.org/cpython/file/fbebc90abcd1/Lib/distutils/sysconfig.py#l171
only by the unix profile]; they are completely ignored by mingw32.
Aha, you say, I will copy/symlink i686-w64-mingw32-gcc so it is available
as gcc.exe. But! among the flags hardcoded by distutils is `-mno-cygwin`,
which [http://bugs.python.org/issue12641 was removed from GCC in 2010] and
now causes an error when used. Also, when running inside Wine, distutils
will pass to the compiler Windows paths with backslashes like
build\lib.win32-2.7\Crypto\Util\strxor.o instead of
build/lib.win32-2.7/Crypto/Util/strxor.o. (The `-mno-cygwin` issue is
[http://bugs.python.org/issue12641 fixed in Python 2.7.6], but the problem
with Windows paths remains.)
Aha, you say, I will install a small Python wrapper that removes `-mno-
cygwin` and rewrites paths (using the [http://wiki.winehq.org/winepath
winepath] utility), then execs the real compiler. But simply installing a
Python script as gcc.exe doesn't really work. It works in that it runs and
does what you want, but (perhaps because it is not a native .exe) Wine
detaches it from the foreground when it is run. distutils repeatedly calls
gcc to produce a .o file, then calls dllwrap on the .o file. When gcc
backgrounds itself immediately, distutils doesn't wait for it to finish
and write the .o file that dllwrap needs, so all the dllwrap calls fail.
Aha, you say, I will install a batch file called gcc.bat, which will
invoke the Windows python.exe on the gcc wrapper. This might work, except
for that distutils
[http://hg.python.org/cpython/file/fbebc90abcd1/Lib/distutils/spawn.py#l161
requires that all executables have a file name ending in ".exe"].
So you compile your Python wrappers into native binaries using py2exe.
Then you wonder for a while why your processes still seem to be getting
backgrounded. It turns out that your call to
[http://docs.python.org/2/library/subprocess.html#subprocess.call
subprocess.call] is failing with "WindowsError: [Error 6] Invalid handle"
when it does a
[http://docs.python.org/2/library/subprocess.html#subprocess.Popen.wait
Popen.wait]. This causes the Python wrapper to return prematurely, while
the gcc process is still running. Instead of waiting for the process to
terminate, you can read from its stderr stream, and wait until it closes.
Then finally things start working. You still get a message on the terminal
when the command exits:
{{{
Exception WindowsError: (6, 'Invalid handle') in <bound method
Popen.__del__ of <subprocess.Popen object at 0x001580D0>> ignored
}}}
but it doesn't happen until the command is actually finished.
Incidentally, this is why py2exe is installed from a binary package
instead of from sourceâit would require py2exe-compiled wrappers itself,
in order to be compiled. Writing the wrappers in C, for example, would
allow py2exe to be built from source.
I found I needed wrappers for gcc, dllwrap, and swig. (swig only for
m2crypto.) These Wine wrappers, I put in a subdirectory `build-helpers
/wine-wrappers`. I changed the `build-helpers` copy commands into
recursive copies to get the whole subdirectory. But I noticed this message
from gbuild:
{{{
sha256sum: wine-wrappers: Is a directory
}}}
This means that the Wine wrappers aren't included in the `gitian-
builder/result/pluggable-transports-windows-res.yml`. I don't know what's
the best way to handle that.
Current versions of Wine [http://bugs.winehq.org/show_bug.cgi?id=31237
don't work with libfaketime]. We selectively disable libfaketime for Wine
commands using `LD_PRELOAD=`. Otherwise, you get this error for every Wine
command: (this bug was hard to figure out because I could SSH into the
virtual host and the same commands would be fine when run manually!)
{{{
wine: created the configuration directory '/home/ubuntu/.wine'
wine: Unhandled page fault on read access to 0x00000000 at address (nil)
(thread 000b),
err:seh:start_debugger Couldn't start debugger ("winedbg --auto 10 104")
(2)
Read the Wine Developers Guide on how to set up winedbg or another
debugger
wine: Unhandled page fault on read access to 0x00000000 at address (nil)
(thread 0011),
err:seh:start_debugger Couldn't start debugger ("winedbg --auto 16 68")
(2)
Read the Wine Developers Guide on how to set up winedbg or another
debugger
}}}
(This is a different page fault than the `_PyVerify_fd` one above; this
one is at 0x00000000 and the other is at some nonzero address.)
--
Ticket URL: <https://trac.torproject.org/projects/tor/ticket/9444#comment:20>
Tor Bug Tracker & Wiki <https://trac.torproject.org/>
The Tor Project: anonymity online
_______________________________________________
tor-bugs mailing list
tor-bugs@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-bugs