Skip to content

Commit

Permalink
[release-branch.go1.17] misc/wasm, cmd/link: do not let command line …
Browse files Browse the repository at this point in the history
…args overwrite global data

On Wasm, wasm_exec.js puts command line arguments at the beginning
of the linear memory (following the "zero page"). Currently there
is no limit for this, and a very long command line can overwrite
the program's data section. Prevent this by limiting the command
line to 4096 bytes, and in the linker ensuring the data section
starts at a high enough address (8192).

(Arguably our address assignment on Wasm is a bit confusing. This
is the minimum fix I can come up with.)

Thanks to Ben Lubar for reporting this issue.

Change by Cherry Mui <cherryyz@google.com>.

For #48797
Fixes #48800
Fixes CVE-2021-38297

Change-Id: I0f50fbb2a5b6d0d047e3c134a88988d9133e4ab3
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1205933
Reviewed-by: Roland Shoemaker <bracewell@google.com>
Reviewed-by: Than McIntosh <thanm@google.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/354592
Trust: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Heschi Kreinick <heschi@google.com>
  • Loading branch information
mknyszek committed Oct 7, 2021
1 parent b18ba59 commit 4925e07
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 1 deletion.
7 changes: 7 additions & 0 deletions misc/wasm/wasm_exec.js
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,13 @@
offset += 8;
});

// The linker guarantees global data starts from at least wasmMinDataAddr.
// Keep in sync with cmd/link/internal/ld/data.go:wasmMinDataAddr.
const wasmMinDataAddr = 4096 + 4096;
if (offset >= wasmMinDataAddr) {
throw new Error("command line too long");
}

this._inst.exports.run(argc, argv);
if (this.exited) {
this._resolveExitPromise();
Expand Down
11 changes: 10 additions & 1 deletion src/cmd/link/internal/ld/data.go
Original file line number Diff line number Diff line change
Expand Up @@ -2450,6 +2450,11 @@ func splitTextSections(ctxt *Link) bool {
return (ctxt.IsPPC64() || (ctxt.IsARM64() && ctxt.IsDarwin())) && ctxt.IsExternal()
}

// On Wasm, we reserve 4096 bytes for zero page, then 4096 bytes for wasm_exec.js
// to store command line args. Data sections starts from at least address 8192.
// Keep in sync with wasm_exec.js.
const wasmMinDataAddr = 4096 + 4096

// address assigns virtual addresses to all segments and sections and
// returns all segments in file order.
func (ctxt *Link) address() []*sym.Segment {
Expand All @@ -2459,10 +2464,14 @@ func (ctxt *Link) address() []*sym.Segment {
order = append(order, &Segtext)
Segtext.Rwx = 05
Segtext.Vaddr = va
for _, s := range Segtext.Sections {
for i, s := range Segtext.Sections {
va = uint64(Rnd(int64(va), int64(s.Align)))
s.Vaddr = va
va += s.Length

if ctxt.IsWasm() && i == 0 && va < wasmMinDataAddr {
va = wasmMinDataAddr
}
}

Segtext.Length = va - uint64(*FlagTextAddr)
Expand Down

0 comments on commit 4925e07

Please sign in to comment.