diff --git a/pkg/sentry/kernel/task_exec.go b/pkg/sentry/kernel/task_exec.go index 20c74ef637..56b2673fd1 100644 --- a/pkg/sentry/kernel/task_exec.go +++ b/pkg/sentry/kernel/task_exec.go @@ -473,7 +473,7 @@ func getExecveSeccheckInfo(t *Task, argv, env []string, executable *vfs.FileDesc if fields.Local.Contains(seccheck.FieldSentryExecveBinaryInfo) { info.BinaryOverlayfsUpper = overlay.IsCopiedUp(executable.Dentry()) statOpts := vfs.StatOptions{ - Mask: linux.STATX_TYPE | linux.STATX_MODE | linux.STATX_UID | linux.STATX_GID | linux.STATX_INO, + Mask: linux.STATX_TYPE | linux.STATX_MODE | linux.STATX_UID | linux.STATX_GID | linux.STATX_INO | linux.STATX_CTIME, } if stat, err := executable.Stat(t, statOpts); err == nil { if stat.Mask&(linux.STATX_TYPE|linux.STATX_MODE) == (linux.STATX_TYPE | linux.STATX_MODE) { @@ -488,6 +488,12 @@ func getExecveSeccheckInfo(t *Task, argv, env []string, executable *vfs.FileDesc if stat.Mask&linux.STATX_INO != 0 { info.BinaryIno = stat.Ino } + if stat.Mask&linux.STATX_CTIME != 0 { + info.BinaryCtime = &pb.Timespec{ + Sec: stat.Ctime.Sec, + Nsec: int64(stat.Ctime.Nsec), + } + } } } diff --git a/pkg/sentry/seccheck/points/common.proto b/pkg/sentry/seccheck/points/common.proto index 0c90823ff1..a265cf95ad 100644 --- a/pkg/sentry/seccheck/points/common.proto +++ b/pkg/sentry/seccheck/points/common.proto @@ -64,6 +64,11 @@ message Handshake { uint32 version = 1; } +message Timespec { + int64 sec = 1; + int64 nsec = 2; +} + message Credentials { uint32 real_uid = 1; uint32 effective_uid = 2; diff --git a/pkg/sentry/seccheck/points/sentry.proto b/pkg/sentry/seccheck/points/sentry.proto index 0d264e723f..b5f143e236 100644 --- a/pkg/sentry/seccheck/points/sentry.proto +++ b/pkg/sentry/seccheck/points/sentry.proto @@ -66,6 +66,9 @@ message ExecveInfo { // BinaryIno is the virtualized inode number of the executable binary file. uint64 binary_ino = 10; + + // BinaryCtime is the ctime of the executable binary file. + gvisor.common.Timespec binary_ctime = 11; } message ExitNotifyParentInfo { @@ -105,4 +108,7 @@ message MmapInfo { // IsInitialMmap indicates whether this mapping corresponds to the task's // initial executable file. bool is_initial_mmap = 7; + + // MappedCtime is the ctime of the backing file. + gvisor.common.Timespec mapped_ctime = 8; } diff --git a/pkg/sentry/seccheck/points/syscall.proto b/pkg/sentry/seccheck/points/syscall.proto index 011d62a583..6da98c9fc4 100644 --- a/pkg/sentry/seccheck/points/syscall.proto +++ b/pkg/sentry/seccheck/points/syscall.proto @@ -239,14 +239,9 @@ message TimerfdCreate { int32 flags = 5; } -message Timespec { - int64 sec = 1; - int64 nsec = 2; -} - message ItimerSpec { - Timespec interval = 1; - Timespec value = 2; + gvisor.common.Timespec interval = 1; + gvisor.common.Timespec value = 2; } message TimerfdSetTime { diff --git a/pkg/sentry/syscalls/linux/sys_mmap.go b/pkg/sentry/syscalls/linux/sys_mmap.go index 58c8f00bc2..7cf27277a6 100644 --- a/pkg/sentry/syscalls/linux/sys_mmap.go +++ b/pkg/sentry/syscalls/linux/sys_mmap.go @@ -369,7 +369,7 @@ func traceMmap(t *kernel.Task, file *vfs.FileDescription) error { if file != nil { info.MappedPath = file.MappedName(t) statOpts := vfs.StatOptions{ - Mask: linux.STATX_TYPE | linux.STATX_MODE | linux.STATX_UID | linux.STATX_GID | linux.STATX_INO, + Mask: linux.STATX_TYPE | linux.STATX_MODE | linux.STATX_UID | linux.STATX_GID | linux.STATX_INO | linux.STATX_CTIME, } if stat, err := file.Stat(t, statOpts); err == nil { if stat.Mask&(linux.STATX_TYPE|linux.STATX_MODE) == (linux.STATX_TYPE | linux.STATX_MODE) { @@ -384,6 +384,12 @@ func traceMmap(t *kernel.Task, file *vfs.FileDescription) error { if stat.Mask&linux.STATX_INO != 0 { info.MappedIno = stat.Ino } + if stat.Mask&linux.STATX_CTIME != 0 { + info.MappedCtime = &ppb.Timespec{ + Sec: stat.Ctime.Sec, + Nsec: int64(stat.Ctime.Nsec), + } + } } } if exe := t.MemoryManager().Executable(); exe != nil { diff --git a/test/trace/trace_test.go b/test/trace/trace_test.go index 85a695ea5f..687966a708 100644 --- a/test/trace/trace_test.go +++ b/test/trace/trace_test.go @@ -273,6 +273,9 @@ func checkSentryMmap(msg test.Message) error { if p.IsInitialMmap || p.MappedPath != "" { fmt.Printf("Mmap event: path=%q, ino=%d, mode=%o, uid=%d, gid=%d, initial=%v\n", p.MappedPath, p.MappedIno, p.MappedMode, p.MappedUid, p.MappedGid, p.IsInitialMmap) } + if p.MappedPath != "" && (p.MappedCtime == nil || p.MappedCtime.Sec == 0) { + return fmt.Errorf("MappedCtime should not be empty for mapped file: %q", p.MappedPath) + } if err := checkContextData(p.ContextData); err != nil { return err } @@ -431,6 +434,9 @@ func checkSentryExec(msg test.Message) error { if p.BinaryIno == 0 { return fmt.Errorf("BinaryIno should not be 0") } + if p.BinaryCtime == nil || p.BinaryCtime.Sec == 0 { + return fmt.Errorf("BinaryCtime should not be empty") + } // Get SHA256 from the binary and compare it with the one from the event. out, err := exec.Command("sha256sum", p.BinaryPath).CombinedOutput()