The Tor BSD Diversity Project


The Eight Stages of a Tor Browser Update for OpenBSD Ports

3519 words by attila written on 2018–04–18, last edit: 2018–04–25, tags: openbsd, porting, tbbPrevious post: Onionshare: patches and portsNext post: Tor Browser 7.5.3 in OpenBSD -current Ports

This post describes what I do to get an update ready for the Tor Browser ports under OpenBSD. All of this is done on -current, the OpenBSD head of line, although backporting this work to the -stable release is high on our list of things to get going.

Please note: I am not an OpenBSD committer. I am not a Tor committer. I’m just some guy who’s interested in pushing privacy-enhancing technologies on BSD Unix. I speak for nobody but TDP.

All the examples in this post were typed at ksh, the OpenBSD default and my shell of choice these days.

It should also be noted that all of this assumes the build machine has the latest snapshot and ports tree. The implicit first step here is to update the build machine to this state and make sure there aren’t any issues; this happens very rarely, but it also pays to keep up on the and mailing lists.

It would be a good idea to peruse the ports(7) man page and several of the man pages it points at; at least and packages(7) for starters. I presume you know a lot of what is in those documents in what follows, and that you have some basic understanding of OpenBSD.

My goal in all of this is get to a place where I’ve produced binary packages on amd64 for all of the core components of tor-browser, each of which has its own separate port. These packages are generally unsigned and meant only for testing by a small, internal group. Once they pass muster there a patch is produced to bring the official ports tree up to date and posted to the mailing list.

1. Investigation

Investigate all of the diffs to certain key Mozillan files in the ports tree since the last time I updated:

landry@ does a great job of keeping on top of the Mozillan ports on OpenBSD. I generally ride on his shoulders, so to speak, and watch what he does closely. Firefox ESR is especially relevant since Tor Browser is based on ESR; we differ a bit, but not much and only where it is required to stick with how the Tor Browser team does things.

OpenBSD has the concept of ports modules, which are named chunks of Makefile that are factored out of ports that share them in common: lang/python, for instance, is generally used by all Pythonic ports. One of Landry’s innovations was writing the www/mozilla port module, to keep all the individual Mozillan port Makefiles clean and easier to maintain. The Tor Browser port uses this module, so I also have to track changes there, where many key variables are set. Landry even went so far as to add something to the module for me to help get the port working at all (MOZILLA_USE_BUNDLED_NSS). Quite cool, and essential because Tor Browser requires the version of nss that is bundled in the source, whereas the Mozillan ports under OpenBSD generally use the version that is packaged as its own port (along with the corresponding port of nspr). This is the reason why I also need to track what goes on in the security/nss port.

It is important to look at all the diffs, or you miss things… like when the ports tree switched over to using COMPILER, for instance. I should have learned about that by keeping up on the ports@ mailing list, but I actually learned about it by looking at the diffs. Don’t do as I do, kids, but anyway: watch what they do.

On the other side of the house, I start by reading the change logs posted to the mailing list, which also make it onto their blog; here’s the release announcement for the version I just did an update for, 7.5.3.

I also try to keep up on what’s been brewing on the Tor and OpenBSD mailing lists in general. Mainly I’m interested in knowing if we’re going to have some kind of version-skew issue. There are a couple varieties in our case:

In general, Landry is always ahead of us on ESR and there’s no problem. On one or two occasions I have had some issue because of a difference in versions and was able to find a way to resolve it, or the issue went away while I was working on the port because a new version of TB came out. The net/tor maintainer, pascal@, is also generally ahead of us on updates, and since our version of TB is the stable one, it ships with the latest stable version of Tor and we’ve never been out of sync there yet.

Finally, there is one file in the bundle that I especially care about: extension-overrides.js. It is the place where customizations to all of the addons used by Tor Browser are centralized, and also where pre-configured lists of bridges go. I deal with it specially in my packaging, and make sure that whatever package I produce has an identical extension-overrides.js to the one in the official release for Linux.

2. Git Wrangling

The Tor Project does not produce source tarballs for Tor Browser as of yet. I am confident that this will change, but for the moment it has not (tickets, have been, filed). In the past we used GitHub as a cheap (okay, free) way to produce source tarballs. This was appealing mainly because of the GH_* stuff in the OpenBSD ports framework. Then one of the core OpenBSD ports team members noted that there are some issues with using GitHub this way. At this point we were already committed to running a web server on and the machine in question has plenty of disk, so why not just self-host tarballs until official ones come along?

No good reason, so now we do that instead. One less external thing to depend on.

Wherever the tarball goes, it must first exist. Since I know what versions of ESR and TB (resp) we’re dealing with (remember step 1?), I know I’m looking for refs named something like: tor-browser-esr-versionesr-tb-version-something, e.g. tor-browser-52.7.3esr-7.5-1. I drop into my tor-browser git checkout and do something like:

