diff --git a/pkg/sentry/kernel/task_exec.go b/pkg/sentry/kernel/task_exec.go index 85a662810..baeddbb66 100644 --- a/pkg/sentry/kernel/task_exec.go +++ b/pkg/sentry/kernel/task_exec.go @@ -65,13 +65,18 @@ package kernel // """ import ( + "crypto/sha256" + "io" + "gvisor.dev/gvisor/pkg/abi/linux" "gvisor.dev/gvisor/pkg/cleanup" "gvisor.dev/gvisor/pkg/errors/linuxerr" + "gvisor.dev/gvisor/pkg/log" "gvisor.dev/gvisor/pkg/sentry/mm" "gvisor.dev/gvisor/pkg/sentry/seccheck" pb "gvisor.dev/gvisor/pkg/sentry/seccheck/points/points_go_proto" "gvisor.dev/gvisor/pkg/sentry/vfs" + "gvisor.dev/gvisor/pkg/usermem" ) // execStop is a TaskStop that a task sets on itself when it wants to execve @@ -333,6 +338,29 @@ func getExecveSeccheckInfo(t *Task, argv, env []string, executable *vfs.FileDesc } } } + + if fields.Local.Contains(seccheck.FieldSentryExecveBinarySha256) { + hash := sha256.New() + buf := make([]byte, 1024*1024) // Read 1MB at a time. + dest := usermem.BytesIOSequence(buf) + offset := int64(0) + + for { + if read, err := executable.PRead(t, dest, offset, vfs.ReadOptions{}); err == nil { + hash.Write(buf[0:read]) + offset += read + + } else if err == io.EOF { + hash.Write(buf[0:read]) + info.BinarySha256 = hash.Sum(nil) + break + + } else { + log.Warningf("Failed to read executable for SHA-256 hash: %v", err) + break + } + } + } } if !fields.Context.Empty() { diff --git a/pkg/sentry/seccheck/metadata.go b/pkg/sentry/seccheck/metadata.go index c4d949d4d..463e30239 100644 --- a/pkg/sentry/seccheck/metadata.go +++ b/pkg/sentry/seccheck/metadata.go @@ -60,6 +60,10 @@ const ( // FieldSentryExecveBinaryInfo is an optional field to collect information // about the binary being executed. FieldSentryExecveBinaryInfo Field = iota + + // FieldSentryExecveBinarySha256 is an optional field to collect the SHA-256 + // hash of the binary being executed. + FieldSentryExecveBinarySha256 ) // Points is a map with all the trace points registered in the system. @@ -240,6 +244,10 @@ func genericInit() { ID: FieldSentryExecveBinaryInfo, Name: "binary_info", }, + { + ID: FieldSentryExecveBinarySha256, + Name: "binary_sha256", + }, }, ContextFields: defaultContextFields, }) diff --git a/test/trace/trace_test.go b/test/trace/trace_test.go index 0a050aab7..09bfafe09 100644 --- a/test/trace/trace_test.go +++ b/test/trace/trace_test.go @@ -409,6 +409,22 @@ func checkSentryExec(msg test.Message) error { if p.BinaryGid != nobody { return fmt.Errorf("BinaryGid, want: %d, got: %d", nobody, p.BinaryGid) } + + // Get SHA256 from the binary and compare it with the one from the event. + out, err := exec.Command("sha256sum", p.BinaryPath).CombinedOutput() + if err != nil { + return fmt.Errorf("Not able to calculate sha256sum: %v", err) + } + want := strings.SplitN(string(out), " ", 2)[0] + + got := "" + for _, b := range p.BinarySha256 { + got += fmt.Sprintf("%02x", b) + } + if want != got { + return fmt.Errorf("BinarySha256, want: %q, got: %q", got, want) + } + return nil }