Commit Graph

187 Commits (8c03afee953d7e63315c79bc39ba042bbf25bee9)
 

Author SHA1 Message Date
Andrew LeFevre 8c03afee95
Use latest Binject/debug version to support importmap directives, fixes #146 (#189)
* Use latest Binject/debug version to support importmap directives in the importcfg file

* Uncomment line in goprivate testscript to test ImportMap

* Fixed issue where a package in specified in importmap would be hashed differently in a package that imported it, due to the mapping of import paths.

Also commented out the 'net' import in the goprivate testscript (again) due to cgo compile errors
4 years ago
Daniel Martí 3e7416ee9e
add test case for ImportMap support (#186)
We also update the "original types importer" to support ImportMap.

The test now gets further along, no longer getting stuck on "path not
found in listed packages". Instead, we get stuck on:

	error parsing importcfg: <...>/importcfg:2: unknown directive "importmap"

This bug has been filed at https://github.com/Binject/debug/issues/17.
Until it's fixed, we can't really proceed on #146, so the net import in
the test file (which triggers this case) is commented out for now.

Updates #146.
4 years ago
Daniel Martí 1336711c9c
CONTRIBUTING: include some basic terminology (#188)
Fixes #132.
4 years ago
lu4p e35f19ab1b
Add a Contributing section to the README (#187)
Fixes #185
4 years ago
Daniel Martí 39372a8c9b testdata: don't let tests rely on rewriting mod files
In Go 1.15, if a dependency is required but not listed in go.mod/go.sum,
it's resolved and added automatically.

This is changing in 1.16. From that release, one will have to explicitly
update the mod files via 'go mod tidy' or 'go get'.

To get ahead of the curve, start using -mod=readonly to get the same
behavior in 1.15, and fix all existing tests.

The only tests that failed were imports.txt and syntax.txt, the only
ones to require other modules. But since we're here, let's add the 'go'
line to all go.mod files as well.
4 years ago
Daniel Martí 4e79bfc01a
warn when a public package imports a private package (#182)
That is, a package that is built without obfuscation imports an
obfuscated package. This will result in confusing compilation error
messages, because the importer can't find the exported names from the
imported package by their non-obfuscated names:

	> ! garble build ./importer
	[stderr]
	# test/main/importer
	importer/importer.go:5:9: undefined: imported.Name
	exit status 2

Instead, detect this bad input case and provide a nice error:

	public package "test/main/importer" can't depend on obfuscated package "test/main/imported" (matched via GOPRIVATE="test/main/imported")

For now, this is by design. It also makes little sense for a public
package to import an obfuscated package in general, because the public
package would have to leak details about the private package's API and
behavior.

While at it, fix a quirk where we thought the unsafe package could be
private. It can't be, because the runtime package is always public and
it imports the runtime package:

	public package "internal/bytealg" can't depend on obfuscated package "unsafe" (matched via GOPRIVATE="*")

Instead of trying to obfuscate "unsafe" and doing nothing, simply add it
to the neverPrivate list, which is also a better name than
"privateBlacklist" (for #169).

Fixes #164.

Co-authored-by: lu4p <lu4p@pm.me>
4 years ago
Andrew LeFevre 523cc4454f
Hash identical package names from different package paths differently (#172) 4 years ago
Nick 43163c2e9b Remove the `usesUnsafe` global variable as it's unused
I've tested the code on unsafe code bases as well, I truly believe that
this variable is not necessary/used.
4 years ago
Nick d4eee0c9bc Replaced asthelper.Ident with ast.NewIdent
No point in having around a helper method that has been implemented for
us by `go/ast`
4 years ago
Daniel Martí 07fd9d5beb introduce a receiver type to transform a Go package
Means that we no longer have to pass a dozen parameters around, mainly
to transformGo. We can also start documenting what each of the fields
actually does, and group them better.

While at it, pkgPath and pkgScope can both be replaced by a
*types.Package, since they're both accessible via trivially cheap
methods.
4 years ago
Andrew LeFevre bca460e36e
Print interfaces/pointers when -tiny is used (#170)
fixes #167
4 years ago
Daniel Martí 7ad246c6fe
testdata: make tiny.txt simpler and faster (#168)
By avoiding the fmt import, we save some work: 'go test -run Script/tiny'
goes down from 0.8s to 0.5s even with a warm build cache.

Since the output changes between runs, we use stderr grep lines instead
of cmp. This way we can also check that the "oh noes" panic is entirely
hidden in the tiny mode.
4 years ago
Daniel Martí 95501f0fcd
testdata: avoid unnecessary deps in init.txt (#166)
We can use println instead of fmt.Println. Similarly, we can avoid
strings.Join by just appending bytes to a []byte.

This is less important now that we have build caching, but it still
helps to do less work overall and link smaller binaries.

Reduces 'go test -run Script/init' from 0.5s to 0.3s on my laptop.

Also, properly format the Go in that file, since the space indentation
wasn't noticed during code review. We might want to enforce gofmt in Go
files within txtar files if this keeps happening.
4 years ago
Andrew LeFevre 6cf1eb6d49
keep init funcs in original order (#165) 4 years ago
Andrew LeFevre 1fc990dcf8
Fix bug where structs would get garbled in some packages but not in others (#161)
* fix bug where structs would get garbled in some packages but not in others

* only check if struct/field was not defined in current package

* fix a related bug when two objects share the same name in the same package and one is garbled but the other one is not

* renamed parameter for clarity
4 years ago
Andrew LeFevre 047aa254e2
properly remove all filenames when -tiny is passed (#160)
* properly remove all filenames when -tiny is passed

* document filename symbol removal
4 years ago
Andrew LeFevre 0e0a9fc594
Allow struct fields to be garbled, fixes #48 (#159)
* Allow struct fields to be garbled, fixes #48

* fix syntax test script

* simplified code according to review
4 years ago
pagran 803c1d9439
Store obfuscated sources in object files (#158)
Now the flag "-debugdir" does not trigger a full recompilation.
Obfuscated source files are saved to object files and are extracted during linking.
4 years ago
Daniel Martí 29378787e2
CI: comment out test-gotip for now (#157)
Since it's been failing for weeks, it's practically useless for now.
Even with continue-on-error, the failures still look scary at first
glance.

We can re-enable this job once we fix master.
4 years ago
Daniel Martí b823b07443 testdata: avoid 'go build' with -short in literals.txt
Use a static main.stderr file, like in the other tests. This means we
don't need to always start the test with a 'go build', and the output is
also obvious by just reading the txtar file.

We can also move generate-literals to a later stage, so that 'go test
-short' needs to do even less work.

'go test -short -run Script/literals' drops from ~0.4s to ~0.2s on my
laptop.

Finally, make the printing of byte lists not use trailing spaces, so
that the txtar file itself doesn't have trailing whitespace in its lines
either.

Fixes #103.
4 years ago
Daniel Martí 1e19d136c7 testdata: make syntax.txt pass when offline
The test intended to use an extra module to be obfuscated, rsc.io/quote,
which we were bundling in the local proxy as well. Unfortunately, the
use of GOPRIVATE also meant that we did not actually fetch the module
from the proxy, and we would instead do a full roundtrip to the internet
to "git clone" the actual upstream repository.

To prevent that roundtrip, instead use a locally replaced module. This
fits the syntax.txt test too, since it's one more edge case that we want
to make sure works well with garble. Since rsc.io/quote is used in
another test, simply make up our own tiny module.

Reduces a 'go test -run Syntax/syntax' run with warm cache from ~5s to
~0.5s, thanks to removing the multiple roundtrips. A warm 'go test' run
still sits at ~6s, since we still need that much CPU time in total.

While at it, fix a staticcheck warning and fix inconsistent indentation
in a couple of tests.
4 years ago
Daniel Martí 2a0ac434fb
initial support for build caching (#142)
As per the discussion in https://github.com/golang/go/issues/41145, it
turns out that we don't need special support for build caching in
-toolexec. We can simply modify the behavior of "[...]/compile -V=full"
and "[...]/link -V=full" so that they include garble's own version and
options in the printed build ID.

The part of the build ID that matters is the last, since it's the
"content ID" which is used to work out whether there is a need to redo
the action (build) or not. Since cmd/go parses the last word in the
output as "buildID=...", we simply add "+garble buildID=_/_/_/${hash}".
The slashes let us imitate a full binary build ID, but we assume that
the other components such as the action ID are not necessary, since the
only reader here is cmd/go and it only consumes the content ID.

The reported content ID includes the tool's original content ID,
garble's own content ID from the built binary, and the garble options
which modify how we obfuscate code. If any of the three changes, we
should use a different build cache key. GOPRIVATE also affects caching,
since a different GOPRIVATE value means that we might have to garble a
different set of packages.

Include tests, which mainly check that 'garble build -v' prints package
lines when we expect to always need to rebuild packages, and that it
prints nothing when we should be reusing the build cache even when the
built binary is missing.

After this change, 'go test' on Go 1.15.2 stabilizes at about 8s on my
machine, whereas it used to be at around 25s before.
4 years ago
Daniel Martí 859221a950 make import path obfuscation work with the build cache
What obfuscateImports did was valid, but unfortunately made the build
cache redo work. This is because we were modifying object files in-place
in the build cache, meaning that the Go tool would think it had to
re-compile those packages.

Instead, write the modified object files in a temporary directory, and
leave the input object files untouched. We require a bit of extra code
to keep track of this and adjust the link argument as well as its
importcfg file.

The function of obfuscateImports, as well as the reasoning above, is now
summarized in its godoc as well.

This should be the last change in preparation for proper build caching
support. Rebasing the build caching branch on this commit finally makes
caching work reliably every single time.
4 years ago
pagran ea4a01df87
More correct comments transformation (#152)
More correct comments transformation was implemented.

Added processing of //go:linkname localname [importpath.name] directive, now localname is not renamed. This is safe and does not cause a name disclosure because the functions marked //linkname do not have a name in the resulting binary.

Added cgo directives support

Fixed filename leak protection for cgo

Part of #149
4 years ago
pagran 991fbb042b
avoid potential short name collisions
Fix for bug when a conflict occurred between generated short names
and local variables/functions/types/structs.

The already existing names are collected and if the generated short name
already exists, the package counter is increased until a free name is found.

Part of #149.
4 years ago
pagran 434df0476d
fixed comments cleaning
Added cleanup of the Comment field.
In some cases, the appearance of a comment in a random place
may break the compilation (e.g. cgo and runtime package).

This is safe because the Comment field cannot contain any directives.

Part of #149.
4 years ago
Daniel Martí 88450a2cbc
update Binject/debug dependency to get its license file (#148)
See https://github.com/Binject/debug/issues/12.

Also update x/tools, while at it.
4 years ago
Daniel Martí 3970bb98cc clean up global buildInfo a bit, fix up godocs
The struct type for buildInfo doesn't need to be named. Plus, the
"packageInfo" name was actually pretty misleading, because buildInfo
contains data from many packages.

Add an importCfg field, so that we don't need to fetch the flag value
many times.

Simplify reading the importCfg file; we used to also write to it, but
that's no longer the case, so we can just use ioutil.ReadFile.

Finally, give the function that fills buildInfo a better name, a godoc,
and fix the origTypesConfig godoc.

We also add a TODO to reuse goobj.ParseImportCfg in the future.
4 years ago
pagran 406036d433
rewrite private name map storage to support build caching
We now store how we obfuscated unexported names in the object file
itself, not a separate file. This means that the data can survive in the
build cache, whereas the separate file was being lost. Luckily, we can
just add an extra header to the archive, and other programs like the Go
linker will just ignore it.
4 years ago
pagran 5c6fa4575f
Remove unused constant and fix magic number (#143)
Removed PosMax constant as it is no longer needed after optimization (b3f04e5) of line obfuscation.
Replaced the magic number with PosMin
4 years ago
Daniel Martí c3bee46a26 testdata: use the debugdir flag less often
In tiny.txt, we already check line numbers via stderr, so there's no
need to do that via -debugdir.

In syntax.txt, we only really care about what names remain in the
binary, not the names which remain in the source but don't affect the
binary.

These changes are important because -debugdir adds a non-trivial amount
of work, which will impede build caching once that feature lands. We
will likely make -debugdir support build caching eventually, but for
now, this preliminary change will make 'go test' much faster with build
caching.

And of course, the tests get simpler, which is nice.
4 years ago
pagran 00c1d5b11d
add test for Go version checking (#140)
Add tests for Go version checking

Fix panic if go version has invalid format

Fixes: #121
Co-authored-by: Daniel Martí <mvdan@mvdan.cc>
4 years ago
Daniel Martí 25b73afaec
follow-up patches to the 'go version' checking (#139)
Give the func a name that tells what the return value means.

Add missing newlines to printfs, use consistent quoting, and replace
"%s" with %q.

Document the Go 1.15 date.

Finally, fix the imports via goimports.
4 years ago
Daniel Martí 6b6a6eee2e
CONTRIBUTING: clarify that tests are required (#138)
See https://github.com/burrowers/garble/issues/121#issuecomment-695935859.

In some rare cases, it's nearly impossible to write a test for a change,
but they are truly so rare that we shouldn't give any ideas here.

By default, all contributors should try to write a test for every
change that changes what the code is meant to do.
4 years ago
pagran 46c111325f
Add go version validation (#136)
Fixes https://github.com/burrowers/garble/issues/121
4 years ago
pagran 90fa325da7
Rewrite renaming logic for private names and reduce length of public names (#135)
1. Now private names are obfuscated based on the counter in scope of the package.
2. The length of public names is reduced to 4 bytes.
4 years ago
Andrew LeFevre 0d182a3dbd remove unnecessary data from runtime if -tiny is passed
Fixes #127. Saves an additional ~1-2% binary size in my testing.
4 years ago
Andrew LeFevre d679944408
Strip all filename and position info when -tiny is passed (#128)
Co-authored-by: pagran <pagran@protonmail.com>
Co-authored-by: lu4p <lu4p@pm.me>
4 years ago
Daniel Martí 1b50a898bd
all: fix links after moving repository (#131)
A couple of places still linked to the personal repo.
4 years ago
Daniel Martí 805c895d59 set up an AUTHORS file to attribute copyright
Many files were missing copyright, so also add a short script to add the
missing lines with the current year, and run it.

The AUTHORS file is also self-explanatory. Contributors can add
themselves there, or we can simply update it from time to time via
git-shortlog.

Since we have two scripts now, set up a directory for them.
4 years ago
lu4p c59283c548 Update FUNDING.yml 4 years ago
lu4p d8d784639f
Validate the user provided seed. (#126)
Also allow base64 seeds without padding.

Fixes #123.
4 years ago
Daniel Martí f764467e9b all: update the docs a bit
Rework the features section in the README, leaving optional features at
the end of the list. Simplify the caveats list, too; the build cache and
exported field/method bits only need one point each. Overall, the
section was far too wordy for little reason.

Also redo the help text a bit. There's now a line to briefly introduce
the tool, as well as a link to the README with all the details. Finally,
the flags have shorter and more consistent help strings.

While at it, remove two unused global vars as spotted by staticcheck.
4 years ago
Andrew LeFevre c8d61c772f
Garble imports and package paths in GOPRIVATE (#116)
Finally, finally this is done. This allows import paths to be obfuscated by modifying
object/archive files and garbling import paths contained within. The bulk of the
code that makes parsing and writing Go object/archive files possible lives at
https://github.com/Binject/debug/tree/master/goobj2, which I wrote as well.

I have tested by garbling and checking for import paths via strings and grep
(in order of difficulty) https://github.com/lu4p/binclude, garble itself, and
https://github.com/dominikh/go-tools/tree/master/cmd/staticcheck.

This only supports object/archive files produced from the Go 1.15 compiler.
The object file format changed at 1.15, and 1.14 and earlier is not supported.

Fixes #13.
4 years ago
Andrew LeFevre 30df5e9bbd
Disable plugin test (#120)
* disable plugin test for now, add note to README

* add link to issue in README

* fix README link to issue
4 years ago
Andrew LeFevre dc02bc9f6b also replace 'println' statements in the runtime with panicprint 4 years ago
Daniel Martí 1bff68d8c8 update go-internal to fix go 1.16
CI's gotip job should now succeed.
4 years ago
Daniel Martí b250b64d2c
update dependency versions, drop Go 1.14
Most notably, x/mod now includes the GOPRIVATE pattern-matching API we
were copying before, so we can use it directly.

Also bump the Go version requirement to 1.15, in preparation for the
import path obfuscation PR, and don't let the gotip job fail the entire
workflow.
4 years ago
pagran bd46c29380
add blacklist for runtime std packages 4 years ago
Daniel Martí 951eb65510 never obfuscate unsafe.Pointer
Before this change, obfuscating any package using unsafe.Pointer and
with GOPRIVATE="*" would result in errors like:

	undefined: unsafe.ZrMmYd1lg

This is because the type isn't plain Go; it's rather a special type that
gets special treatment from the typechecker and compiler:

	type Pointer *ArbitraryType

So, trying to obfuscate the name "unsafe.Pointer" will never work,
because there isn't a real Go type definition we can obfuscate along
with that.

Updates, but does not yet fully fix, #108.
4 years ago