$ git ls-remote | fgrep 52.7.3esr
fee2e3ef3764b5aaff8db1a4b415b70c9a2490a3        refs/heads/tor-browser-52.7.3esr-7.5-1
90e16dd25b6eb199c016fc8b5e9478a3454d36e1        refs/heads/tor-browser-52.7.3esr-8.0-1
852c5122042c97a077b9bfa90011640e09716d5f        refs/tags/tor-browser-52.7.3esr-7.5-1-build1
fee2e3ef3764b5aaff8db1a4b415b70c9a2490a3        refs/tags/tor-browser-52.7.3esr-7.5-1-build1^{}
9a1d8e8e0c3ad1ac5430b2d6007babcaaa045814        refs/tags/tor-browser-52.7.3esr-8.0-1-build1
901380f79a748e4dfdd3602b230fd3fbfa838819        refs/tags/tor-browser-52.7.3esr-8.0-1-build1^{}
d0322b642f5d3cf784531baf420bd3d34eb64e96        refs/tags/tor-browser-52.7.3esr-8.0-1-build2
90e16dd25b6eb199c016fc8b5e9478a3454d36e1        refs/tags/tor-browser-52.7.3esr-8.0-1-build2^{}

The two non-tag refs are the branches for 7.5.x and 8.0.x series of TB, respectively. We only care about 7.5.x, so it’s the first ref we’re interested in . The tags are usually the same, and there’s usually only a build1 tag, but occasionally there is more than one buildX tag. My process is to pull the right branch and then git diff against any buildX tags. Usually this yields no diffs, but on occasion it looks like they play with some minor things in different builds. Thus far it has always been some JS config file, like 000-firefox.js, and it was easy to figure out which tag corresponded to the release by examining the official TBB release for Linux. If there’s ever a more complex situation, the TBB devs are nice and generally accessible on IRC.

Since we have patches to torbutton and tor-launcher, I also keep git checkouts but the situation there is much easier; tags are used that correspond to the versions released, there’s only a master branch and it’s dead easy to get the right code for the release. I just git pull --tags origin master in both directories, switch them temporarily to the right tag and tar them up.

For this last step I have a small shell script that does some dirty little things in the filesystem to make the top-level directory have the expected name (e.g. tor-browser-7.5.3). It rolls up tarballs, generates sha256sums for them and drops them into our distfiles area.

The noscript and https-everywhere addons are really just “pass-thru” ports: I repackage the official XPI files in such a way that they get installed in the right place. I still have to mind the REVISION bumps there, but that’s about all I generally have to do.

3. First Cut

We keep the version of Tor Browser in www/tor-browser/, so that always needs to be edited. Most of that file has to do with building the JS addons; the browser itself is another deal.

Each extension (torbutton, tor-launcher, https-everywhere, noscript) has the version in its Makefile, so those all have to be edited. If some of them do not change for a release (happens frequently) then instead of changing the version we add or increment REVISION; this is because these extensions and the tb-browser port itself (stored in www/tor-browser/browser) are intertwined: the extensions get installed under /usr/local/lib/tor-browser-x.y.z, where x.y.z is the TB version. The paths where the files in a package get unpacked are baked into the package, so we can’t just keep using the same e.g. tor-launcher package that we cooked for the previous release even if tor-launcher didn’t change. OpenBSD’s answer to this is a “REVISION bump”: each time this happens the packages that don’t change get their REVISION incremented (or set to zero initially), so the package names change, along with the paths where their contents are installed. This is why sometimes you’ll see package names like e.g. tor-launcher-x.y.zp0; the p0 is the revision bump.

Once we’ve got that all sorted, it’s time to do make makesum in each sub-port that has new distfiles to pick up the changes to checksums and sizes.

4. Build the browser

N.B. I do none of this as root.

N.B.2 MAKE SURE THERE’S ENOUGH DISK FREE in /usr/ports/pobj. If you really want to build large ports from source I strongly suggest partitioning your machine to have /usr/ports/pobj as a separate, large partition. I suggest at least 20G (that’s how we have /usr/ports/pobj set up on the build machine).

N.B.3 ALSO VERY IMPORTANT: make sure /usr/ports/pobj is mounted with the wxallowed option or the build will fail early; it needs Python’s virtualenv, which requires wxallowed.

All of this happens in the www/tor-browser/browser port directory. I generally do my work under /usr/ports/mystuff, as per convention, so the full path to where I’m working is /usr/ports/mystuff/www/tor-browser/browser. I start off by clearing out my old work and tar’ing over the current state of the ports (under /usr/ports/www/tor-browser).

Then I make sure all build deps are installed. I have some tooling in my ~/.profile that helps:

alias mdeps='while read pkg; do pkg_info -e $pkg || echo miss:$pkg; done'
alias btdeps='make full-{build,test}-depends|sort -u|mdeps'
alias missdeps='btdeps | grep ^miss:'

In a port’s directory, I do:

$ missdeps

to see if any deps need to be installed. I first try pkg_add(1) and only resort to building the port from source if the package available for -current has not caught up with the ports tree. This does not happen very often, but once in a while we’re unlucky, like with the snapshot. I think I can count the number of times either thing has happened in the last three years on one hand and have some fingers left over, but as usual YMMV. In general a bit of patience is miles better than thrashing around trying to “solve” a problem that isn’t really yours.

