aboutsummaryrefslogtreecommitdiffstats
path: root/vm
diff options
context:
space:
mode:
authorJoey Jiao <joeyjiaojg@gmail.com>2021-03-29 14:37:22 +0800
committerDmitry Vyukov <dvyukov@google.com>2021-04-14 19:04:39 +0200
commite40a490e9c5e71bb3c0aca2a1ddcf7af4845635d (patch)
tree96fb8d65e2b684cd46c579a58a7c20dd5f0e3e39 /vm
parent5c9ed2bcc8d10336c1389d63db51a4bde97b16a0 (diff)
vm/adb: add startup_script config
Diffstat (limited to 'vm')
-rw-r--r--vm/adb/adb.go19
-rwxr-xr-xvm/isolated/isolated.go42
-rw-r--r--vm/isolated/isolated_test.go8
-rw-r--r--vm/vmimpl/vmimpl.go41
4 files changed, 65 insertions, 45 deletions
diff --git a/vm/adb/adb.go b/vm/adb/adb.go
index cbd5109b1..92e49c346 100644
--- a/vm/adb/adb.go
+++ b/vm/adb/adb.go
@@ -40,7 +40,8 @@ type Config struct {
BatteryCheck bool `json:"battery_check"`
// If this option is set (default), the device is rebooted after each crash.
// Set it to false to disable reboots.
- TargetReboot bool `json:"target_reboot"`
+ TargetReboot bool `json:"target_reboot"`
+ StartupScript string `json:"startup_script"` // script to execute after each startup
}
type Pool struct {
@@ -283,7 +284,21 @@ func (inst *instance) repair() error {
}
// Switch to root for userdebug builds.
inst.adb("root")
- return inst.waitForSSH()
+ inst.waitForSSH()
+ if inst.cfg.StartupScript != "" {
+ log.Logf(2, "adb: executing startup_script")
+ // Execute the contents of the StartupScript on the DUT.
+ contents, err := ioutil.ReadFile(inst.cfg.StartupScript)
+ if err != nil {
+ return fmt.Errorf("unable to read startup_script: %v", err)
+ }
+ c := string(contents)
+ if _, err := inst.adb("shell", fmt.Sprintf("sh -c \"%v\"", vmimpl.EscapeDoubleQuotes(c))); err != nil {
+ return fmt.Errorf("failed to execute startup_script: %v", err)
+ }
+ log.Logf(2, "adb: done executing startup_script")
+ }
+ return nil
}
func (inst *instance) waitForSSH() error {
diff --git a/vm/isolated/isolated.go b/vm/isolated/isolated.go
index 3d69683e9..5bff5f1c0 100755
--- a/vm/isolated/isolated.go
+++ b/vm/isolated/isolated.go
@@ -214,46 +214,6 @@ func (inst *instance) waitRebootAndSSH(rebootTimeout int, sshTimeout time.Durati
return nil
}
-// Escapes double quotes(and nested double quote escapes). Ignores any other escapes.
-// Reference: https://www.gnu.org/software/bash/manual/html_node/Double-Quotes.html
-func escapeDoubleQuotes(inp string) string {
- var ret strings.Builder
- for pos := 0; pos < len(inp); pos++ {
- // If inp[pos] is not a double quote or a backslash, just use
- // as is.
- if inp[pos] != '"' && inp[pos] != '\\' {
- ret.WriteByte(inp[pos])
- continue
- }
- // If it is a double quote, escape.
- if inp[pos] == '"' {
- ret.WriteString("\\\"")
- continue
- }
- // If we detect a backslash, reescape only if what it's already escaping
- // is a double-quotes.
- temp := ""
- j := pos
- for ; j < len(inp); j++ {
- if inp[j] == '\\' {
- temp += string(inp[j])
- continue
- }
- // If the escape corresponds to a double quotes, re-escape.
- // Else, just use as is.
- if inp[j] == '"' {
- temp = temp + temp + "\\\""
- } else {
- temp += string(inp[j])
- }
- break
- }
- ret.WriteString(temp)
- pos = j
- }
- return ret.String()
-}
-
func (inst *instance) repair() error {
log.Logf(2, "isolated: trying to ssh")
if err := inst.waitForSSH(30 * time.Minute); err != nil {
@@ -288,7 +248,7 @@ func (inst *instance) repair() error {
return fmt.Errorf("unable to read startup_script: %v", err)
}
c := string(contents)
- if err := inst.ssh(fmt.Sprintf("bash -c \"%v\"", escapeDoubleQuotes(c))); err != nil {
+ if err := inst.ssh(fmt.Sprintf("bash -c \"%v\"", vmimpl.EscapeDoubleQuotes(c))); err != nil {
return fmt.Errorf("failed to execute startup_script: %v", err)
}
log.Logf(2, "isolated: done executing startup_script")
diff --git a/vm/isolated/isolated_test.go b/vm/isolated/isolated_test.go
index 74bbff9f1..f1b4dbda0 100644
--- a/vm/isolated/isolated_test.go
+++ b/vm/isolated/isolated_test.go
@@ -3,7 +3,11 @@
package isolated
-import "testing"
+import (
+ "testing"
+
+ "github.com/google/syzkaller/vm/vmimpl"
+)
func TestEscapeDoubleQuotes(t *testing.T) {
testcases := []struct {
@@ -65,7 +69,7 @@ bash -c \"bash -c \\\"ls -al\\\"\"`,
},
}
for i, tc := range testcases {
- output := escapeDoubleQuotes(tc.inp)
+ output := vmimpl.EscapeDoubleQuotes(tc.inp)
if tc.expected != output {
t.Fatalf("%v: For input %v Expected escaped string %v got %v", i+1, tc.inp, tc.expected, output)
}
diff --git a/vm/vmimpl/vmimpl.go b/vm/vmimpl/vmimpl.go
index b3b7b19e4..854bef0a0 100644
--- a/vm/vmimpl/vmimpl.go
+++ b/vm/vmimpl/vmimpl.go
@@ -14,6 +14,7 @@ import (
"math/rand"
"net"
"os/exec"
+ "strings"
"time"
"github.com/google/syzkaller/pkg/log"
@@ -181,3 +182,43 @@ func UnusedTCPPort() int {
}
}
}
+
+// Escapes double quotes(and nested double quote escapes). Ignores any other escapes.
+// Reference: https://www.gnu.org/software/bash/manual/html_node/Double-Quotes.html
+func EscapeDoubleQuotes(inp string) string {
+ var ret strings.Builder
+ for pos := 0; pos < len(inp); pos++ {
+ // If inp[pos] is not a double quote or a backslash, just use
+ // as is.
+ if inp[pos] != '"' && inp[pos] != '\\' {
+ ret.WriteByte(inp[pos])
+ continue
+ }
+ // If it is a double quote, escape.
+ if inp[pos] == '"' {
+ ret.WriteString("\\\"")
+ continue
+ }
+ // If we detect a backslash, reescape only if what it's already escaping
+ // is a double-quotes.
+ temp := ""
+ j := pos
+ for ; j < len(inp); j++ {
+ if inp[j] == '\\' {
+ temp += string(inp[j])
+ continue
+ }
+ // If the escape corresponds to a double quotes, re-escape.
+ // Else, just use as is.
+ if inp[j] == '"' {
+ temp = temp + temp + "\\\""
+ } else {
+ temp += string(inp[j])
+ }
+ break
+ }
+ ret.WriteString(temp)
+ pos = j
+ }
+ return ret.String()
+}