summaryrefslogtreecommitdiff
path: root/doc/HACKING
diff options
context:
space:
mode:
Diffstat (limited to 'doc/HACKING')
-rw-r--r--doc/HACKING/CodingStandards.md11
-rw-r--r--doc/HACKING/Fuzzing.md123
-rw-r--r--doc/HACKING/HelpfulTools.md68
-rw-r--r--doc/HACKING/ReleasingTor.md89
-rw-r--r--doc/HACKING/Tracing.md91
-rw-r--r--doc/HACKING/WritingTests.md2
6 files changed, 326 insertions, 58 deletions
diff --git a/doc/HACKING/CodingStandards.md b/doc/HACKING/CodingStandards.md
index f1c65850a4..c7787a72cc 100644
--- a/doc/HACKING/CodingStandards.md
+++ b/doc/HACKING/CodingStandards.md
@@ -4,9 +4,10 @@ Coding conventions for Tor
tl;dr:
- Run configure with `--enable-fatal-warnings`
- - Run `make check-spaces` to catch whitespace errors
- Document your functions
- Write unit tests
+ - Run `make test-full` to test against all unit and integration tests.
+ - Run `make distcheck` to ensure the distribution works
- Add a file in `changes` for your branch.
Patch checklist
@@ -22,10 +23,12 @@ preference)
Did you remember...
- To build your code while configured with `--enable-fatal-warnings`?
- - To run `make check-spaces` on your code?
- To run `make check-docs` to see whether all new options are on
the manpage?
- To write unit tests, as possible?
+ - To run `make test-full` to test against all unit and integration tests (or
+ `make test-full-online` if you have a working connection to the internet)?
+ - To test that the distribution will actually work via `make distcheck`?
- To base your code on the appropriate branch?
- To include a file in the `changes` directory as appropriate?
@@ -93,6 +96,10 @@ What needs a changes file?
rewrites. Anything about which somebody might plausibly wonder "when
did that happen, and/or why did we do that" 6 months down the line.
+What does not need a changes file?
+
+ * Bugfixes for code that hasn't shipped in any released version of Tor
+
Why use changes files instead of Git commit messages?
* Git commit messages are written for developers, not users, and they
diff --git a/doc/HACKING/Fuzzing.md b/doc/HACKING/Fuzzing.md
new file mode 100644
index 0000000000..2039d6a4c0
--- /dev/null
+++ b/doc/HACKING/Fuzzing.md
@@ -0,0 +1,123 @@
+= Fuzzing Tor
+
+== The simple version (no fuzzing, only tests)
+
+Check out fuzzing-corpora, and set TOR_FUZZ_CORPORA to point to the place
+where you checked it out.
+
+To run the fuzzing test cases in a deterministic fashion, use:
+ make test-fuzz-corpora
+
+This won't actually fuzz Tor! It will just run all the fuzz binaries
+on our existing set of testcases for the fuzzer.
+
+
+== Different kinds of fuzzing
+
+Right now we support three different kinds of fuzzer.
+
+First, there's American Fuzzy Lop (AFL), a fuzzer that works by forking
+a target binary and passing it lots of different inputs on stdin. It's the
+trickiest one to set up, so I'll be describing it more below.
+
+Second, there's libFuzzer, a llvm-based fuzzer that you link in as a library,
+and it runs a target function over and over. To use this one, you'll need to
+have a reasonably recent clang and libfuzzer installed. At that point, you
+just build with --enable-expensive-hardening and --enable-libfuzzer. That
+will produce a set of binaries in src/test/fuzz/lf-fuzz-* . These programs
+take as input a series of directories full of fuzzing examples. For more
+information on libfuzzer, see http://llvm.org/docs/LibFuzzer.html
+
+Third, there's Google's OSS-Fuzz infrastructure, which expects to get all of
+its. For more on this, see https://github.com/google/oss-fuzz and the
+projects/tor subdirectory. You'll need to mess around with Docker a bit to
+test this one out; it's meant to run on Google's infrastructure.
+
+In all cases, you'll need some starting examples to give the fuzzer when it
+starts out. There's a set in the "fuzzing-corpora" git repository. Try
+setting TOR_FUZZ_CORPORA to point to a checkout of that repository
+
+== Writing Tor fuzzers
+
+A tor fuzzing harness should have:
+* a fuzz_init() function to set up any necessary global state.
+* a fuzz_main() function to receive input and pass it to a parser.
+* a fuzz_cleanup() function to clear global state.
+
+Most fuzzing frameworks will produce many invalid inputs - a tor fuzzing
+harness should rejecting invalid inputs without crashing or behaving badly.
+
+But the fuzzing harness should crash if tor fails an assertion, triggers a
+bug, or accesses memory it shouldn't. This helps fuzzing frameworks detect
+"interesting" cases.
+
+
+== Guided Fuzzing with AFL
+
+There is no HTTPS, hash, or signature for American Fuzzy Lop's source code, so
+its integrity can't be verified. That said, you really shouldn't fuzz on a
+machine you care about, anyway.
+
+To Build:
+ Get AFL from http://lcamtuf.coredump.cx/afl/ and unpack it
+ cd afl
+ make
+ cd ../tor
+ PATH=$PATH:../afl/ CC="../afl/afl-gcc" ./configure --enable-expensive-hardening
+ AFL_HARDEN=1 make clean fuzzers
+
+To Find The ASAN Memory Limit: (64-bit only)
+
+On 64-bit platforms, afl needs to know how much memory ASAN uses,
+because ASAN tends to allocate a ridiculous amount of virtual memory,
+and then not actually use it.
+
+Read afl/docs/notes_for_asan.txt for more details.
+
+ Download recidivm from http://jwilk.net/software/recidivm
+ Download the signature
+ Check the signature
+ tar xvzf recidivm*.tar.gz
+ cd recidivm*
+ make
+ /path/to/recidivm -v src/test/fuzz/fuzz-http
+ Use the final "ok" figure as the input to -m when calling afl-fuzz
+ (Normally, recidivm would output a figure automatically, but in some cases,
+ the fuzzing harness will hang when the memory limit is too small.)
+
+You could also just say "none" instead of the memory limit below, if you
+don't care about memory limits.
+
+
+To Run:
+ mkdir -p src/test/fuzz/fuzz_http_findings
+ ../afl/afl-fuzz -i ${TOR_FUZZ_CORPORA}/http -o src/test/fuzz/fuzz_http_findings -m <asan-memory-limit> -- src/test/fuzz/fuzz-http
+
+
+AFL has a multi-core mode, check the documentation for details.
+You might find the included fuzz-multi.sh script useful for this.
+
+macOS (OS X) requires slightly more preparation, including:
+* using afl-clang (or afl-clang-fast from the llvm directory)
+* disabling external crash reporting (AFL will guide you through this step)
+
+== Triaging Issues
+
+Crashes are usually interesting, particularly if using AFL_HARDEN=1 and --enable-expensive-hardening. Sometimes crashes are due to bugs in the harness code.
+
+Hangs might be interesting, but they might also be spurious machine slowdowns.
+Check if a hang is reproducible before reporting it. Sometimes, processing
+valid inputs may take a second or so, particularly with the fuzzer and
+sanitizers enabled.
+
+To see what fuzz-http is doing with a test case, call it like this:
+ src/test/fuzz/fuzz-http --debug < /path/to/test.case
+
+(Logging is disabled while fuzzing to increase fuzzing speed.)
+
+== Reporting Issues
+
+Please report any issues discovered using the process in Tor's security issue
+policy:
+
+https://trac.torproject.org/projects/tor/wiki/org/meetings/2016SummerDevMeeting/Notes/SecurityIssuePolicy
diff --git a/doc/HACKING/HelpfulTools.md b/doc/HACKING/HelpfulTools.md
index a7f36e6c7e..b8ba2aa408 100644
--- a/doc/HACKING/HelpfulTools.md
+++ b/doc/HACKING/HelpfulTools.md
@@ -142,6 +142,12 @@ run `make test-network`.
We also have scripts to run integration tests using Stem. To try them, set
`STEM_SOURCE_DIR` to your Stem source directory, and run `test-stem`.
+Profiling Tor
+-------------
+
+Ongoing notes about Tor profiling can be found at
+https://pad.riseup.net/p/profiling-tor
+
Profiling Tor with oprofile
---------------------------
@@ -168,20 +174,62 @@ Here are some basic instructions
* `opreport -l that_dir/*`
- Profit
+Profiling Tor with perf
+-----------------------
+
+This works with a running Tor, and requires root.
+
+1. Decide how long you want to profile for. Start with (say) 30 seconds. If that
+ works, try again with longer times.
+
+2. Find the PID of your running tor process.
+
+3. Run `perf record --call-graph dwarf -p <PID> sleep <SECONDS>`
+
+ (You may need to do this as root.)
+
+ You might need to add `-e cpu-clock` as an option to the perf record line
+ above, if you are on an older CPU without access to hardware profiling
+ events, or in a VM, or something.
+
+4. Now you have a perf.data file. Have a look at it with `perf report
+ --no-children --sort symbol,dso` or `perf report --no-children --sort
+ symbol,dso --stdio --header`. How does it look?
+
+5a. Once you have a nice big perf.data file, you can compress it, encrypt it,
+ and send it to your favorite Tor developers.
+
+5b. Or maybe you'd rather not send a nice big perf.data file. Who knows what's
+ in that!? It's kinda scary. To generate a less scary file, you can use `perf
+ report -g > <FILENAME>.out`. Then you can compress that and put it somewhere
+ public.
+
+Profiling Tor with gperftools aka Google-performance-tools
+----------------------------------------------------------
+
+This should work on nearly any unixy system. It doesn't seem to be compatible
+with RunAsDaemon though.
+
+Beforehand, install google-perftools.
+
+1. You need to rebuild Tor, hack the linking steps to add `-lprofiler` to the
+ libs. You can do this by adding `LIBS=-lprofiler` when you call `./configure`.
+
+Now you can run Tor with profiling enabled, and use the pprof utility to look at
+performance! See the gperftools manual for more info, but basically:
+
+2. Run `env CPUPROFILE=/tmp/profile src/or/tor -f <path/torrc>`. The profile file
+ is not written to until Tor finishes execuction.
+
+3. Run `pprof src/or/tor /tm/profile` to start the REPL.
+
Generating and analyzing a callgraph
------------------------------------
-1. Run `./scripts/maint/generate_callgraph.sh`. This will generate a
- bunch of files in a new ./callgraph directory.
-
-2. Run `./scripts/maint/analyze_callgraph.py callgraph/src/*/*`. This
- will do a lot of graph operations and then dump out a new
- `callgraph.pkl` file, containing data in Python's 'pickle' format.
+0. Build Tor on linux or mac, ideally with -O0 or -fno-inline.
-3. Run `./scripts/maint/display_callgraph.py`. It will display:
- - the number of functions reachable from each function.
- - all strongly-connnected components in the Tor callgraph
- - the largest bottlenecks in the largest SCC in the Tor callgraph.
+1. Clone 'https://gitweb.torproject.org/user/nickm/calltool.git/' .
+ Follow the README in that repository.
Note that currently the callgraph generator can't detect calls that pass
through function pointers.
diff --git a/doc/HACKING/ReleasingTor.md b/doc/HACKING/ReleasingTor.md
index 7595398241..4ece4d7a1d 100644
--- a/doc/HACKING/ReleasingTor.md
+++ b/doc/HACKING/ReleasingTor.md
@@ -26,9 +26,7 @@ new Tor release:
What about Coverity Scan?
- Is make check-spaces happy?
-
- Does 'make distcheck' compain?
+ Does 'make distcheck' complain?
How about 'make test-stem' and 'make test-network'?
@@ -44,21 +42,16 @@ new Tor release:
of them and reordering to focus on what users and funders would find
interesting and understandable.
- 1. Make sure that everything that wants a bug number has one.
- Make sure that everything which is a bugfix says what version
- it was a bugfix on.
-
- 2. Concatenate them.
-
- 3. Sort them by section. Within each section, sort by "version it's
- a bugfix on", else by numerical ticket order.
+ To do this, first run `./scripts/maint/lintChanges.py changes/*` and
+ fix as many warnings as you can. Then run `./scripts/maint/sortChanges.py
+ changes/* > changelog.in` to combine headings and sort the entries.
+ After that, it's time to hand-edit and fix the issues that lintChanges
+ can't find:
- 4. Clean them up:
+ 1. Within each section, sort by "version it's a bugfix on", else by
+ numerical ticket order.
- Standard idioms:
- `Fixes bug 9999; bugfix on 0.3.3.3-alpha.`
-
- One space after a period.
+ 2. Clean them up:
Make stuff very terse
@@ -86,19 +79,23 @@ new Tor release:
maint-0.2.1), be sure to make the stanzas identical (so people can
distinguish if these are the same change).
- 5. Merge them in.
+ 3. Clean everything one last time.
- 6. Clean everything one last time.
+ 4. Run `./scripts/maint/format_changelog.py --inplace` to make it prettier
- 7. Run `./scripts/maint/format_changelog.py` to make it prettier.
2. Compose a short release blurb to highlight the user-facing
changes. Insert said release blurb into the ChangeLog stanza. If it's
a stable release, add it to the ReleaseNotes file too. If we're adding
- to a release-0.2.x branch, manually commit the changelogs to the later
+ to a release-* branch, manually commit the changelogs to the later
git branches too.
-3. If you're doing the first stable release in a series, you need to
+3. If there are changes that require or suggest operator intervention
+ before or during the update, mail operators (either dirauth or relays
+ list) with a headline that indicates that an action is required or
+ appreciated.
+
+4. If you're doing the first stable release in a series, you need to
create a ReleaseNotes for the series as a whole. To get started
there, copy all of the Changelog entries from the series into a new
file, and run `./scripts/maint/sortChanges.py` on it. That will
@@ -111,38 +108,40 @@ new Tor release:
=== III. Making the source release.
-1. In `maint-0.2.x`, bump the version number in `configure.ac` and run
+1. In `maint-0.?.x`, bump the version number in `configure.ac` and run
`scripts/maint/updateVersions.pl` to update version numbers in other
- places, and commit. Then merge `maint-0.2.x` into `release-0.2.x`.
+ places, and commit. Then merge `maint-0.?.x` into `release-0.?.x`.
(NOTE: To bump the version number, edit `configure.ac`, and then run
either `make`, or `perl scripts/maint/updateVersions.pl`, depending on
your version.)
-2. Make distcheck, put the tarball up somewhere, and tell `#tor` about
- it. Wait a while to see if anybody has problems building it. Try to
- get Sebastian or somebody to try building it on Windows.
+2. Make distcheck, put the tarball up in somewhere (how about your
+ homedir on your homedir on people.torproject.org?) , and tell `#tor`
+ about it. Wait a while to see if anybody has problems building it.
+ (Though jenkins is usually pretty good about catching these things.)
=== IV. Commit, upload, announce
1. Sign the tarball, then sign and push the git tag:
gpg -ba <the_tarball>
- git tag -u <keyid> tor-0.2.x.y-status
- git push origin tag tor-0.2.x.y-status
+ git tag -u <keyid> tor-0.3.x.y-status
+ git push origin tag tor-0.3.x.y-status
2. scp the tarball and its sig to the dist website, i.e.
`/srv/dist-master.torproject.org/htdocs/` on dist-master. When you want
it to go live, you run "static-update-component dist.torproject.org"
on dist-master.
- Edit `include/versions.wmi` and `Makefile` to note the new version.
+ In the webwml.git repository, `include/versions.wmi` and `Makefile`
+ to note the new version.
(NOTE: Due to #17805, there can only be one stable version listed at
once. Nonetheless, do not call your version "alpha" if it is stable,
or people will get confused.)
-3. Email the packagers (cc'ing tor-assistants) that a new tarball is up.
+3. Email the packagers (cc'ing tor-team) that a new tarball is up.
The current list of packagers is:
- {weasel,gk,mikeperry} at torproject dot org
@@ -151,11 +150,7 @@ new Tor release:
- {lfleischer} at archlinux dot org
- {Nathan} at freitas dot net
- {mike} at tig dot as
- - {tails-rm} at boum dot org (for pre-release announcments)
-
-
- - {tails-dev} at boum dot org (for at-release announcements)
-
+ - {tails-rm} at boum dot org
4. Add the version number to Trac. To do this, go to Trac, log in,
select "Admin" near the top of the screen, then select "Versions" from
@@ -164,22 +159,26 @@ new Tor release:
0.2.2.23-alpha" (or whatever the version is), and we select the date as
the date in the ChangeLog.
-5. Wait up to a day or two (for a development release), or until most
- packages are up (for a stable release), and mail the release blurb and
- changelog to tor-talk or tor-announce.
+5. Mail the release blurb and ChangeLog to tor-talk (development release) or
+ tor-announce (stable).
+
+ Post the changelog on the the blog as well. You can generate a
+ blog-formatted version of the changelog with the -B option to
+ format-changelog.
- (We might be moving to faster announcements, but don't announce until
- the website is at least updated.)
+ When you post, include an estimate of when the next TorBrowser
+ releases will come out that include this Tor release. This will
+ usually track https://wiki.mozilla.org/RapidRelease/Calendar , but it
+ can vary.
=== V. Aftermath and cleanup
-1. If it's a stable release, bump the version number in the `maint-x.y.z`
- branch to "newversion-dev", and do a `merge -s ours` merge to avoid
- taking that change into master. Do a similar `merge -s theirs`
- merge to get the change (and only that change) into release. (Some
- of the build scripts require that maint merge cleanly into release.)
+1. If it's a stable release, bump the version number in the
+ `maint-x.y.z` branch to "newversion-dev", and do a `merge -s ours`
+ merge to avoid taking that change into master.
2. Forward-port the ChangeLog (and ReleaseNotes if appropriate).
+3. Keep an eye on the blog post, to moderate comments and answer questions.
diff --git a/doc/HACKING/Tracing.md b/doc/HACKING/Tracing.md
new file mode 100644
index 0000000000..a5fb5165e2
--- /dev/null
+++ b/doc/HACKING/Tracing.md
@@ -0,0 +1,91 @@
+# Tracing #
+
+This document describes how the event tracing subsystem works in tor so
+developers can add events to the code base but also hook them to an event
+tracing framework.
+
+## Basics ###
+
+Event tracing is seperated in two concepts, trace events and a tracer. The
+tracing subsystem can be found in `src/trace`. The `events.h` header file is
+the main file that maps the different tracers to trace events.
+
+### Events ###
+
+A trace event is basically a function from which we can pass any data that
+we want to collect. In addition, we specify a context for the event such as
+a subsystem and an event name.
+
+A trace event in tor has the following standard format:
+
+ tor_trace(subsystem, event\_name, args...)
+
+The `subsystem` parameter is the name of the subsytem the trace event is in.
+For example that could be "scheduler" or "vote" or "hs". The idea is to add
+some context to the event so when we collect them we know where it's coming
+from. The `event_name` is the name of the event which helps a lot with
+adding some semantic to the event. Finally, `args` is any number of
+arguments we want to collect.
+
+Here is an example of a possible tracepoint in main():
+
+ tor_trace(main, init_phase, argc)
+
+The above is a tracepoint in the `main` subsystem with `init_phase` as the
+event name and the `int argc` is passed to the event as well.
+
+How `argc` is collected or used has nothing to do with the instrumentation
+(adding trace events to the code). It is the work of the tracer so this is why
+the trace events and collection framework (tracer) are decoupled. You _can_
+have trace events without a tracer.
+
+### Tracer ###
+
+In `src/trace/events.h`, we map the `tor_trace()` function to the right
+tracer. A tracer support is only enabled at compile time. For instance, the
+file `src/trace/debug.h` contains the mapping of the generic tracing function
+`tor_trace()` to the `log_debug()` function. More specialized function can be
+mapped depending on the tracepoint.
+
+## Build System ##
+
+This section describes how it is integrated into the build system of tor.
+
+By default, every tracing events are disabled in tor that is `tor_trace()`
+is a NOP.
+
+To enable a tracer, there is a configure option on the form of:
+
+ --enable-tracing-<tracer>
+
+We have an option that will send every trace events to a `log_debug()` (as
+mentionned above) which will print you the subsystem and name of the event but
+not the arguments for technical reasons. This is useful if you want to quickly
+see if your trace event is being hit or well written. To do so, use this
+configure option:
+
+ --enable-tracing-debug
+
+## Instrument Tor ##
+
+This is pretty easy. Let's say you want to add a trace event in
+`src/or/rendcache.c`, you only have to add this include statement:
+
+ #include "trace/events.h"
+
+Once done, you can add as many as you want `tor_trace()` that you need.
+Please use the right subsystem (here it would be `hs`) and a unique name that
+tells what the event is for. For example:
+
+ tor_trace(hs, store_desc_as_client, desc, desc_id);
+
+If you look in `src/trace/events.h`, you'll see that if tracing is enabled it
+will be mapped to a function called:
+
+ tor_trace_hs_store_desc_as_client(desc, desc_id)
+
+And the point of all this is for that function to be defined in a new file
+that you might want to add named `src/trace/hs.{c|h}` which would defined how
+to collect the data for the `tor_trace_hs_store_desc_as_client()` function
+like for instance sending it to a `log_debug()` or do more complex operations
+or use a userspace tracer like LTTng (https://lttng.org).
diff --git a/doc/HACKING/WritingTests.md b/doc/HACKING/WritingTests.md
index de80bbdef2..4dae41e922 100644
--- a/doc/HACKING/WritingTests.md
+++ b/doc/HACKING/WritingTests.md
@@ -48,7 +48,7 @@ isolation, you just run `./src/test/test-memwipe`.
To run tests within the unit test programs, you can specify the name
of the test. The string ".." can be used as a wildcard at the end of the
test name. For example, to run all the cell format tests, enter
-`./src/test/test cellfmt/..`. To run
+`./src/test/test cellfmt/..`.
Many tests that need to mess with global state run in forked subprocesses in
order to keep from contaminating one another. But when debugging a failing test,