Next, check that our patches didn’t blow up (should kinda already know at this point, given that I’ve read all the change logs :-):

$ make patch

If the patches blew up then that’s a whole ’nother ball of wax, and beyond the scope of this post, so let’s just assume it’s all fine (although c.f. “Denoument”, below). Assuming we’re good, the next step is to try a build; on our normal build machine it takes roughly 120 minutes:

$ time env MAKE_JOBS=10 make build 2>&1 | tee ~/build.log
... 8867 lines of spew ...
  117m16.54s real   270m27.60s user   516m50.88s system

Next I grep the warnings for anything suspicious; again this is sort of beyond the scope of this post, but so far I’ve yet to run into anything that didn’t turn out to be a known issue.

Next step, we use the fake framework to create a “fake” installation that we can examine and (hopefully) turn into an installable pacakge:

$ make fake

At this point /usr/ports/pobj/tb-browser-7.5.3/fake-amd64 contains a complete installation of the tb-browser package, viewed from root. If we look there under usr/local/lib/tor-browser-7.5.3 we’ll see all the shared libraries that get installed with the package (along with a lot of other stuff). In OpenBSD the ports system (really the porters) maintain a discipline with regard to shared libraries using the SHARED_LIBS mechanism. They are versioned, independently of the version of the port, starting with 0.0 at first import. A detailed treatment of the issue is given in the Special Porting Topics FAQ, highly recommended for folks interested in porting stuff to OpenBSD.

Beyond the shared libraries we install, there is the issue of those we depend on. The ports framework wants to make sure the metadata for each package is correct in this regard, that we know what depends on what. The place to start is the port-lib-depends-check target:

$ make port-lib-depends-check

If WANTLIB and/or LIB_DEPENDS is wrong you’ll be warned and told what to do.

Always good form to check if your patches need to be updated; sometimes whitespace changes or other things happen:

$ make update-patches

The packing list in pkg/PLIST may have to change from release to release, although usually I know about any changes and do them by hand. Even so, it doesn’t hurt to do:

$ make update-plist

and examine the results carefully.

If we get this far we’re probably good but this is always a good idea anyway:

$ portcheck

Finally, to build an unsigned package for testing:

$ make package

Worth noting again that I did none of that as root.

5. Build the rest

We still have patches outstanding for the torbutton and tor-launcher extensions, so we have to do the usual check-for-patch-blowup there.

Assuming our patches are good, building these packages is easy, I just do:

$ make package

in each extension.

The https-everywhere and noscript extensions are repackaged as-is from the official XPI files, so we just make sure we don’t need REVISION bumps or other stuff in the port and that’s about it.

Also, this is the time to update the meta-port, which lives in /usr/ports/meta/tor-browser. Its only job is to depend on the right versions of all the ports that make up Tor Browser, so end-users can type:

$ doas pkg_add tor-browser

and get everything installed.

6. Test

Sadly, I often cannot do this right away because of my crappy network connection; getting my snap up to date to the point where I can test takes me a while. I rely on my TDP projectmate gman999 to do most of the testing, especially early on. If the update is not a major one then that may be enough. If e.g. my patches blew up or other issues arose during the update then I wait until I can get my snap up to date and download packages to test before posting anything, and also call for others to help.

7. Post on ports@

Since I work in mystuff normally, I tar things back over to the ports tree proper when I’m ready to make the final diff. When I’m pretty sure it’s right:

$ cd /usr/ports
$ cvs diff {meta,www}/tor-browser > ~/my.patch

Then I look the patch over, make sure REVISION bumps are right one way or another, look for anything glaring.

Then I post it on and wait. The convention is that if your post doesn’t get attention in a week, you “bump it” - ping the list, reminding anyone interested in reviewing that you’re waiting.

In all of this patience is a virtue. Everyone is a volunteer. Don’t take it personally if they don’t get back to you right away, everyone has a life.

8. Denouement

Getting patches upstream is a cornerstone of Landry’s approach, as he says in his BSDcan talk. By this metric my efforts so far have not been very good. I have had meaningful discussions with my upstream about where to go with my efforts and some agreement on principles but thusfar I have been outpaced by them and too short on time in real life to close the loop.

The current state of affairs:

Getting as much of this upstream as I can before things change under me again is my first priority at this point (once my latest update is accepted, of course). Only slightly behind that is backporting what we have to -stable, something that more users are requesting. Just behind that is making progress on Pluggable Transports, something that has been on our list since the very beginning and has yet to materialize. We have managed to get obfs4proxy into OpenBSD ports, and you can use it in Tor bridges that run OpenBSD now, but this still doesn’t help on the client end.

So in the end we expend a long of energy to stay in place, perhaps more overall that we would if we could manage to push forward a little bit more. This is a kind of validation for Landry’s approach over-all: get your patches upstream and keep things simple… or face the consequences. Sadly we’ve not done well on all of his points but the fact that his work has allowed us to build on top of it is a good indication that we’re not wasting our time.

So long as we keep improving, I’m happy.

Copyright © 2015–2018 by The Tor BSD Diversity Project (TDP). All Rights Reserved.