From 3e0062480650ded910ef6bc80883668da89e2ef8 Mon Sep 17 00:00:00 2001 From: Bin Lu Date: Tue, 26 Nov 2019 15:57:07 +0800 Subject: passed the kvm test case of "TestApplicationSyscall" on Arm64 platform For test case "TestApplicationSyscall", Syscall in guest user level will be trapped in el0_svc. And in el0_svc, we use mmio_exit to leave the KVM guest for now. Signed-off-by: Bin Lu --- pkg/sentry/platform/ring0/entry_arm64.s | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pkg/sentry/platform/ring0/entry_arm64.s b/pkg/sentry/platform/ring0/entry_arm64.s index 29c475882..bd9f09469 100644 --- a/pkg/sentry/platform/ring0/entry_arm64.s +++ b/pkg/sentry/platform/ring0/entry_arm64.s @@ -441,6 +441,16 @@ TEXT ·El0_sync(SB),NOSPLIT,$0 B el0_invalid el0_svc: + WORD $0xd538d092 //MRS TPIDR_EL1, R18 + + MOVD $0, CPU_ERROR_CODE(RSV_REG) // Clear error code. + + MOVD $1, R3 + MOVD R3, CPU_ERROR_TYPE(RSV_REG) // Set error type to user. + + MOVD $Syscall, R3 + MOVD R3, CPU_VECTOR_CODE(RSV_REG) + B ·Halt(SB) el0_da: -- cgit v1.2.3 From 3f0e91b00450f926d8378ebd518b557c1f273712 Mon Sep 17 00:00:00 2001 From: Bin Lu Date: Tue, 26 Nov 2019 15:59:51 +0800 Subject: passed the kvm test case of "TestApplicationFault" on Arm64 platform For test case "TestApplicationFault", Memory-fault in guest user level will be trapped in el0_da. And in el0_da, we use mmio_exit to leave the KVM guest. Signed-off-by: Bin Lu --- pkg/sentry/platform/ring0/entry_arm64.s | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/pkg/sentry/platform/ring0/entry_arm64.s b/pkg/sentry/platform/ring0/entry_arm64.s index 29c475882..7b7420785 100644 --- a/pkg/sentry/platform/ring0/entry_arm64.s +++ b/pkg/sentry/platform/ring0/entry_arm64.s @@ -444,6 +444,17 @@ el0_svc: B ·Halt(SB) el0_da: + WORD $0xd538d092 //MRS TPIDR_EL1, R18 + WORD $0xd538601a //MRS FAR_EL1, R26 + + MOVD R26, CPU_FAULT_ADDR(RSV_REG) + + MOVD $1, R3 + MOVD R3, CPU_ERROR_TYPE(RSV_REG) // Set error type to user. + + MOVD $PageFault, R3 + MOVD R3, CPU_VECTOR_CODE(RSV_REG) + B ·Halt(SB) el0_ia: -- cgit v1.2.3 From 200cf245c4ed43d8e2a37484cdbc36f5fbfa1ac9 Mon Sep 17 00:00:00 2001 From: Marek Majkowski Date: Tue, 31 Dec 2019 16:49:30 +0100 Subject: netstack: minor fix typo in "if err" handler --- pkg/tcpip/sample/tun_tcp_connect/main.go | 2 +- pkg/tcpip/sample/tun_tcp_echo/main.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/tcpip/sample/tun_tcp_connect/main.go b/pkg/tcpip/sample/tun_tcp_connect/main.go index 2239c1e66..0ab089208 100644 --- a/pkg/tcpip/sample/tun_tcp_connect/main.go +++ b/pkg/tcpip/sample/tun_tcp_connect/main.go @@ -164,7 +164,7 @@ func main() { // Create TCP endpoint. var wq waiter.Queue ep, e := s.NewEndpoint(tcp.ProtocolNumber, ipv4.ProtocolNumber, &wq) - if err != nil { + if e != nil { log.Fatal(e) } diff --git a/pkg/tcpip/sample/tun_tcp_echo/main.go b/pkg/tcpip/sample/tun_tcp_echo/main.go index bca73cbb1..9e37cab18 100644 --- a/pkg/tcpip/sample/tun_tcp_echo/main.go +++ b/pkg/tcpip/sample/tun_tcp_echo/main.go @@ -168,7 +168,7 @@ func main() { // Create TCP endpoint, bind it, then start listening. var wq waiter.Queue ep, e := s.NewEndpoint(tcp.ProtocolNumber, proto, &wq) - if err != nil { + if e != nil { log.Fatal(e) } -- cgit v1.2.3 From de0d127ae61df783745880871a199ff86a720035 Mon Sep 17 00:00:00 2001 From: Haibo Xu Date: Tue, 31 Dec 2019 08:44:06 +0000 Subject: Make some of the fcntl flags arch specific.. Some of the flags in the file system related system call are architecture specific(O_NOFOLLOW/O_DIRECT..). Ref to the fcntl.h file in the Linux src codes. Signed-off-by: Haibo Xu Change-Id: I354d988073bfd0c9ff5371d4e0be9da2b8fd019f --- pkg/abi/linux/file.go | 38 +++++++++++++++++--------------------- pkg/abi/linux/file_amd64.go | 8 ++++++++ pkg/abi/linux/file_arm64.go | 8 ++++++++ 3 files changed, 33 insertions(+), 21 deletions(-) diff --git a/pkg/abi/linux/file.go b/pkg/abi/linux/file.go index 16791d03e..64bee84b4 100644 --- a/pkg/abi/linux/file.go +++ b/pkg/abi/linux/file.go @@ -24,27 +24,23 @@ import ( // Constants for open(2). const ( - O_ACCMODE = 000000003 - O_RDONLY = 000000000 - O_WRONLY = 000000001 - O_RDWR = 000000002 - O_CREAT = 000000100 - O_EXCL = 000000200 - O_NOCTTY = 000000400 - O_TRUNC = 000001000 - O_APPEND = 000002000 - O_NONBLOCK = 000004000 - O_DSYNC = 000010000 - O_ASYNC = 000020000 - O_DIRECT = 000040000 - O_LARGEFILE = 000100000 - O_DIRECTORY = 000200000 - O_NOFOLLOW = 000400000 - O_NOATIME = 001000000 - O_CLOEXEC = 002000000 - O_SYNC = 004000000 // __O_SYNC in Linux - O_PATH = 010000000 - O_TMPFILE = 020000000 // __O_TMPFILE in Linux + O_ACCMODE = 000000003 + O_RDONLY = 000000000 + O_WRONLY = 000000001 + O_RDWR = 000000002 + O_CREAT = 000000100 + O_EXCL = 000000200 + O_NOCTTY = 000000400 + O_TRUNC = 000001000 + O_APPEND = 000002000 + O_NONBLOCK = 000004000 + O_DSYNC = 000010000 + O_ASYNC = 000020000 + O_NOATIME = 001000000 + O_CLOEXEC = 002000000 + O_SYNC = 004000000 // __O_SYNC in Linux + O_PATH = 010000000 + O_TMPFILE = 020000000 // __O_TMPFILE in Linux ) // Constants for fstatat(2). diff --git a/pkg/abi/linux/file_amd64.go b/pkg/abi/linux/file_amd64.go index 74c554be6..9d307e840 100644 --- a/pkg/abi/linux/file_amd64.go +++ b/pkg/abi/linux/file_amd64.go @@ -14,6 +14,14 @@ package linux +// Constants for open(2). +const ( + O_DIRECT = 000040000 + O_LARGEFILE = 000100000 + O_DIRECTORY = 000200000 + O_NOFOLLOW = 000400000 +) + // Stat represents struct stat. type Stat struct { Dev uint64 diff --git a/pkg/abi/linux/file_arm64.go b/pkg/abi/linux/file_arm64.go index f16c07589..26a54f416 100644 --- a/pkg/abi/linux/file_arm64.go +++ b/pkg/abi/linux/file_arm64.go @@ -14,6 +14,14 @@ package linux +// Constants for open(2). +const ( + O_DIRECTORY = 000040000 + O_NOFOLLOW = 000100000 + O_DIRECT = 000200000 + O_LARGEFILE = 000400000 +) + // Stat represents struct stat. type Stat struct { Dev uint64 -- cgit v1.2.3 From c0e39a8271198f10407009ec1994e5d9efac796c Mon Sep 17 00:00:00 2001 From: Haibo Xu Date: Fri, 20 Dec 2019 06:00:30 +0000 Subject: Enable uname syscall support on arm64. Signed-off-by: Haibo Xu Change-Id: I206f38416a64d7c6a8531d8eb305c6ea239616b8 --- pkg/sentry/syscalls/linux/sys_utsname.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/pkg/sentry/syscalls/linux/sys_utsname.go b/pkg/sentry/syscalls/linux/sys_utsname.go index 748e8dd8d..a393e28c1 100644 --- a/pkg/sentry/syscalls/linux/sys_utsname.go +++ b/pkg/sentry/syscalls/linux/sys_utsname.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -// +build amd64 +// +build amd64 arm64 package linux @@ -35,7 +35,15 @@ func Uname(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall copy(u.Nodename[:], uts.HostName()) copy(u.Release[:], version.Release) copy(u.Version[:], version.Version) - copy(u.Machine[:], "x86_64") // build tag above. + // build tag above. + switch t.SyscallTable().Arch { + case arch.AMD64: + copy(u.Machine[:], "x86_64") + case arch.ARM64: + copy(u.Machine[:], "aarch64") + default: + copy(u.Machine[:], "unknown") + } copy(u.Domainname[:], uts.DomainName()) // Copy out the result. -- cgit v1.2.3 From d46c397a1cd38f1e2aa5c864c1bb8594fb87bb63 Mon Sep 17 00:00:00 2001 From: Fabricio Voznika Date: Tue, 21 Jan 2020 13:26:50 -0800 Subject: Add line break to /proc/net files Some files were missing the last line break. PiperOrigin-RevId: 290808898 --- pkg/sentry/fs/proc/net.go | 14 +++++++------- pkg/sentry/fsimpl/proc/tasks_net.go | 14 +++++++------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/pkg/sentry/fs/proc/net.go b/pkg/sentry/fs/proc/net.go index 3f17e98ea..bad445f3f 100644 --- a/pkg/sentry/fs/proc/net.go +++ b/pkg/sentry/fs/proc/net.go @@ -52,17 +52,17 @@ func (p *proc) newNetDir(ctx context.Context, k *kernel.Kernel, msrc *fs.MountSo // implemented in netstack, if the file contains a // header the stub is just the header otherwise it is // an empty file. - "arp": newStaticProcInode(ctx, msrc, []byte("IP address HW type Flags HW address Mask Device")), + "arp": newStaticProcInode(ctx, msrc, []byte("IP address HW type Flags HW address Mask Device\n")), - "netlink": newStaticProcInode(ctx, msrc, []byte("sk Eth Pid Groups Rmem Wmem Dump Locks Drops Inode")), - "netstat": newStaticProcInode(ctx, msrc, []byte("TcpExt: SyncookiesSent SyncookiesRecv SyncookiesFailed EmbryonicRsts PruneCalled RcvPruned OfoPruned OutOfWindowIcmps LockDroppedIcmps ArpFilter TW TWRecycled TWKilled PAWSPassive PAWSActive PAWSEstab DelayedACKs DelayedACKLocked DelayedACKLost ListenOverflows ListenDrops TCPPrequeued TCPDirectCopyFromBacklog TCPDirectCopyFromPrequeue TCPPrequeueDropped TCPHPHits TCPHPHitsToUser TCPPureAcks TCPHPAcks TCPRenoRecovery TCPSackRecovery TCPSACKReneging TCPFACKReorder TCPSACKReorder TCPRenoReorder TCPTSReorder TCPFullUndo TCPPartialUndo TCPDSACKUndo TCPLossUndo TCPLostRetransmit TCPRenoFailures TCPSackFailures TCPLossFailures TCPFastRetrans TCPForwardRetrans TCPSlowStartRetrans TCPTimeouts TCPLossProbes TCPLossProbeRecovery TCPRenoRecoveryFail TCPSackRecoveryFail TCPSchedulerFailed TCPRcvCollapsed TCPDSACKOldSent TCPDSACKOfoSent TCPDSACKRecv TCPDSACKOfoRecv TCPAbortOnData TCPAbortOnClose TCPAbortOnMemory TCPAbortOnTimeout TCPAbortOnLinger TCPAbortFailed TCPMemoryPressures TCPSACKDiscard TCPDSACKIgnoredOld TCPDSACKIgnoredNoUndo TCPSpuriousRTOs TCPMD5NotFound TCPMD5Unexpected TCPMD5Failure TCPSackShifted TCPSackMerged TCPSackShiftFallback TCPBacklogDrop TCPMinTTLDrop TCPDeferAcceptDrop IPReversePathFilter TCPTimeWaitOverflow TCPReqQFullDoCookies TCPReqQFullDrop TCPRetransFail TCPRcvCoalesce TCPOFOQueue TCPOFODrop TCPOFOMerge TCPChallengeACK TCPSYNChallenge TCPFastOpenActive TCPFastOpenActiveFail TCPFastOpenPassive TCPFastOpenPassiveFail TCPFastOpenListenOverflow TCPFastOpenCookieReqd TCPSpuriousRtxHostQueues BusyPollRxPackets TCPAutoCorking TCPFromZeroWindowAdv TCPToZeroWindowAdv TCPWantZeroWindowAdv TCPSynRetrans TCPOrigDataSent TCPHystartTrainDetect TCPHystartTrainCwnd TCPHystartDelayDetect TCPHystartDelayCwnd TCPACKSkippedSynRecv TCPACKSkippedPAWS TCPACKSkippedSeq TCPACKSkippedFinWait2 TCPACKSkippedTimeWait TCPACKSkippedChallenge TCPWinProbe TCPKeepAlive TCPMTUPFail TCPMTUPSuccess")), - "packet": newStaticProcInode(ctx, msrc, []byte("sk RefCnt Type Proto Iface R Rmem User Inode")), - "protocols": newStaticProcInode(ctx, msrc, []byte("protocol size sockets memory press maxhdr slab module cl co di ac io in de sh ss gs se re sp bi br ha uh gp em")), + "netlink": newStaticProcInode(ctx, msrc, []byte("sk Eth Pid Groups Rmem Wmem Dump Locks Drops Inode\n")), + "netstat": newStaticProcInode(ctx, msrc, []byte("TcpExt: SyncookiesSent SyncookiesRecv SyncookiesFailed EmbryonicRsts PruneCalled RcvPruned OfoPruned OutOfWindowIcmps LockDroppedIcmps ArpFilter TW TWRecycled TWKilled PAWSPassive PAWSActive PAWSEstab DelayedACKs DelayedACKLocked DelayedACKLost ListenOverflows ListenDrops TCPPrequeued TCPDirectCopyFromBacklog TCPDirectCopyFromPrequeue TCPPrequeueDropped TCPHPHits TCPHPHitsToUser TCPPureAcks TCPHPAcks TCPRenoRecovery TCPSackRecovery TCPSACKReneging TCPFACKReorder TCPSACKReorder TCPRenoReorder TCPTSReorder TCPFullUndo TCPPartialUndo TCPDSACKUndo TCPLossUndo TCPLostRetransmit TCPRenoFailures TCPSackFailures TCPLossFailures TCPFastRetrans TCPForwardRetrans TCPSlowStartRetrans TCPTimeouts TCPLossProbes TCPLossProbeRecovery TCPRenoRecoveryFail TCPSackRecoveryFail TCPSchedulerFailed TCPRcvCollapsed TCPDSACKOldSent TCPDSACKOfoSent TCPDSACKRecv TCPDSACKOfoRecv TCPAbortOnData TCPAbortOnClose TCPAbortOnMemory TCPAbortOnTimeout TCPAbortOnLinger TCPAbortFailed TCPMemoryPressures TCPSACKDiscard TCPDSACKIgnoredOld TCPDSACKIgnoredNoUndo TCPSpuriousRTOs TCPMD5NotFound TCPMD5Unexpected TCPMD5Failure TCPSackShifted TCPSackMerged TCPSackShiftFallback TCPBacklogDrop TCPMinTTLDrop TCPDeferAcceptDrop IPReversePathFilter TCPTimeWaitOverflow TCPReqQFullDoCookies TCPReqQFullDrop TCPRetransFail TCPRcvCoalesce TCPOFOQueue TCPOFODrop TCPOFOMerge TCPChallengeACK TCPSYNChallenge TCPFastOpenActive TCPFastOpenActiveFail TCPFastOpenPassive TCPFastOpenPassiveFail TCPFastOpenListenOverflow TCPFastOpenCookieReqd TCPSpuriousRtxHostQueues BusyPollRxPackets TCPAutoCorking TCPFromZeroWindowAdv TCPToZeroWindowAdv TCPWantZeroWindowAdv TCPSynRetrans TCPOrigDataSent TCPHystartTrainDetect TCPHystartTrainCwnd TCPHystartDelayDetect TCPHystartDelayCwnd TCPACKSkippedSynRecv TCPACKSkippedPAWS TCPACKSkippedSeq TCPACKSkippedFinWait2 TCPACKSkippedTimeWait TCPACKSkippedChallenge TCPWinProbe TCPKeepAlive TCPMTUPFail TCPMTUPSuccess\n")), + "packet": newStaticProcInode(ctx, msrc, []byte("sk RefCnt Type Proto Iface R Rmem User Inode\n")), + "protocols": newStaticProcInode(ctx, msrc, []byte("protocol size sockets memory press maxhdr slab module cl co di ac io in de sh ss gs se re sp bi br ha uh gp em\n")), // Linux sets psched values to: nsec per usec, psched // tick in ns, 1000000, high res timer ticks per sec // (ClockGetres returns 1ns resolution). "psched": newStaticProcInode(ctx, msrc, []byte(fmt.Sprintf("%08x %08x %08x %08x\n", uint64(time.Microsecond/time.Nanosecond), 64, 1000000, uint64(time.Second/time.Nanosecond)))), - "ptype": newStaticProcInode(ctx, msrc, []byte("Type Device Function")), + "ptype": newStaticProcInode(ctx, msrc, []byte("Type Device Function\n")), "route": seqfile.NewSeqFileInode(ctx, &netRoute{s: s}, msrc), "tcp": seqfile.NewSeqFileInode(ctx, &netTCP{k: k}, msrc), "udp": seqfile.NewSeqFileInode(ctx, &netUDP{k: k}, msrc), @@ -73,7 +73,7 @@ func (p *proc) newNetDir(ctx context.Context, k *kernel.Kernel, msrc *fs.MountSo contents["if_inet6"] = seqfile.NewSeqFileInode(ctx, &ifinet6{s: s}, msrc) contents["ipv6_route"] = newStaticProcInode(ctx, msrc, []byte("")) contents["tcp6"] = seqfile.NewSeqFileInode(ctx, &netTCP6{k: k}, msrc) - contents["udp6"] = newStaticProcInode(ctx, msrc, []byte(" sl local_address remote_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode")) + contents["udp6"] = newStaticProcInode(ctx, msrc, []byte(" sl local_address remote_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode\n")) } } d := ramfs.NewDir(ctx, contents, fs.RootOwner, fs.FilePermsFromMode(0555)) diff --git a/pkg/sentry/fsimpl/proc/tasks_net.go b/pkg/sentry/fsimpl/proc/tasks_net.go index 3dbf3ba41..4aaf23e97 100644 --- a/pkg/sentry/fsimpl/proc/tasks_net.go +++ b/pkg/sentry/fsimpl/proc/tasks_net.go @@ -41,12 +41,12 @@ func newNetDir(root *auth.Credentials, inoGen InoGenerator, k *kernel.Kernel) *k var contents map[string]*kernfs.Dentry if stack := k.NetworkStack(); stack != nil { const ( - arp = "IP address HW type Flags HW address Mask Device" - netlink = "sk Eth Pid Groups Rmem Wmem Dump Locks Drops Inode" - packet = "sk RefCnt Type Proto Iface R Rmem User Inode" - protocols = "protocol size sockets memory press maxhdr slab module cl co di ac io in de sh ss gs se re sp bi br ha uh gp em" - ptype = "Type Device Function" - upd6 = " sl local_address remote_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode" + arp = "IP address HW type Flags HW address Mask Device\n" + netlink = "sk Eth Pid Groups Rmem Wmem Dump Locks Drops Inode\n" + packet = "sk RefCnt Type Proto Iface R Rmem User Inode\n" + protocols = "protocol size sockets memory press maxhdr slab module cl co di ac io in de sh ss gs se re sp bi br ha uh gp em\n" + ptype = "Type Device Function\n" + upd6 = " sl local_address remote_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode\n" ) psched := fmt.Sprintf("%08x %08x %08x %08x\n", uint64(time.Microsecond/time.Nanosecond), 64, 1000000, uint64(time.Second/time.Nanosecond)) @@ -779,6 +779,6 @@ func (d *netStatData) Generate(ctx context.Context, buf *bytes.Buffer) error { "TCPHystartTrainCwnd TCPHystartDelayDetect TCPHystartDelayCwnd " + "TCPACKSkippedSynRecv TCPACKSkippedPAWS TCPACKSkippedSeq " + "TCPACKSkippedFinWait2 TCPACKSkippedTimeWait TCPACKSkippedChallenge " + - "TCPWinProbe TCPKeepAlive TCPMTUPFail TCPMTUPSuccess") + "TCPWinProbe TCPKeepAlive TCPMTUPFail TCPMTUPSuccess\n") return nil } -- cgit v1.2.3 From cbc0a92276b75e744511a43a9c0b78fc64946ec6 Mon Sep 17 00:00:00 2001 From: Ryan Heacock Date: Tue, 21 Jan 2020 14:15:01 -0800 Subject: Correct todos referencing IPV6_RECVTCLASS Bug 68320120 was revived because TODOs referenced the IP_RECVTOS bug instead of the IPV6_RECVTCLASS bug. PiperOrigin-RevId: 290820178 --- test/syscalls/linux/udp_socket_test_cases.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/syscalls/linux/udp_socket_test_cases.cc b/test/syscalls/linux/udp_socket_test_cases.cc index 68e0a8109..a2f6ef8cc 100644 --- a/test/syscalls/linux/udp_socket_test_cases.cc +++ b/test/syscalls/linux/udp_socket_test_cases.cc @@ -1349,7 +1349,7 @@ TEST_P(UdpSocketTest, TimestampIoctlPersistence) { // outgoing packets, and that a receiving socket with IP_RECVTOS or // IPV6_RECVTCLASS will create the corresponding control message. TEST_P(UdpSocketTest, SetAndReceiveTOS) { - // TODO(b/68320120): IPV6_RECVTCLASS not supported for netstack. + // TODO(b/144868438): IPV6_RECVTCLASS not supported for netstack. SKIP_IF((GetParam() != AddressFamily::kIpv4) && IsRunningOnGvisor() && !IsRunningWithHostinet()); ASSERT_THAT(bind(s_, addr_[0], addrlen_), SyscallSucceeds()); @@ -1422,7 +1422,7 @@ TEST_P(UdpSocketTest, SetAndReceiveTOS) { // TOS byte on outgoing packets, and that a receiving socket with IP_RECVTOS or // IPV6_RECVTCLASS will create the corresponding control message. TEST_P(UdpSocketTest, SendAndReceiveTOS) { - // TODO(b/68320120): IPV6_RECVTCLASS not supported for netstack. + // TODO(b/144868438): IPV6_RECVTCLASS not supported for netstack. // TODO(b/146661005): Setting TOS via cmsg not supported for netstack. SKIP_IF(IsRunningOnGvisor() && !IsRunningWithHostinet()); ASSERT_THAT(bind(s_, addr_[0], addrlen_), SyscallSucceeds()); -- cgit v1.2.3 From dc9989720562e5df0131986eed3e3d681616db57 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Tue, 21 Jan 2020 14:23:12 -0800 Subject: Add missing verb PiperOrigin-RevId: 290821997 --- pkg/abi/linux/netlink_route.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/abi/linux/netlink_route.go b/pkg/abi/linux/netlink_route.go index 3898d2314..0e3582ab6 100644 --- a/pkg/abi/linux/netlink_route.go +++ b/pkg/abi/linux/netlink_route.go @@ -190,7 +190,7 @@ const ( ARPHRD_LOOPBACK = 772 ) -// RouteMessage struct rtmsg, from uapi/linux/rtnetlink.h. +// RouteMessage is struct rtmsg, from uapi/linux/rtnetlink.h. type RouteMessage struct { Family uint8 DstLen uint8 -- cgit v1.2.3 From ad1968ed5665c7541d6920edbd7c7492b7db3046 Mon Sep 17 00:00:00 2001 From: Rahat Mahmood Date: Tue, 21 Jan 2020 14:25:14 -0800 Subject: Implement sysfs. PiperOrigin-RevId: 290822487 --- pkg/abi/linux/file.go | 13 +++ pkg/sentry/fsimpl/kernfs/BUILD | 3 +- pkg/sentry/fsimpl/kernfs/kernfs_test.go | 175 ++++++------------------------- pkg/sentry/fsimpl/proc/BUILD | 13 +-- pkg/sentry/fsimpl/proc/boot_test.go | 149 -------------------------- pkg/sentry/fsimpl/proc/tasks_test.go | 13 +-- pkg/sentry/fsimpl/sys/BUILD | 35 +++++++ pkg/sentry/fsimpl/sys/sys.go | 124 ++++++++++++++++++++++ pkg/sentry/fsimpl/sys/sys_test.go | 90 ++++++++++++++++ pkg/sentry/fsimpl/testutil/BUILD | 36 +++++++ pkg/sentry/fsimpl/testutil/kernel.go | 149 ++++++++++++++++++++++++++ pkg/sentry/fsimpl/testutil/testutil.go | 178 ++++++++++++++++++++++++++++++++ 12 files changed, 663 insertions(+), 315 deletions(-) delete mode 100644 pkg/sentry/fsimpl/proc/boot_test.go create mode 100644 pkg/sentry/fsimpl/sys/BUILD create mode 100644 pkg/sentry/fsimpl/sys/sys.go create mode 100644 pkg/sentry/fsimpl/sys/sys_test.go create mode 100644 pkg/sentry/fsimpl/testutil/BUILD create mode 100644 pkg/sentry/fsimpl/testutil/kernel.go create mode 100644 pkg/sentry/fsimpl/testutil/testutil.go diff --git a/pkg/abi/linux/file.go b/pkg/abi/linux/file.go index 16791d03e..6fbdd668d 100644 --- a/pkg/abi/linux/file.go +++ b/pkg/abi/linux/file.go @@ -180,6 +180,19 @@ const ( DT_WHT = 14 ) +// DirentType are the friendly strings for linux_dirent64.d_type. +var DirentType = abi.ValueSet{ + DT_UNKNOWN: "DT_UNKNOWN", + DT_FIFO: "DT_FIFO", + DT_CHR: "DT_CHR", + DT_DIR: "DT_DIR", + DT_BLK: "DT_BLK", + DT_REG: "DT_REG", + DT_LNK: "DT_LNK", + DT_SOCK: "DT_SOCK", + DT_WHT: "DT_WHT", +} + // Values for preadv2/pwritev2. const ( // Note: gVisor does not implement the RWF_HIPRI feature, but the flag is diff --git a/pkg/sentry/fsimpl/kernfs/BUILD b/pkg/sentry/fsimpl/kernfs/BUILD index 809178250..66d409785 100644 --- a/pkg/sentry/fsimpl/kernfs/BUILD +++ b/pkg/sentry/fsimpl/kernfs/BUILD @@ -51,13 +51,12 @@ go_test( deps = [ ":kernfs", "//pkg/abi/linux", - "//pkg/fspath", "//pkg/sentry/context", "//pkg/sentry/context/contexttest", + "//pkg/sentry/fsimpl/testutil", "//pkg/sentry/kernel/auth", "//pkg/sentry/usermem", "//pkg/sentry/vfs", - "//pkg/sync", "//pkg/syserror", "@com_github_google_go-cmp//cmp:go_default_library", ], diff --git a/pkg/sentry/fsimpl/kernfs/kernfs_test.go b/pkg/sentry/fsimpl/kernfs/kernfs_test.go index 5c9d580e1..a5fdfbde5 100644 --- a/pkg/sentry/fsimpl/kernfs/kernfs_test.go +++ b/pkg/sentry/fsimpl/kernfs/kernfs_test.go @@ -17,20 +17,17 @@ package kernfs_test import ( "bytes" "fmt" - "io" - "runtime" "testing" "github.com/google/go-cmp/cmp" "gvisor.dev/gvisor/pkg/abi/linux" - "gvisor.dev/gvisor/pkg/fspath" "gvisor.dev/gvisor/pkg/sentry/context" "gvisor.dev/gvisor/pkg/sentry/context/contexttest" "gvisor.dev/gvisor/pkg/sentry/fsimpl/kernfs" + "gvisor.dev/gvisor/pkg/sentry/fsimpl/testutil" "gvisor.dev/gvisor/pkg/sentry/kernel/auth" "gvisor.dev/gvisor/pkg/sentry/usermem" "gvisor.dev/gvisor/pkg/sentry/vfs" - "gvisor.dev/gvisor/pkg/sync" "gvisor.dev/gvisor/pkg/syserror" ) @@ -41,21 +38,11 @@ const staticFileContent = "This is sample content for a static test file." // filesystem. See newTestSystem. type RootDentryFn func(*auth.Credentials, *filesystem) *kernfs.Dentry -// TestSystem represents the context for a single test. -type TestSystem struct { - t *testing.T - ctx context.Context - creds *auth.Credentials - vfs *vfs.VirtualFilesystem - mns *vfs.MountNamespace - root vfs.VirtualDentry -} - // newTestSystem sets up a minimal environment for running a test, including an // instance of a test filesystem. Tests can control the contents of the // filesystem by providing an appropriate rootFn, which should return a // pre-populated root dentry. -func newTestSystem(t *testing.T, rootFn RootDentryFn) *TestSystem { +func newTestSystem(t *testing.T, rootFn RootDentryFn) *testutil.System { ctx := contexttest.Context(t) creds := auth.CredentialsFromContext(ctx) v := vfs.New() @@ -66,57 +53,7 @@ func newTestSystem(t *testing.T, rootFn RootDentryFn) *TestSystem { if err != nil { t.Fatalf("Failed to create testfs root mount: %v", err) } - - s := &TestSystem{ - t: t, - ctx: ctx, - creds: creds, - vfs: v, - mns: mns, - root: mns.Root(), - } - runtime.SetFinalizer(s, func(s *TestSystem) { s.root.DecRef() }) - return s -} - -// PathOpAtRoot constructs a vfs.PathOperation for a path from the -// root of the test filesystem. -// -// Precondition: path should be relative path. -func (s *TestSystem) PathOpAtRoot(path string) vfs.PathOperation { - return vfs.PathOperation{ - Root: s.root, - Start: s.root, - Path: fspath.Parse(path), - } -} - -// GetDentryOrDie attempts to resolve a dentry referred to by the -// provided path operation. If unsuccessful, the test fails. -func (s *TestSystem) GetDentryOrDie(pop vfs.PathOperation) vfs.VirtualDentry { - vd, err := s.vfs.GetDentryAt(s.ctx, s.creds, &pop, &vfs.GetDentryOptions{}) - if err != nil { - s.t.Fatalf("GetDentryAt(pop:%+v) failed: %v", pop, err) - } - return vd -} - -func (s *TestSystem) ReadToEnd(fd *vfs.FileDescription) (string, error) { - buf := make([]byte, usermem.PageSize) - bufIOSeq := usermem.BytesIOSequence(buf) - opts := vfs.ReadOptions{} - - var content bytes.Buffer - for { - n, err := fd.Impl().Read(s.ctx, bufIOSeq, opts) - if n == 0 || err != nil { - if err == io.EOF { - err = nil - } - return content.String(), err - } - content.Write(buf[:n]) - } + return testutil.NewSystem(ctx, t, v, mns) } type fsType struct { @@ -260,6 +197,7 @@ func TestBasic(t *testing.T) { "file1": fs.newFile(creds, staticFileContent), }) }) + defer sys.Destroy() sys.GetDentryOrDie(sys.PathOpAtRoot("file1")).DecRef() } @@ -269,9 +207,10 @@ func TestMkdirGetDentry(t *testing.T) { "dir1": fs.newDir(creds, 0755, nil), }) }) + defer sys.Destroy() pop := sys.PathOpAtRoot("dir1/a new directory") - if err := sys.vfs.MkdirAt(sys.ctx, sys.creds, &pop, &vfs.MkdirOptions{Mode: 0755}); err != nil { + if err := sys.VFS.MkdirAt(sys.Ctx, sys.Creds, &pop, &vfs.MkdirOptions{Mode: 0755}); err != nil { t.Fatalf("MkdirAt for PathOperation %+v failed: %v", pop, err) } sys.GetDentryOrDie(pop).DecRef() @@ -283,20 +222,21 @@ func TestReadStaticFile(t *testing.T) { "file1": fs.newFile(creds, staticFileContent), }) }) + defer sys.Destroy() pop := sys.PathOpAtRoot("file1") - fd, err := sys.vfs.OpenAt(sys.ctx, sys.creds, &pop, &vfs.OpenOptions{}) + fd, err := sys.VFS.OpenAt(sys.Ctx, sys.Creds, &pop, &vfs.OpenOptions{}) if err != nil { - sys.t.Fatalf("OpenAt for PathOperation %+v failed: %v", pop, err) + t.Fatalf("OpenAt for PathOperation %+v failed: %v", pop, err) } defer fd.DecRef() content, err := sys.ReadToEnd(fd) if err != nil { - sys.t.Fatalf("Read failed: %v", err) + t.Fatalf("Read failed: %v", err) } if diff := cmp.Diff(staticFileContent, content); diff != "" { - sys.t.Fatalf("Read returned unexpected data:\n--- want\n+++ got\n%v", diff) + t.Fatalf("Read returned unexpected data:\n--- want\n+++ got\n%v", diff) } } @@ -306,83 +246,44 @@ func TestCreateNewFileInStaticDir(t *testing.T) { "dir1": fs.newDir(creds, 0755, nil), }) }) + defer sys.Destroy() pop := sys.PathOpAtRoot("dir1/newfile") opts := &vfs.OpenOptions{Flags: linux.O_CREAT | linux.O_EXCL, Mode: defaultMode} - fd, err := sys.vfs.OpenAt(sys.ctx, sys.creds, &pop, opts) + fd, err := sys.VFS.OpenAt(sys.Ctx, sys.Creds, &pop, opts) if err != nil { - sys.t.Fatalf("OpenAt(pop:%+v, opts:%+v) failed: %v", pop, opts, err) + t.Fatalf("OpenAt(pop:%+v, opts:%+v) failed: %v", pop, opts, err) } // Close the file. The file should persist. fd.DecRef() - fd, err = sys.vfs.OpenAt(sys.ctx, sys.creds, &pop, &vfs.OpenOptions{}) + fd, err = sys.VFS.OpenAt(sys.Ctx, sys.Creds, &pop, &vfs.OpenOptions{}) if err != nil { - sys.t.Fatalf("OpenAt(pop:%+v) = %+v failed: %v", pop, fd, err) + t.Fatalf("OpenAt(pop:%+v) = %+v failed: %v", pop, fd, err) } fd.DecRef() } -// direntCollector provides an implementation for vfs.IterDirentsCallback for -// testing. It simply iterates to the end of a given directory FD and collects -// all dirents emitted by the callback. -type direntCollector struct { - mu sync.Mutex - dirents map[string]vfs.Dirent -} - -// Handle implements vfs.IterDirentsCallback.Handle. -func (d *direntCollector) Handle(dirent vfs.Dirent) bool { - d.mu.Lock() - if d.dirents == nil { - d.dirents = make(map[string]vfs.Dirent) - } - d.dirents[dirent.Name] = dirent - d.mu.Unlock() - return true -} - -// count returns the number of dirents currently in the collector. -func (d *direntCollector) count() int { - d.mu.Lock() - defer d.mu.Unlock() - return len(d.dirents) -} - -// contains checks whether the collector has a dirent with the given name and -// type. -func (d *direntCollector) contains(name string, typ uint8) error { - d.mu.Lock() - defer d.mu.Unlock() - dirent, ok := d.dirents[name] - if !ok { - return fmt.Errorf("No dirent named %q found", name) - } - if dirent.Type != typ { - return fmt.Errorf("Dirent named %q found, but was expecting type %d, got: %+v", name, typ, dirent) - } - return nil -} - func TestDirFDReadWrite(t *testing.T) { sys := newTestSystem(t, func(creds *auth.Credentials, fs *filesystem) *kernfs.Dentry { return fs.newReadonlyDir(creds, 0755, nil) }) + defer sys.Destroy() pop := sys.PathOpAtRoot("/") - fd, err := sys.vfs.OpenAt(sys.ctx, sys.creds, &pop, &vfs.OpenOptions{}) + fd, err := sys.VFS.OpenAt(sys.Ctx, sys.Creds, &pop, &vfs.OpenOptions{}) if err != nil { - sys.t.Fatalf("OpenAt for PathOperation %+v failed: %v", pop, err) + t.Fatalf("OpenAt for PathOperation %+v failed: %v", pop, err) } defer fd.DecRef() // Read/Write should fail for directory FDs. - if _, err := fd.Read(sys.ctx, usermem.BytesIOSequence([]byte{}), vfs.ReadOptions{}); err != syserror.EISDIR { - sys.t.Fatalf("Read for directory FD failed with unexpected error: %v", err) + if _, err := fd.Read(sys.Ctx, usermem.BytesIOSequence([]byte{}), vfs.ReadOptions{}); err != syserror.EISDIR { + t.Fatalf("Read for directory FD failed with unexpected error: %v", err) } - if _, err := fd.Write(sys.ctx, usermem.BytesIOSequence([]byte{}), vfs.WriteOptions{}); err != syserror.EISDIR { - sys.t.Fatalf("Wrire for directory FD failed with unexpected error: %v", err) + if _, err := fd.Write(sys.Ctx, usermem.BytesIOSequence([]byte{}), vfs.WriteOptions{}); err != syserror.EISDIR { + t.Fatalf("Write for directory FD failed with unexpected error: %v", err) } } @@ -397,30 +298,12 @@ func TestDirFDIterDirents(t *testing.T) { "file1": fs.newFile(creds, staticFileContent), }) }) + defer sys.Destroy() pop := sys.PathOpAtRoot("/") - fd, err := sys.vfs.OpenAt(sys.ctx, sys.creds, &pop, &vfs.OpenOptions{}) - if err != nil { - sys.t.Fatalf("OpenAt for PathOperation %+v failed: %v", pop, err) - } - defer fd.DecRef() - - collector := &direntCollector{} - if err := fd.IterDirents(sys.ctx, collector); err != nil { - sys.t.Fatalf("IterDirent failed: %v", err) - } - - // Root directory should contain ".", ".." and 3 children: - if collector.count() != 5 { - sys.t.Fatalf("IterDirent returned too many dirents") - } - for _, dirName := range []string{".", "..", "dir1", "dir2"} { - if err := collector.contains(dirName, linux.DT_DIR); err != nil { - sys.t.Fatalf("IterDirent had unexpected results: %v", err) - } - } - if err := collector.contains("file1", linux.DT_REG); err != nil { - sys.t.Fatalf("IterDirent had unexpected results: %v", err) - } - + sys.AssertDirectoryContains(&pop, map[string]testutil.DirentType{ + "dir1": linux.DT_DIR, + "dir2": linux.DT_DIR, + "file1": linux.DT_REG, + }) } diff --git a/pkg/sentry/fsimpl/proc/BUILD b/pkg/sentry/fsimpl/proc/BUILD index f69aa19c4..c5b79fb38 100644 --- a/pkg/sentry/fsimpl/proc/BUILD +++ b/pkg/sentry/fsimpl/proc/BUILD @@ -44,30 +44,19 @@ go_test( name = "proc_test", size = "small", srcs = [ - "boot_test.go", "tasks_sys_test.go", "tasks_test.go", ], embed = [":proc"], deps = [ "//pkg/abi/linux", - "//pkg/cpuid", "//pkg/fspath", - "//pkg/memutil", "//pkg/sentry/context", "//pkg/sentry/context/contexttest", - "//pkg/sentry/fs", + "//pkg/sentry/fsimpl/testutil", "//pkg/sentry/inet", "//pkg/sentry/kernel", "//pkg/sentry/kernel/auth", - "//pkg/sentry/kernel/sched", - "//pkg/sentry/limits", - "//pkg/sentry/loader", - "//pkg/sentry/pgalloc", - "//pkg/sentry/platform", - "//pkg/sentry/platform/kvm", - "//pkg/sentry/platform/ptrace", - "//pkg/sentry/time", "//pkg/sentry/usermem", "//pkg/sentry/vfs", "//pkg/syserror", diff --git a/pkg/sentry/fsimpl/proc/boot_test.go b/pkg/sentry/fsimpl/proc/boot_test.go deleted file mode 100644 index 84a93ee56..000000000 --- a/pkg/sentry/fsimpl/proc/boot_test.go +++ /dev/null @@ -1,149 +0,0 @@ -// Copyright 2019 The gVisor Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package proc - -import ( - "flag" - "fmt" - "os" - "runtime" - - "gvisor.dev/gvisor/pkg/abi/linux" - "gvisor.dev/gvisor/pkg/cpuid" - "gvisor.dev/gvisor/pkg/memutil" - "gvisor.dev/gvisor/pkg/sentry/context" - "gvisor.dev/gvisor/pkg/sentry/fs" - "gvisor.dev/gvisor/pkg/sentry/kernel" - "gvisor.dev/gvisor/pkg/sentry/kernel/auth" - "gvisor.dev/gvisor/pkg/sentry/kernel/sched" - "gvisor.dev/gvisor/pkg/sentry/limits" - "gvisor.dev/gvisor/pkg/sentry/loader" - "gvisor.dev/gvisor/pkg/sentry/pgalloc" - "gvisor.dev/gvisor/pkg/sentry/platform" - "gvisor.dev/gvisor/pkg/sentry/time" - - // Platforms are plugable. - _ "gvisor.dev/gvisor/pkg/sentry/platform/kvm" - _ "gvisor.dev/gvisor/pkg/sentry/platform/ptrace" -) - -var ( - platformFlag = flag.String("platform", "ptrace", "specify which platform to use") -) - -// boot initializes a new bare bones kernel for test. -func boot() (*kernel.Kernel, error) { - platformCtr, err := platform.Lookup(*platformFlag) - if err != nil { - return nil, fmt.Errorf("platform not found: %v", err) - } - deviceFile, err := platformCtr.OpenDevice() - if err != nil { - return nil, fmt.Errorf("creating platform: %v", err) - } - plat, err := platformCtr.New(deviceFile) - if err != nil { - return nil, fmt.Errorf("creating platform: %v", err) - } - - k := &kernel.Kernel{ - Platform: plat, - } - - mf, err := createMemoryFile() - if err != nil { - return nil, err - } - k.SetMemoryFile(mf) - - // Pass k as the platform since it is savable, unlike the actual platform. - vdso, err := loader.PrepareVDSO(nil, k) - if err != nil { - return nil, fmt.Errorf("creating vdso: %v", err) - } - - // Create timekeeper. - tk, err := kernel.NewTimekeeper(k, vdso.ParamPage.FileRange()) - if err != nil { - return nil, fmt.Errorf("creating timekeeper: %v", err) - } - tk.SetClocks(time.NewCalibratedClocks()) - - creds := auth.NewRootCredentials(auth.NewRootUserNamespace()) - - // Initiate the Kernel object, which is required by the Context passed - // to createVFS in order to mount (among other things) procfs. - if err = k.Init(kernel.InitKernelArgs{ - ApplicationCores: uint(runtime.GOMAXPROCS(-1)), - FeatureSet: cpuid.HostFeatureSet(), - Timekeeper: tk, - RootUserNamespace: creds.UserNamespace, - Vdso: vdso, - RootUTSNamespace: kernel.NewUTSNamespace("hostname", "domain", creds.UserNamespace), - RootIPCNamespace: kernel.NewIPCNamespace(creds.UserNamespace), - RootAbstractSocketNamespace: kernel.NewAbstractSocketNamespace(), - PIDNamespace: kernel.NewRootPIDNamespace(creds.UserNamespace), - }); err != nil { - return nil, fmt.Errorf("initializing kernel: %v", err) - } - - ctx := k.SupervisorContext() - - // Create mount namespace without root as it's the minimum required to create - // the global thread group. - mntns, err := fs.NewMountNamespace(ctx, nil) - if err != nil { - return nil, err - } - ls, err := limits.NewLinuxLimitSet() - if err != nil { - return nil, err - } - tg := k.NewThreadGroup(mntns, k.RootPIDNamespace(), kernel.NewSignalHandlers(), linux.SIGCHLD, ls) - k.TestOnly_SetGlobalInit(tg) - - return k, nil -} - -// createTask creates a new bare bones task for tests. -func createTask(ctx context.Context, name string, tc *kernel.ThreadGroup) (*kernel.Task, error) { - k := kernel.KernelFromContext(ctx) - config := &kernel.TaskConfig{ - Kernel: k, - ThreadGroup: tc, - TaskContext: &kernel.TaskContext{Name: name}, - Credentials: auth.CredentialsFromContext(ctx), - AllowedCPUMask: sched.NewFullCPUSet(k.ApplicationCores()), - UTSNamespace: kernel.UTSNamespaceFromContext(ctx), - IPCNamespace: kernel.IPCNamespaceFromContext(ctx), - AbstractSocketNamespace: kernel.NewAbstractSocketNamespace(), - } - return k.TaskSet().NewTask(config) -} - -func createMemoryFile() (*pgalloc.MemoryFile, error) { - const memfileName = "test-memory" - memfd, err := memutil.CreateMemFD(memfileName, 0) - if err != nil { - return nil, fmt.Errorf("error creating memfd: %v", err) - } - memfile := os.NewFile(uintptr(memfd), memfileName) - mf, err := pgalloc.NewMemoryFile(memfile, pgalloc.MemoryFileOpts{}) - if err != nil { - memfile.Close() - return nil, fmt.Errorf("error creating pgalloc.MemoryFile: %v", err) - } - return mf, nil -} diff --git a/pkg/sentry/fsimpl/proc/tasks_test.go b/pkg/sentry/fsimpl/proc/tasks_test.go index 002d2f73b..41977d816 100644 --- a/pkg/sentry/fsimpl/proc/tasks_test.go +++ b/pkg/sentry/fsimpl/proc/tasks_test.go @@ -24,6 +24,7 @@ import ( "gvisor.dev/gvisor/pkg/abi/linux" "gvisor.dev/gvisor/pkg/fspath" "gvisor.dev/gvisor/pkg/sentry/context" + "gvisor.dev/gvisor/pkg/sentry/fsimpl/testutil" "gvisor.dev/gvisor/pkg/sentry/kernel" "gvisor.dev/gvisor/pkg/sentry/kernel/auth" "gvisor.dev/gvisor/pkg/sentry/usermem" @@ -134,7 +135,7 @@ func checkFiles(gots []vfs.Dirent, wants map[string]vfs.Dirent) ([]vfs.Dirent, e } func setup() (context.Context, *vfs.VirtualFilesystem, vfs.VirtualDentry, error) { - k, err := boot() + k, err := testutil.Boot() if err != nil { return nil, nil, vfs.VirtualDentry{}, fmt.Errorf("creating kernel: %v", err) } @@ -206,7 +207,7 @@ func TestTasks(t *testing.T) { var tasks []*kernel.Task for i := 0; i < 5; i++ { tc := k.NewThreadGroup(nil, k.RootPIDNamespace(), kernel.NewSignalHandlers(), linux.SIGCHLD, k.GlobalInit().Limits()) - task, err := createTask(ctx, fmt.Sprintf("name-%d", i), tc) + task, err := testutil.CreateTask(ctx, fmt.Sprintf("name-%d", i), tc) if err != nil { t.Fatalf("CreateTask(): %v", err) } @@ -298,7 +299,7 @@ func TestTasksOffset(t *testing.T) { k := kernel.KernelFromContext(ctx) for i := 0; i < 3; i++ { tc := k.NewThreadGroup(nil, k.RootPIDNamespace(), kernel.NewSignalHandlers(), linux.SIGCHLD, k.GlobalInit().Limits()) - if _, err := createTask(ctx, fmt.Sprintf("name-%d", i), tc); err != nil { + if _, err := testutil.CreateTask(ctx, fmt.Sprintf("name-%d", i), tc); err != nil { t.Fatalf("CreateTask(): %v", err) } } @@ -417,7 +418,7 @@ func TestTask(t *testing.T) { k := kernel.KernelFromContext(ctx) tc := k.NewThreadGroup(nil, k.RootPIDNamespace(), kernel.NewSignalHandlers(), linux.SIGCHLD, k.GlobalInit().Limits()) - _, err = createTask(ctx, "name", tc) + _, err = testutil.CreateTask(ctx, "name", tc) if err != nil { t.Fatalf("CreateTask(): %v", err) } @@ -458,7 +459,7 @@ func TestProcSelf(t *testing.T) { k := kernel.KernelFromContext(ctx) tc := k.NewThreadGroup(nil, k.RootPIDNamespace(), kernel.NewSignalHandlers(), linux.SIGCHLD, k.GlobalInit().Limits()) - task, err := createTask(ctx, "name", tc) + task, err := testutil.CreateTask(ctx, "name", tc) if err != nil { t.Fatalf("CreateTask(): %v", err) } @@ -555,7 +556,7 @@ func TestTree(t *testing.T) { var tasks []*kernel.Task for i := 0; i < 5; i++ { tc := k.NewThreadGroup(nil, k.RootPIDNamespace(), kernel.NewSignalHandlers(), linux.SIGCHLD, k.GlobalInit().Limits()) - task, err := createTask(uberCtx, fmt.Sprintf("name-%d", i), tc) + task, err := testutil.CreateTask(uberCtx, fmt.Sprintf("name-%d", i), tc) if err != nil { t.Fatalf("CreateTask(): %v", err) } diff --git a/pkg/sentry/fsimpl/sys/BUILD b/pkg/sentry/fsimpl/sys/BUILD new file mode 100644 index 000000000..ee3c842bd --- /dev/null +++ b/pkg/sentry/fsimpl/sys/BUILD @@ -0,0 +1,35 @@ +load("//tools/go_stateify:defs.bzl", "go_library") +load("@io_bazel_rules_go//go:def.bzl", "go_test") + +package(licenses = ["notice"]) + +go_library( + name = "sys", + srcs = [ + "sys.go", + ], + importpath = "gvisor.dev/gvisor/pkg/sentry/fsimpl/sys", + deps = [ + "//pkg/abi/linux", + "//pkg/sentry/context", + "//pkg/sentry/fsimpl/kernfs", + "//pkg/sentry/kernel", + "//pkg/sentry/kernel/auth", + "//pkg/sentry/vfs", + "//pkg/syserror", + ], +) + +go_test( + name = "sys_test", + srcs = ["sys_test.go"], + deps = [ + ":sys", + "//pkg/abi/linux", + "//pkg/sentry/fsimpl/testutil", + "//pkg/sentry/kernel", + "//pkg/sentry/kernel/auth", + "//pkg/sentry/vfs", + "@com_github_google_go-cmp//cmp:go_default_library", + ], +) diff --git a/pkg/sentry/fsimpl/sys/sys.go b/pkg/sentry/fsimpl/sys/sys.go new file mode 100644 index 000000000..1305ad01d --- /dev/null +++ b/pkg/sentry/fsimpl/sys/sys.go @@ -0,0 +1,124 @@ +// Copyright 2019 The gVisor Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package sys implements sysfs. +package sys + +import ( + "bytes" + "fmt" + + "gvisor.dev/gvisor/pkg/abi/linux" + "gvisor.dev/gvisor/pkg/sentry/context" + "gvisor.dev/gvisor/pkg/sentry/fsimpl/kernfs" + "gvisor.dev/gvisor/pkg/sentry/kernel" + "gvisor.dev/gvisor/pkg/sentry/kernel/auth" + "gvisor.dev/gvisor/pkg/sentry/vfs" + "gvisor.dev/gvisor/pkg/syserror" +) + +// FilesystemType implements vfs.FilesystemType. +type FilesystemType struct{} + +// filesystem implements vfs.FilesystemImpl. +type filesystem struct { + kernfs.Filesystem +} + +// GetFilesystem implements vfs.FilesystemType.GetFilesystem. +func (FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.VirtualFilesystem, creds *auth.Credentials, source string, opts vfs.GetFilesystemOptions) (*vfs.Filesystem, *vfs.Dentry, error) { + fs := &filesystem{} + fs.Filesystem.Init(vfsObj) + k := kernel.KernelFromContext(ctx) + maxCPUCores := k.ApplicationCores() + defaultSysDirMode := linux.FileMode(0755) + + root := fs.newDir(creds, defaultSysDirMode, map[string]*kernfs.Dentry{ + "block": fs.newDir(creds, defaultSysDirMode, nil), + "bus": fs.newDir(creds, defaultSysDirMode, nil), + "class": fs.newDir(creds, defaultSysDirMode, map[string]*kernfs.Dentry{ + "power_supply": fs.newDir(creds, defaultSysDirMode, nil), + }), + "dev": fs.newDir(creds, defaultSysDirMode, nil), + "devices": fs.newDir(creds, defaultSysDirMode, map[string]*kernfs.Dentry{ + "system": fs.newDir(creds, defaultSysDirMode, map[string]*kernfs.Dentry{ + "cpu": fs.newDir(creds, defaultSysDirMode, map[string]*kernfs.Dentry{ + "online": fs.newCPUFile(creds, maxCPUCores, linux.FileMode(0444)), + "possible": fs.newCPUFile(creds, maxCPUCores, linux.FileMode(0444)), + "present": fs.newCPUFile(creds, maxCPUCores, linux.FileMode(0444)), + }), + }), + }), + "firmware": fs.newDir(creds, defaultSysDirMode, nil), + "fs": fs.newDir(creds, defaultSysDirMode, nil), + "kernel": fs.newDir(creds, defaultSysDirMode, nil), + "module": fs.newDir(creds, defaultSysDirMode, nil), + "power": fs.newDir(creds, defaultSysDirMode, nil), + }) + return fs.VFSFilesystem(), root.VFSDentry(), nil +} + +// dir implements kernfs.Inode. +type dir struct { + kernfs.InodeAttrs + kernfs.InodeNoDynamicLookup + kernfs.InodeNotSymlink + kernfs.InodeDirectoryNoNewChildren + + kernfs.OrderedChildren + dentry kernfs.Dentry +} + +func (fs *filesystem) newDir(creds *auth.Credentials, mode linux.FileMode, contents map[string]*kernfs.Dentry) *kernfs.Dentry { + d := &dir{} + d.InodeAttrs.Init(creds, fs.NextIno(), linux.ModeDirectory|0755) + d.OrderedChildren.Init(kernfs.OrderedChildrenOptions{}) + d.dentry.Init(d) + + d.IncLinks(d.OrderedChildren.Populate(&d.dentry, contents)) + + return &d.dentry +} + +// SetStat implements kernfs.Inode.SetStat. +func (d *dir) SetStat(fs *vfs.Filesystem, opts vfs.SetStatOptions) error { + return syserror.EPERM +} + +// Open implements kernfs.Inode.Open. +func (d *dir) Open(rp *vfs.ResolvingPath, vfsd *vfs.Dentry, flags uint32) (*vfs.FileDescription, error) { + fd := &kernfs.GenericDirectoryFD{} + fd.Init(rp.Mount(), vfsd, &d.OrderedChildren, flags) + return fd.VFSFileDescription(), nil +} + +// cpuFile implements kernfs.Inode. +type cpuFile struct { + kernfs.DynamicBytesFile + maxCores uint +} + +// Generate implements vfs.DynamicBytesSource.Generate. +func (c *cpuFile) Generate(ctx context.Context, buf *bytes.Buffer) error { + fmt.Fprintf(buf, "0-%d", c.maxCores-1) + return nil +} + +func (fs *filesystem) newCPUFile(creds *auth.Credentials, maxCores uint, mode linux.FileMode) *kernfs.Dentry { + c := &cpuFile{maxCores: maxCores} + c.DynamicBytesFile.Init(creds, fs.NextIno(), c, mode) + d := &kernfs.Dentry{} + d.Init(c) + return d +} diff --git a/pkg/sentry/fsimpl/sys/sys_test.go b/pkg/sentry/fsimpl/sys/sys_test.go new file mode 100644 index 000000000..60a1634a9 --- /dev/null +++ b/pkg/sentry/fsimpl/sys/sys_test.go @@ -0,0 +1,90 @@ +// Copyright 2019 The gVisor Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package sys_test + +import ( + "fmt" + "testing" + + "github.com/google/go-cmp/cmp" + "gvisor.dev/gvisor/pkg/abi/linux" + "gvisor.dev/gvisor/pkg/sentry/fsimpl/sys" + "gvisor.dev/gvisor/pkg/sentry/fsimpl/testutil" + "gvisor.dev/gvisor/pkg/sentry/kernel" + "gvisor.dev/gvisor/pkg/sentry/kernel/auth" + "gvisor.dev/gvisor/pkg/sentry/vfs" +) + +func newTestSystem(t *testing.T) *testutil.System { + k, err := testutil.Boot() + if err != nil { + t.Fatalf("Failed to create test kernel: %v", err) + } + ctx := k.SupervisorContext() + creds := auth.CredentialsFromContext(ctx) + v := vfs.New() + v.MustRegisterFilesystemType("sysfs", sys.FilesystemType{}, &vfs.RegisterFilesystemTypeOptions{ + AllowUserMount: true, + }) + + mns, err := v.NewMountNamespace(ctx, creds, "", "sysfs", &vfs.GetFilesystemOptions{}) + if err != nil { + t.Fatalf("Failed to create new mount namespace: %v", err) + } + return testutil.NewSystem(ctx, t, v, mns) +} + +func TestReadCPUFile(t *testing.T) { + s := newTestSystem(t) + defer s.Destroy() + k := kernel.KernelFromContext(s.Ctx) + maxCPUCores := k.ApplicationCores() + + expected := fmt.Sprintf("0-%d", maxCPUCores-1) + + for _, fname := range []string{"online", "possible", "present"} { + pop := s.PathOpAtRoot(fmt.Sprintf("devices/system/cpu/%s", fname)) + fd, err := s.VFS.OpenAt(s.Ctx, s.Creds, &pop, &vfs.OpenOptions{}) + if err != nil { + t.Fatalf("OpenAt(pop:%+v) = %+v failed: %v", pop, fd, err) + } + defer fd.DecRef() + content, err := s.ReadToEnd(fd) + if err != nil { + t.Fatalf("Read failed: %v", err) + } + if diff := cmp.Diff(expected, content); diff != "" { + t.Fatalf("Read returned unexpected data:\n--- want\n+++ got\n%v", diff) + } + } +} + +func TestSysRootContainsExpectedEntries(t *testing.T) { + s := newTestSystem(t) + defer s.Destroy() + pop := s.PathOpAtRoot("/") + s.AssertDirectoryContains(&pop, map[string]testutil.DirentType{ + "block": linux.DT_DIR, + "bus": linux.DT_DIR, + "class": linux.DT_DIR, + "dev": linux.DT_DIR, + "devices": linux.DT_DIR, + "firmware": linux.DT_DIR, + "fs": linux.DT_DIR, + "kernel": linux.DT_DIR, + "module": linux.DT_DIR, + "power": linux.DT_DIR, + }) +} diff --git a/pkg/sentry/fsimpl/testutil/BUILD b/pkg/sentry/fsimpl/testutil/BUILD new file mode 100644 index 000000000..4e70d84a7 --- /dev/null +++ b/pkg/sentry/fsimpl/testutil/BUILD @@ -0,0 +1,36 @@ +load("//tools/go_stateify:defs.bzl", "go_library") + +package(licenses = ["notice"]) + +go_library( + name = "testutil", + testonly = 1, + srcs = [ + "kernel.go", + "testutil.go", + ], + importpath = "gvisor.dev/gvisor/pkg/sentry/fsimpl/testutil", + visibility = ["//pkg/sentry:internal"], + deps = [ + "//pkg/abi/linux", + "//pkg/cpuid", + "//pkg/fspath", + "//pkg/memutil", + "//pkg/sentry/context", + "//pkg/sentry/fs", + "//pkg/sentry/kernel", + "//pkg/sentry/kernel/auth", + "//pkg/sentry/kernel/sched", + "//pkg/sentry/limits", + "//pkg/sentry/loader", + "//pkg/sentry/pgalloc", + "//pkg/sentry/platform", + "//pkg/sentry/platform/kvm", + "//pkg/sentry/platform/ptrace", + "//pkg/sentry/time", + "//pkg/sentry/usermem", + "//pkg/sentry/vfs", + "//pkg/sync", + "@com_github_google_go-cmp//cmp:go_default_library", + ], +) diff --git a/pkg/sentry/fsimpl/testutil/kernel.go b/pkg/sentry/fsimpl/testutil/kernel.go new file mode 100644 index 000000000..295da2d52 --- /dev/null +++ b/pkg/sentry/fsimpl/testutil/kernel.go @@ -0,0 +1,149 @@ +// Copyright 2019 The gVisor Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package testutil + +import ( + "flag" + "fmt" + "os" + "runtime" + + "gvisor.dev/gvisor/pkg/abi/linux" + "gvisor.dev/gvisor/pkg/cpuid" + "gvisor.dev/gvisor/pkg/memutil" + "gvisor.dev/gvisor/pkg/sentry/context" + "gvisor.dev/gvisor/pkg/sentry/fs" + "gvisor.dev/gvisor/pkg/sentry/kernel" + "gvisor.dev/gvisor/pkg/sentry/kernel/auth" + "gvisor.dev/gvisor/pkg/sentry/kernel/sched" + "gvisor.dev/gvisor/pkg/sentry/limits" + "gvisor.dev/gvisor/pkg/sentry/loader" + "gvisor.dev/gvisor/pkg/sentry/pgalloc" + "gvisor.dev/gvisor/pkg/sentry/platform" + "gvisor.dev/gvisor/pkg/sentry/time" + + // Platforms are plugable. + _ "gvisor.dev/gvisor/pkg/sentry/platform/kvm" + _ "gvisor.dev/gvisor/pkg/sentry/platform/ptrace" +) + +var ( + platformFlag = flag.String("platform", "ptrace", "specify which platform to use") +) + +// Boot initializes a new bare bones kernel for test. +func Boot() (*kernel.Kernel, error) { + platformCtr, err := platform.Lookup(*platformFlag) + if err != nil { + return nil, fmt.Errorf("platform not found: %v", err) + } + deviceFile, err := platformCtr.OpenDevice() + if err != nil { + return nil, fmt.Errorf("creating platform: %v", err) + } + plat, err := platformCtr.New(deviceFile) + if err != nil { + return nil, fmt.Errorf("creating platform: %v", err) + } + + k := &kernel.Kernel{ + Platform: plat, + } + + mf, err := createMemoryFile() + if err != nil { + return nil, err + } + k.SetMemoryFile(mf) + + // Pass k as the platform since it is savable, unlike the actual platform. + vdso, err := loader.PrepareVDSO(nil, k) + if err != nil { + return nil, fmt.Errorf("creating vdso: %v", err) + } + + // Create timekeeper. + tk, err := kernel.NewTimekeeper(k, vdso.ParamPage.FileRange()) + if err != nil { + return nil, fmt.Errorf("creating timekeeper: %v", err) + } + tk.SetClocks(time.NewCalibratedClocks()) + + creds := auth.NewRootCredentials(auth.NewRootUserNamespace()) + + // Initiate the Kernel object, which is required by the Context passed + // to createVFS in order to mount (among other things) procfs. + if err = k.Init(kernel.InitKernelArgs{ + ApplicationCores: uint(runtime.GOMAXPROCS(-1)), + FeatureSet: cpuid.HostFeatureSet(), + Timekeeper: tk, + RootUserNamespace: creds.UserNamespace, + Vdso: vdso, + RootUTSNamespace: kernel.NewUTSNamespace("hostname", "domain", creds.UserNamespace), + RootIPCNamespace: kernel.NewIPCNamespace(creds.UserNamespace), + RootAbstractSocketNamespace: kernel.NewAbstractSocketNamespace(), + PIDNamespace: kernel.NewRootPIDNamespace(creds.UserNamespace), + }); err != nil { + return nil, fmt.Errorf("initializing kernel: %v", err) + } + + ctx := k.SupervisorContext() + + // Create mount namespace without root as it's the minimum required to create + // the global thread group. + mntns, err := fs.NewMountNamespace(ctx, nil) + if err != nil { + return nil, err + } + ls, err := limits.NewLinuxLimitSet() + if err != nil { + return nil, err + } + tg := k.NewThreadGroup(mntns, k.RootPIDNamespace(), kernel.NewSignalHandlers(), linux.SIGCHLD, ls) + k.TestOnly_SetGlobalInit(tg) + + return k, nil +} + +// CreateTask creates a new bare bones task for tests. +func CreateTask(ctx context.Context, name string, tc *kernel.ThreadGroup) (*kernel.Task, error) { + k := kernel.KernelFromContext(ctx) + config := &kernel.TaskConfig{ + Kernel: k, + ThreadGroup: tc, + TaskContext: &kernel.TaskContext{Name: name}, + Credentials: auth.CredentialsFromContext(ctx), + AllowedCPUMask: sched.NewFullCPUSet(k.ApplicationCores()), + UTSNamespace: kernel.UTSNamespaceFromContext(ctx), + IPCNamespace: kernel.IPCNamespaceFromContext(ctx), + AbstractSocketNamespace: kernel.NewAbstractSocketNamespace(), + } + return k.TaskSet().NewTask(config) +} + +func createMemoryFile() (*pgalloc.MemoryFile, error) { + const memfileName = "test-memory" + memfd, err := memutil.CreateMemFD(memfileName, 0) + if err != nil { + return nil, fmt.Errorf("error creating memfd: %v", err) + } + memfile := os.NewFile(uintptr(memfd), memfileName) + mf, err := pgalloc.NewMemoryFile(memfile, pgalloc.MemoryFileOpts{}) + if err != nil { + memfile.Close() + return nil, fmt.Errorf("error creating pgalloc.MemoryFile: %v", err) + } + return mf, nil +} diff --git a/pkg/sentry/fsimpl/testutil/testutil.go b/pkg/sentry/fsimpl/testutil/testutil.go new file mode 100644 index 000000000..eada31d94 --- /dev/null +++ b/pkg/sentry/fsimpl/testutil/testutil.go @@ -0,0 +1,178 @@ +// Copyright 2019 The gVisor Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package testutil provides common test utilities for kernfs-based +// filesystems. +package testutil + +import ( + "fmt" + "io" + "strings" + "testing" + + "github.com/google/go-cmp/cmp" + "gvisor.dev/gvisor/pkg/abi/linux" + "gvisor.dev/gvisor/pkg/fspath" + "gvisor.dev/gvisor/pkg/sentry/context" + "gvisor.dev/gvisor/pkg/sentry/kernel/auth" + "gvisor.dev/gvisor/pkg/sentry/usermem" + "gvisor.dev/gvisor/pkg/sentry/vfs" + "gvisor.dev/gvisor/pkg/sync" +) + +// System represents the context for a single test. +// +// Test systems must be explicitly destroyed with System.Destroy. +type System struct { + t *testing.T + Ctx context.Context + Creds *auth.Credentials + VFS *vfs.VirtualFilesystem + mns *vfs.MountNamespace + root vfs.VirtualDentry +} + +// NewSystem constructs a System. +// +// Precondition: Caller must hold a reference on mns, whose ownership +// is transferred to the new System. +func NewSystem(ctx context.Context, t *testing.T, v *vfs.VirtualFilesystem, mns *vfs.MountNamespace) *System { + s := &System{ + t: t, + Ctx: ctx, + Creds: auth.CredentialsFromContext(ctx), + VFS: v, + mns: mns, + root: mns.Root(), + } + return s +} + +// Destroy release resources associated with a test system. +func (s *System) Destroy() { + s.root.DecRef() + s.mns.DecRef(s.VFS) // Reference on mns passed to NewSystem. +} + +// ReadToEnd reads the contents of fd until EOF to a string. +func (s *System) ReadToEnd(fd *vfs.FileDescription) (string, error) { + buf := make([]byte, usermem.PageSize) + bufIOSeq := usermem.BytesIOSequence(buf) + opts := vfs.ReadOptions{} + + var content strings.Builder + for { + n, err := fd.Read(s.Ctx, bufIOSeq, opts) + if n == 0 || err != nil { + if err == io.EOF { + err = nil + } + return content.String(), err + } + content.Write(buf[:n]) + } +} + +// PathOpAtRoot constructs a PathOperation with the given path from +// the root of the filesystem. +func (s *System) PathOpAtRoot(path string) vfs.PathOperation { + return vfs.PathOperation{ + Root: s.root, + Start: s.root, + Path: fspath.Parse(path), + } +} + +// GetDentryOrDie attempts to resolve a dentry referred to by the +// provided path operation. If unsuccessful, the test fails. +func (s *System) GetDentryOrDie(pop vfs.PathOperation) vfs.VirtualDentry { + vd, err := s.VFS.GetDentryAt(s.Ctx, s.Creds, &pop, &vfs.GetDentryOptions{}) + if err != nil { + s.t.Fatalf("GetDentryAt(pop:%+v) failed: %v", pop, err) + } + return vd +} + +// DirentType is an alias for values for linux_dirent64.d_type. +type DirentType = uint8 + +// AssertDirectoryContains verifies that a directory at pop contains the entries +// specified. AssertDirectoryContains implicitly checks for "." and "..", these +// need not be included in entries. +func (s *System) AssertDirectoryContains(pop *vfs.PathOperation, entries map[string]DirentType) { + // Also implicitly check for "." and "..". + entries["."] = linux.DT_DIR + entries[".."] = linux.DT_DIR + + fd, err := s.VFS.OpenAt(s.Ctx, s.Creds, pop, &vfs.OpenOptions{Flags: linux.O_RDONLY}) + if err != nil { + s.t.Fatalf("OpenAt for PathOperation %+v failed: %v", pop, err) + } + defer fd.DecRef() + + collector := &DirentCollector{} + if err := fd.IterDirents(s.Ctx, collector); err != nil { + s.t.Fatalf("IterDirent failed: %v", err) + } + + collectedEntries := make(map[string]DirentType) + for _, dirent := range collector.dirents { + collectedEntries[dirent.Name] = dirent.Type + } + if diff := cmp.Diff(entries, collectedEntries); diff != "" { + s.t.Fatalf("IterDirent had unexpected results:\n--- want\n+++ got\n%v", diff) + } +} + +// DirentCollector provides an implementation for vfs.IterDirentsCallback for +// testing. It simply iterates to the end of a given directory FD and collects +// all dirents emitted by the callback. +type DirentCollector struct { + mu sync.Mutex + dirents map[string]vfs.Dirent +} + +// Handle implements vfs.IterDirentsCallback.Handle. +func (d *DirentCollector) Handle(dirent vfs.Dirent) bool { + d.mu.Lock() + if d.dirents == nil { + d.dirents = make(map[string]vfs.Dirent) + } + d.dirents[dirent.Name] = dirent + d.mu.Unlock() + return true +} + +// Count returns the number of dirents currently in the collector. +func (d *DirentCollector) Count() int { + d.mu.Lock() + defer d.mu.Unlock() + return len(d.dirents) +} + +// Contains checks whether the collector has a dirent with the given name and +// type. +func (d *DirentCollector) Contains(name string, typ uint8) error { + d.mu.Lock() + defer d.mu.Unlock() + dirent, ok := d.dirents[name] + if !ok { + return fmt.Errorf("No dirent named %q found", name) + } + if dirent.Type != typ { + return fmt.Errorf("Dirent named %q found, but was expecting type %s, got: %+v", name, linux.DirentType.Parse(uint64(typ)), dirent) + } + return nil +} -- cgit v1.2.3 From 7e6fbc6afe797752efe066a8aa86f9eca973f3a4 Mon Sep 17 00:00:00 2001 From: Mithun Iyer Date: Tue, 21 Jan 2020 14:47:04 -0800 Subject: Add a new TCP stat for current open connections. Such a stat accounts for all connections that are currently established and not yet transitioned to close state. Also fix bug in double increment of CurrentEstablished stat. Fixes #1579 PiperOrigin-RevId: 290827365 --- pkg/sentry/socket/netstack/netstack.go | 3 +- pkg/tcpip/tcpip.go | 6 ++- pkg/tcpip/transport/tcp/accept.go | 1 - pkg/tcpip/transport/tcp/connect.go | 1 + pkg/tcpip/transport/tcp/endpoint.go | 1 + pkg/tcpip/transport/tcp/tcp_test.go | 83 ++++++++++++++++++++++++++++++++++ 6 files changed, 92 insertions(+), 3 deletions(-) diff --git a/pkg/sentry/socket/netstack/netstack.go b/pkg/sentry/socket/netstack/netstack.go index 2662fbc0f..318acbeff 100644 --- a/pkg/sentry/socket/netstack/netstack.go +++ b/pkg/sentry/socket/netstack/netstack.go @@ -150,7 +150,8 @@ var Metrics = tcpip.Stats{ TCP: tcpip.TCPStats{ ActiveConnectionOpenings: mustCreateMetric("/netstack/tcp/active_connection_openings", "Number of connections opened successfully via Connect."), PassiveConnectionOpenings: mustCreateMetric("/netstack/tcp/passive_connection_openings", "Number of connections opened successfully via Listen."), - CurrentEstablished: mustCreateMetric("/netstack/tcp/current_established", "Number of connections in either ESTABLISHED or CLOSE-WAIT state now."), + CurrentEstablished: mustCreateMetric("/netstack/tcp/current_established", "Number of connections in ESTABLISHED state now."), + CurrentConnected: mustCreateMetric("/netstack/tcp/current_open", "Number of connections that are in connected state."), EstablishedResets: mustCreateMetric("/netstack/tcp/established_resets", "Number of times TCP connections have made a direct transition to the CLOSED state from either the ESTABLISHED state or the CLOSE-WAIT state"), EstablishedClosed: mustCreateMetric("/netstack/tcp/established_closed", "number of times established TCP connections made a transition to CLOSED state."), EstablishedTimedout: mustCreateMetric("/netstack/tcp/established_timedout", "Number of times an established connection was reset because of keep-alive time out."), diff --git a/pkg/tcpip/tcpip.go b/pkg/tcpip/tcpip.go index 3fc823a36..59c9b3fb0 100644 --- a/pkg/tcpip/tcpip.go +++ b/pkg/tcpip/tcpip.go @@ -938,9 +938,13 @@ type TCPStats struct { PassiveConnectionOpenings *StatCounter // CurrentEstablished is the number of TCP connections for which the - // current state is either ESTABLISHED or CLOSE-WAIT. + // current state is ESTABLISHED. CurrentEstablished *StatCounter + // CurrentConnected is the number of TCP connections that + // are in connected state. + CurrentConnected *StatCounter + // EstablishedResets is the number of times TCP connections have made // a direct transition to the CLOSED state from either the // ESTABLISHED state or the CLOSE-WAIT state. diff --git a/pkg/tcpip/transport/tcp/accept.go b/pkg/tcpip/transport/tcp/accept.go index 1a2e3efa9..d469758eb 100644 --- a/pkg/tcpip/transport/tcp/accept.go +++ b/pkg/tcpip/transport/tcp/accept.go @@ -562,7 +562,6 @@ func (e *endpoint) handleListenSegment(ctx *listenContext, s *segment) { // Switch state to connected. // We do not use transitionToStateEstablishedLocked here as there is // no handshake state available when doing a SYN cookie based accept. - n.stack.Stats().TCP.CurrentEstablished.Increment() n.isConnectNotified = true n.setEndpointState(StateEstablished) diff --git a/pkg/tcpip/transport/tcp/connect.go b/pkg/tcpip/transport/tcp/connect.go index a2f384384..4e3c5419c 100644 --- a/pkg/tcpip/transport/tcp/connect.go +++ b/pkg/tcpip/transport/tcp/connect.go @@ -934,6 +934,7 @@ func (e *endpoint) transitionToStateCloseLocked() { // Mark the endpoint as fully closed for reads/writes. e.cleanupLocked() e.setEndpointState(StateClose) + e.stack.Stats().TCP.CurrentConnected.Decrement() e.stack.Stats().TCP.EstablishedClosed.Increment() } diff --git a/pkg/tcpip/transport/tcp/endpoint.go b/pkg/tcpip/transport/tcp/endpoint.go index 4797f11d1..13718ff55 100644 --- a/pkg/tcpip/transport/tcp/endpoint.go +++ b/pkg/tcpip/transport/tcp/endpoint.go @@ -594,6 +594,7 @@ func (e *endpoint) setEndpointState(state EndpointState) { switch state { case StateEstablished: e.stack.Stats().TCP.CurrentEstablished.Increment() + e.stack.Stats().TCP.CurrentConnected.Increment() case StateError: fallthrough case StateClose: diff --git a/pkg/tcpip/transport/tcp/tcp_test.go b/pkg/tcpip/transport/tcp/tcp_test.go index a9dfbe857..df2fb1071 100644 --- a/pkg/tcpip/transport/tcp/tcp_test.go +++ b/pkg/tcpip/transport/tcp/tcp_test.go @@ -470,6 +470,89 @@ func TestConnectResetAfterClose(t *testing.T) { } } +// TestCurrentConnectedIncrement tests increment of the current +// established and connected counters. +func TestCurrentConnectedIncrement(t *testing.T) { + c := context.New(t, defaultMTU) + defer c.Cleanup() + + // Set TCPTimeWaitTimeout to 1 seconds so that sockets are marked closed + // after 1 second in TIME_WAIT state. + tcpTimeWaitTimeout := 1 * time.Second + if err := c.Stack().SetTransportProtocolOption(tcp.ProtocolNumber, tcpip.TCPTimeWaitTimeoutOption(tcpTimeWaitTimeout)); err != nil { + t.Fatalf("c.stack.SetTransportProtocolOption(tcp, tcpip.TCPTimeWaitTimeout(%d) failed: %s", tcpTimeWaitTimeout, err) + } + + c.CreateConnected(789, 30000, -1 /* epRcvBuf */) + ep := c.EP + c.EP = nil + + if got := c.Stack().Stats().TCP.CurrentEstablished.Value(); got != 1 { + t.Errorf("got stats.TCP.CurrentEstablished.Value() = %v, want = 1", got) + } + gotConnected := c.Stack().Stats().TCP.CurrentConnected.Value() + if gotConnected != 1 { + t.Errorf("got stats.TCP.CurrentConnected.Value() = %v, want = 1", gotConnected) + } + + ep.Close() + + checker.IPv4(t, c.GetPacket(), + checker.TCP( + checker.DstPort(context.TestPort), + checker.SeqNum(uint32(c.IRS)+1), + checker.AckNum(790), + checker.TCPFlags(header.TCPFlagAck|header.TCPFlagFin), + ), + ) + c.SendPacket(nil, &context.Headers{ + SrcPort: context.TestPort, + DstPort: c.Port, + Flags: header.TCPFlagAck, + SeqNum: 790, + AckNum: c.IRS.Add(2), + RcvWnd: 30000, + }) + + if got := c.Stack().Stats().TCP.CurrentEstablished.Value(); got != 0 { + t.Errorf("got stats.TCP.CurrentEstablished.Value() = %v, want = 0", got) + } + if got := c.Stack().Stats().TCP.CurrentConnected.Value(); got != gotConnected { + t.Errorf("got stats.TCP.CurrentConnected.Value() = %v, want = %v", got, gotConnected) + } + + // Ack and send FIN as well. + c.SendPacket(nil, &context.Headers{ + SrcPort: context.TestPort, + DstPort: c.Port, + Flags: header.TCPFlagAck | header.TCPFlagFin, + SeqNum: 790, + AckNum: c.IRS.Add(2), + RcvWnd: 30000, + }) + + // Check that the stack acks the FIN. + checker.IPv4(t, c.GetPacket(), + checker.PayloadLen(header.TCPMinimumSize), + checker.TCP( + checker.DstPort(context.TestPort), + checker.SeqNum(uint32(c.IRS)+2), + checker.AckNum(791), + checker.TCPFlags(header.TCPFlagAck), + ), + ) + + // Wait for the TIME-WAIT state to transition to CLOSED. + time.Sleep(1 * time.Second) + + if got := c.Stack().Stats().TCP.CurrentEstablished.Value(); got != 0 { + t.Errorf("got stats.TCP.CurrentEstablished.Value() = %v, want = 0", got) + } + if got := c.Stack().Stats().TCP.CurrentConnected.Value(); got != 0 { + t.Errorf("got stats.TCP.CurrentConnected.Value() = %v, want = 0", got) + } +} + // TestClosingWithEnqueuedSegments tests handling of still enqueued segments // when the endpoint transitions to StateClose. The in-flight segments would be // re-enqueued to a any listening endpoint. -- cgit v1.2.3 From 2296b4734462b6eeef383ea58e2b1b0b1a214d76 Mon Sep 17 00:00:00 2001 From: Adin Scannell Date: Tue, 21 Jan 2020 16:16:51 -0800 Subject: Change to standard types. PiperOrigin-RevId: 290846481 --- test/syscalls/linux/aio.cc | 2 +- test/syscalls/linux/chown.cc | 6 +- test/syscalls/linux/chroot.cc | 2 +- test/syscalls/linux/clock_gettime.cc | 12 ++-- test/syscalls/linux/eventfd.cc | 22 ++++---- test/syscalls/linux/exceptions.cc | 66 +++++++++++----------- test/syscalls/linux/exec.cc | 10 ++-- test/syscalls/linux/exec_binary.cc | 18 +++--- test/syscalls/linux/fcntl.cc | 22 ++++---- test/syscalls/linux/fork.cc | 2 +- test/syscalls/linux/futex.cc | 2 +- test/syscalls/linux/inotify.cc | 24 ++++---- test/syscalls/linux/ip_socket_test_util.cc | 4 +- test/syscalls/linux/ip_socket_test_util.h | 4 +- test/syscalls/linux/itimer.cc | 4 +- test/syscalls/linux/kill.cc | 4 +- test/syscalls/linux/link.cc | 5 +- test/syscalls/linux/memfd.cc | 2 +- test/syscalls/linux/memory_accounting.cc | 14 ++--- test/syscalls/linux/mempolicy.cc | 28 ++++----- test/syscalls/linux/mmap.cc | 16 +++--- test/syscalls/linux/open.cc | 2 +- test/syscalls/linux/partial_bad_buffer.cc | 2 +- test/syscalls/linux/prctl_setuid.cc | 2 +- test/syscalls/linux/proc.cc | 42 +++++++------- test/syscalls/linux/proc_net_tcp.cc | 62 ++++++++++---------- test/syscalls/linux/proc_net_udp.cc | 32 +++++------ test/syscalls/linux/proc_net_unix.cc | 12 ++-- test/syscalls/linux/proc_pid_uid_gid_map.cc | 26 ++++----- test/syscalls/linux/ptrace.cc | 4 +- test/syscalls/linux/pty.cc | 14 ++--- test/syscalls/linux/pwrite64.cc | 4 +- test/syscalls/linux/raw_socket_hdrincl.cc | 4 +- test/syscalls/linux/rseq.cc | 2 +- test/syscalls/linux/rseq/critical.h | 2 +- test/syscalls/linux/rseq/rseq.cc | 50 ++++++++-------- test/syscalls/linux/rseq/types.h | 16 +++--- test/syscalls/linux/seccomp.cc | 14 ++--- test/syscalls/linux/semaphore.cc | 10 ++-- test/syscalls/linux/shm.cc | 10 ++-- test/syscalls/linux/sigaltstack.cc | 2 +- test/syscalls/linux/sigiret.cc | 14 ++--- .../linux/socket_bind_to_device_distribution.cc | 14 ++--- test/syscalls/linux/socket_generic.cc | 2 +- test/syscalls/linux/socket_inet_loopback.cc | 56 +++++++++--------- test/syscalls/linux/socket_ip_unbound.cc | 8 +-- test/syscalls/linux/socket_netdevice.cc | 8 +-- test/syscalls/linux/socket_netlink_route.cc | 30 +++++----- test/syscalls/linux/socket_netlink_util.cc | 4 +- test/syscalls/linux/socket_netlink_util.h | 2 +- test/syscalls/linux/socket_test_util.cc | 2 +- test/syscalls/linux/splice.cc | 2 +- test/syscalls/linux/stat.cc | 40 ++++++------- test/syscalls/linux/sticky.cc | 4 +- test/syscalls/linux/sysret.cc | 8 +-- test/syscalls/linux/tcp_socket.cc | 2 +- test/syscalls/linux/time.cc | 4 +- test/syscalls/linux/timerfd.cc | 48 ++++++++-------- test/syscalls/linux/udp_socket_test_cases.cc | 14 ++--- test/syscalls/linux/uidgid.cc | 8 +-- test/syscalls/linux/utimes.cc | 25 ++++---- test/syscalls/linux/vfork.cc | 14 ++--- test/syscalls/linux/vsyscall.cc | 2 +- test/syscalls/linux/wait.cc | 18 +++--- test/util/mount_util.h | 6 +- test/util/multiprocess_util.cc | 2 +- test/util/multiprocess_util.h | 5 +- test/util/proc_util.cc | 2 +- test/util/temp_path.cc | 2 +- test/util/test_util.cc | 20 +++---- test/util/test_util.h | 12 ++-- test/util/test_util_test.cc | 4 +- 72 files changed, 483 insertions(+), 480 deletions(-) diff --git a/test/syscalls/linux/aio.cc b/test/syscalls/linux/aio.cc index 28592bc8f..a33daff17 100644 --- a/test/syscalls/linux/aio.cc +++ b/test/syscalls/linux/aio.cc @@ -183,7 +183,7 @@ TEST_F(AIOTest, BadWrite) { // Verify that it fails with the right error code. EXPECT_EQ(events[0].data, 0x123); - EXPECT_EQ(events[0].obj, reinterpret_cast(&cb)); + EXPECT_EQ(events[0].obj, reinterpret_cast(&cb)); EXPECT_LT(events[0].res, 0); } diff --git a/test/syscalls/linux/chown.cc b/test/syscalls/linux/chown.cc index 1c00e2731..7a28b674d 100644 --- a/test/syscalls/linux/chown.cc +++ b/test/syscalls/linux/chown.cc @@ -31,9 +31,9 @@ #include "test/util/test_util.h" #include "test/util/thread_util.h" -ABSL_FLAG(int32, scratch_uid1, 65534, "first scratch UID"); -ABSL_FLAG(int32, scratch_uid2, 65533, "second scratch UID"); -ABSL_FLAG(int32, scratch_gid, 65534, "first scratch GID"); +ABSL_FLAG(int32_t, scratch_uid1, 65534, "first scratch UID"); +ABSL_FLAG(int32_t, scratch_uid2, 65533, "second scratch UID"); +ABSL_FLAG(int32_t, scratch_gid, 65534, "first scratch GID"); namespace gvisor { namespace testing { diff --git a/test/syscalls/linux/chroot.cc b/test/syscalls/linux/chroot.cc index 27e057086..04bc2d7b9 100644 --- a/test/syscalls/linux/chroot.cc +++ b/test/syscalls/linux/chroot.cc @@ -253,7 +253,7 @@ TEST(ChrootTest, ProcMemSelfMapsNoEscapeProcOpen) { // Mmap the newly created file. void* foo_map = mmap(nullptr, kPageSize, PROT_READ | PROT_WRITE, MAP_PRIVATE, foo.get(), 0); - ASSERT_THAT(reinterpret_cast(foo_map), SyscallSucceeds()); + ASSERT_THAT(reinterpret_cast(foo_map), SyscallSucceeds()); // Always unmap. auto cleanup_map = Cleanup( diff --git a/test/syscalls/linux/clock_gettime.cc b/test/syscalls/linux/clock_gettime.cc index 1d5b5af94..7f6015049 100644 --- a/test/syscalls/linux/clock_gettime.cc +++ b/test/syscalls/linux/clock_gettime.cc @@ -34,7 +34,7 @@ namespace testing { namespace { -int64 clock_gettime_nsecs(clockid_t id) { +int64_t clock_gettime_nsecs(clockid_t id) { struct timespec ts; TEST_PCHECK(clock_gettime(id, &ts) == 0); return (ts.tv_sec * 1000000000 + ts.tv_nsec); @@ -42,9 +42,9 @@ int64 clock_gettime_nsecs(clockid_t id) { // Spin on the CPU for at least ns nanoseconds, based on // CLOCK_THREAD_CPUTIME_ID. -void spin_ns(int64 ns) { - int64 start = clock_gettime_nsecs(CLOCK_THREAD_CPUTIME_ID); - int64 end = start + ns; +void spin_ns(int64_t ns) { + int64_t start = clock_gettime_nsecs(CLOCK_THREAD_CPUTIME_ID); + int64_t end = start + ns; do { constexpr int kLoopCount = 1000000; // large and arbitrary @@ -64,7 +64,7 @@ TEST(ClockGettime, CputimeId) { // the workers. Note that we test CLOCK_PROCESS_CPUTIME_ID by having the // workers execute in parallel and verifying that CLOCK_PROCESS_CPUTIME_ID // accumulates the runtime of all threads. - int64 start = clock_gettime_nsecs(CLOCK_PROCESS_CPUTIME_ID); + int64_t start = clock_gettime_nsecs(CLOCK_PROCESS_CPUTIME_ID); // Create a kNumThreads threads. std::list threads; @@ -76,7 +76,7 @@ TEST(ClockGettime, CputimeId) { t.Join(); } - int64 end = clock_gettime_nsecs(CLOCK_PROCESS_CPUTIME_ID); + int64_t end = clock_gettime_nsecs(CLOCK_PROCESS_CPUTIME_ID); // The aggregate time spent in the worker threads must be at least // 'kNumThreads' times the time each thread spun. diff --git a/test/syscalls/linux/eventfd.cc b/test/syscalls/linux/eventfd.cc index fed67a56e..367682c3d 100644 --- a/test/syscalls/linux/eventfd.cc +++ b/test/syscalls/linux/eventfd.cc @@ -37,7 +37,7 @@ TEST(EventfdTest, Nonblock) { FileDescriptor efd = ASSERT_NO_ERRNO_AND_VALUE(NewEventFD(0, EFD_NONBLOCK | EFD_SEMAPHORE)); - uint64 l; + uint64_t l; ASSERT_THAT(read(efd.get(), &l, sizeof(l)), SyscallFailsWithErrno(EAGAIN)); l = 1; @@ -52,7 +52,7 @@ TEST(EventfdTest, Nonblock) { void* read_three_times(void* arg) { int efd = *reinterpret_cast(arg); - uint64 l; + uint64_t l; EXPECT_THAT(read(efd, &l, sizeof(l)), SyscallSucceedsWithValue(sizeof(l))); EXPECT_THAT(read(efd, &l, sizeof(l)), SyscallSucceedsWithValue(sizeof(l))); EXPECT_THAT(read(efd, &l, sizeof(l)), SyscallSucceedsWithValue(sizeof(l))); @@ -68,7 +68,7 @@ TEST(EventfdTest, BlockingWrite) { reinterpret_cast(&efd)), SyscallSucceeds()); - uint64 l = 1; + uint64_t l = 1; ASSERT_THAT(write(efd, &l, sizeof(l)), SyscallSucceeds()); EXPECT_EQ(l, 1); @@ -85,7 +85,7 @@ TEST(EventfdTest, SmallWrite) { FileDescriptor efd = ASSERT_NO_ERRNO_AND_VALUE(NewEventFD(0, EFD_NONBLOCK | EFD_SEMAPHORE)); - uint64 l = 16; + uint64_t l = 16; ASSERT_THAT(write(efd.get(), &l, 4), SyscallFailsWithErrno(EINVAL)); } @@ -93,7 +93,7 @@ TEST(EventfdTest, SmallRead) { FileDescriptor efd = ASSERT_NO_ERRNO_AND_VALUE(NewEventFD(0, EFD_NONBLOCK | EFD_SEMAPHORE)); - uint64 l = 1; + uint64_t l = 1; ASSERT_THAT(write(efd.get(), &l, sizeof(l)), SyscallSucceeds()); l = 0; @@ -104,7 +104,7 @@ TEST(EventfdTest, BigWrite) { FileDescriptor efd = ASSERT_NO_ERRNO_AND_VALUE(NewEventFD(0, EFD_NONBLOCK | EFD_SEMAPHORE)); - uint64 big[16]; + uint64_t big[16]; big[0] = 16; ASSERT_THAT(write(efd.get(), big, sizeof(big)), SyscallSucceeds()); } @@ -113,10 +113,10 @@ TEST(EventfdTest, BigRead) { FileDescriptor efd = ASSERT_NO_ERRNO_AND_VALUE(NewEventFD(0, EFD_NONBLOCK | EFD_SEMAPHORE)); - uint64 l = 1; + uint64_t l = 1; ASSERT_THAT(write(efd.get(), &l, sizeof(l)), SyscallSucceeds()); - uint64 big[16]; + uint64_t big[16]; ASSERT_THAT(read(efd.get(), big, sizeof(big)), SyscallSucceeds()); EXPECT_EQ(big[0], 1); } @@ -125,7 +125,7 @@ TEST(EventfdTest, BigWriteBigRead) { FileDescriptor efd = ASSERT_NO_ERRNO_AND_VALUE(NewEventFD(0, EFD_NONBLOCK | EFD_SEMAPHORE)); - uint64 l[16]; + uint64_t l[16]; l[0] = 16; ASSERT_THAT(write(efd.get(), l, sizeof(l)), SyscallSucceeds()); ASSERT_THAT(read(efd.get(), l, sizeof(l)), SyscallSucceeds()); @@ -150,7 +150,7 @@ TEST(EventfdTest, NotifyNonZero_NoRandomSave) { int wait_out = epoll_wait(epollfd.get(), &out_ev, 1, kEpollTimeoutMs); EXPECT_EQ(wait_out, 1); EXPECT_EQ(efd.get(), out_ev.data.fd); - uint64 val = 0; + uint64_t val = 0; ASSERT_THAT(read(efd.get(), &val, sizeof(val)), SyscallSucceeds()); EXPECT_EQ(val, 1); @@ -159,7 +159,7 @@ TEST(EventfdTest, NotifyNonZero_NoRandomSave) { // epoll_wait times out. ScopedThread t([&efd] { sleep(5); - uint64 val = 1; + uint64_t val = 1; EXPECT_THAT(write(efd.get(), &val, sizeof(val)), SyscallSucceedsWithValue(sizeof(val))); }); diff --git a/test/syscalls/linux/exceptions.cc b/test/syscalls/linux/exceptions.cc index 0b67eb0ad..3d564e720 100644 --- a/test/syscalls/linux/exceptions.cc +++ b/test/syscalls/linux/exceptions.cc @@ -24,20 +24,20 @@ namespace testing { // Default value for the x87 FPU control word. See Intel SDM Vol 1, Ch 8.1.5 // "x87 FPU Control Word". -constexpr uint16 kX87ControlWordDefault = 0x37f; +constexpr uint16_t kX87ControlWordDefault = 0x37f; // Mask for the divide-by-zero exception. -constexpr uint16 kX87ControlWordDiv0Mask = 1 << 2; +constexpr uint16_t kX87ControlWordDiv0Mask = 1 << 2; // Default value for the SSE control register (MXCSR). See Intel SDM Vol 1, Ch // 11.6.4 "Initialization of SSE/SSE3 Extensions". -constexpr uint32 kMXCSRDefault = 0x1f80; +constexpr uint32_t kMXCSRDefault = 0x1f80; // Mask for the divide-by-zero exception. -constexpr uint32 kMXCSRDiv0Mask = 1 << 9; +constexpr uint32_t kMXCSRDiv0Mask = 1 << 9; // Flag for a pending divide-by-zero exception. -constexpr uint32 kMXCSRDiv0Flag = 1 << 2; +constexpr uint32_t kMXCSRDiv0Flag = 1 << 2; void inline Halt() { asm("hlt\r\n"); } @@ -112,10 +112,10 @@ TEST(ExceptionTest, DivideByZero) { EXPECT_EXIT( { - uint32 remainder; - uint32 quotient; - uint32 divisor = 0; - uint64 value = 1; + uint32_t remainder; + uint32_t quotient; + uint32_t divisor = 0; + uint64_t value = 1; asm("divl 0(%2)\r\n" : "=d"(remainder), "=a"(quotient) : "r"(&divisor), "d"(value >> 32), "a"(value)); @@ -126,9 +126,9 @@ TEST(ExceptionTest, DivideByZero) { // By default, x87 exceptions are masked and simply return a default value. TEST(ExceptionTest, X87DivideByZeroMasked) { - int32 quotient; - int32 value = 1; - int32 divisor = 0; + int32_t quotient; + int32_t value = 1; + int32_t divisor = 0; asm("fildl %[value]\r\n" "fidivl %[divisor]\r\n" "fistpl %[quotient]\r\n" @@ -148,12 +148,12 @@ TEST(ExceptionTest, X87DivideByZeroUnmasked) { EXPECT_EXIT( { // Clear the divide by zero exception mask. - constexpr uint16 kControlWord = + constexpr uint16_t kControlWord = kX87ControlWordDefault & ~kX87ControlWordDiv0Mask; - int32 quotient; - int32 value = 1; - int32 divisor = 0; + int32_t quotient; + int32_t value = 1; + int32_t divisor = 0; asm volatile( "fldcw %[cw]\r\n" "fildl %[value]\r\n" @@ -176,12 +176,12 @@ TEST(ExceptionTest, X87StatusClobber) { EXPECT_EXIT( { // Clear the divide by zero exception mask. - constexpr uint16 kControlWord = + constexpr uint16_t kControlWord = kX87ControlWordDefault & ~kX87ControlWordDiv0Mask; - int32 quotient; - int32 value = 1; - int32 divisor = 0; + int32_t quotient; + int32_t value = 1; + int32_t divisor = 0; asm volatile( "fildl %[value]\r\n" "fidivl %[divisor]\r\n" @@ -208,10 +208,10 @@ TEST(ExceptionTest, X87StatusClobber) { // By default, SSE exceptions are masked and simply return a default value. TEST(ExceptionTest, SSEDivideByZeroMasked) { - uint32 status; - int32 quotient; - int32 value = 1; - int32 divisor = 0; + uint32_t status; + int32_t quotient; + int32_t value = 1; + int32_t divisor = 0; asm("cvtsi2ssl %[value], %%xmm0\r\n" "cvtsi2ssl %[divisor], %%xmm1\r\n" "divss %%xmm1, %%xmm0\r\n" @@ -233,11 +233,11 @@ TEST(ExceptionTest, SSEDivideByZeroUnmasked) { EXPECT_EXIT( { // Clear the divide by zero exception mask. - constexpr uint32 kMXCSR = kMXCSRDefault & ~kMXCSRDiv0Mask; + constexpr uint32_t kMXCSR = kMXCSRDefault & ~kMXCSRDiv0Mask; - int32 quotient; - int32 value = 1; - int32 divisor = 0; + int32_t quotient; + int32_t value = 1; + int32_t divisor = 0; asm volatile( "ldmxcsr %[mxcsr]\r\n" "cvtsi2ssl %[value], %%xmm0\r\n" @@ -254,10 +254,10 @@ TEST(ExceptionTest, SSEDivideByZeroUnmasked) { // Pending exceptions in the SSE status register are not clobbered by syscalls. TEST(ExceptionTest, SSEStatusClobber) { - uint32 mxcsr; - int32 quotient; - int32 value = 1; - int32 divisor = 0; + uint32_t mxcsr; + int32_t quotient; + int32_t value = 1; + int32_t divisor = 0; asm("cvtsi2ssl %[value], %%xmm0\r\n" "cvtsi2ssl %[divisor], %%xmm1\r\n" "divss %%xmm1, %%xmm0\r\n" @@ -336,7 +336,7 @@ TEST(ExceptionTest, AlignmentCheck) { SetAlignmentCheck(); for (int i = 0; i < 8; i++) { // At least 7/8 offsets will be unaligned here. - uint64* ptr = reinterpret_cast(&array[i]); + uint64_t* ptr = reinterpret_cast(&array[i]); asm("mov %0, 0(%0)\r\n" : : "r"(ptr) : "ax"); } }, diff --git a/test/syscalls/linux/exec.cc b/test/syscalls/linux/exec.cc index 9c5a11206..b5e0a512b 100644 --- a/test/syscalls/linux/exec.cc +++ b/test/syscalls/linux/exec.cc @@ -62,7 +62,7 @@ constexpr char kExecFromThread[] = "--exec_exec_from_thread"; // Runs file specified by dirfd and pathname with argv and checks that the exit // status is expect_status and that stderr contains expect_stderr. -void CheckExecHelper(const absl::optional dirfd, +void CheckExecHelper(const absl::optional dirfd, const std::string& pathname, const ExecveArray& argv, const ExecveArray& envv, const int flags, int expect_status, const std::string& expect_stderr) { @@ -143,15 +143,15 @@ void CheckExecHelper(const absl::optional dirfd, void CheckExec(const std::string& filename, const ExecveArray& argv, const ExecveArray& envv, int expect_status, const std::string& expect_stderr) { - CheckExecHelper(/*dirfd=*/absl::optional(), filename, argv, envv, + CheckExecHelper(/*dirfd=*/absl::optional(), filename, argv, envv, /*flags=*/0, expect_status, expect_stderr); } -void CheckExecveat(const int32 dirfd, const std::string& pathname, +void CheckExecveat(const int32_t dirfd, const std::string& pathname, const ExecveArray& argv, const ExecveArray& envv, const int flags, int expect_status, const std::string& expect_stderr) { - CheckExecHelper(absl::optional(dirfd), pathname, argv, envv, flags, + CheckExecHelper(absl::optional(dirfd), pathname, argv, envv, flags, expect_status, expect_stderr); } @@ -603,7 +603,7 @@ TEST(ExecveatTest, AbsolutePathWithFDCWD) { TEST(ExecveatTest, AbsolutePath) { std::string path = RunfilePath(kBasicWorkload); // File descriptor should be ignored when an absolute path is given. - const int32 badFD = -1; + const int32_t badFD = -1; CheckExecveat(badFD, path, {path}, {}, ArgEnvExitStatus(0, 0), 0, absl::StrCat(path, "\n")); } diff --git a/test/syscalls/linux/exec_binary.cc b/test/syscalls/linux/exec_binary.cc index 144bf45cf..736452b0c 100644 --- a/test/syscalls/linux/exec_binary.cc +++ b/test/syscalls/linux/exec_binary.cc @@ -700,7 +700,7 @@ TEST(ElfTest, PIE) { // The first segment really needs to start at 0 for a normal PIE binary, and // thus includes the headers. - const uint64 offset = elf.phdrs[1].p_offset; + const uint64_t offset = elf.phdrs[1].p_offset; elf.phdrs[1].p_offset = 0x0; elf.phdrs[1].p_vaddr = 0x0; elf.phdrs[1].p_filesz += offset; @@ -720,7 +720,7 @@ TEST(ElfTest, PIE) { struct user_regs_struct regs; ASSERT_THAT(ptrace(PTRACE_GETREGS, child, 0, ®s), SyscallSucceeds()); - const uint64 load_addr = regs.rip & ~(kPageSize - 1); + const uint64_t load_addr = regs.rip & ~(kPageSize - 1); EXPECT_THAT(child, ContainsMappings(std::vector({ // text page. @@ -789,7 +789,7 @@ TEST(ElfTest, PIENonZeroStart) { struct user_regs_struct regs; ASSERT_THAT(ptrace(PTRACE_GETREGS, child, 0, ®s), SyscallSucceeds()); - const uint64 load_addr = regs.rip & ~(kPageSize - 1); + const uint64_t load_addr = regs.rip & ~(kPageSize - 1); // The ELF is loaded at an arbitrary address, not the first PT_LOAD vaddr. // @@ -859,7 +859,7 @@ TEST(ElfTest, ELFInterpreter) { // The first segment really needs to start at 0 for a normal PIE binary, and // thus includes the headers. - uint64 const offset = interpreter.phdrs[1].p_offset; + uint64_t const offset = interpreter.phdrs[1].p_offset; // N.B. Since Linux 4.10 (0036d1f7eb95b "binfmt_elf: fix calculations for bss // padding"), Linux unconditionally zeroes the remainder of the highest mapped // page in an interpreter, failing if the protections don't allow write. Thus @@ -912,7 +912,7 @@ TEST(ElfTest, ELFInterpreter) { struct user_regs_struct regs; ASSERT_THAT(ptrace(PTRACE_GETREGS, child, 0, ®s), SyscallSucceeds()); - const uint64 interp_load_addr = regs.rip & ~(kPageSize - 1); + const uint64_t interp_load_addr = regs.rip & ~(kPageSize - 1); EXPECT_THAT( child, ContainsMappings(std::vector({ @@ -1047,7 +1047,7 @@ TEST(ElfTest, ELFInterpreterRelative) { // The first segment really needs to start at 0 for a normal PIE binary, and // thus includes the headers. - uint64 const offset = interpreter.phdrs[1].p_offset; + uint64_t const offset = interpreter.phdrs[1].p_offset; // See comment in ElfTest.ELFInterpreter. interpreter.phdrs[1].p_flags = PF_R | PF_W | PF_X; interpreter.phdrs[1].p_offset = 0x0; @@ -1086,7 +1086,7 @@ TEST(ElfTest, ELFInterpreterRelative) { struct user_regs_struct regs; ASSERT_THAT(ptrace(PTRACE_GETREGS, child, 0, ®s), SyscallSucceeds()); - const uint64 interp_load_addr = regs.rip & ~(kPageSize - 1); + const uint64_t interp_load_addr = regs.rip & ~(kPageSize - 1); EXPECT_THAT( child, ContainsMappings(std::vector({ @@ -1109,7 +1109,7 @@ TEST(ElfTest, ELFInterpreterWrongArch) { // The first segment really needs to start at 0 for a normal PIE binary, and // thus includes the headers. - uint64 const offset = interpreter.phdrs[1].p_offset; + uint64_t const offset = interpreter.phdrs[1].p_offset; // See comment in ElfTest.ELFInterpreter. interpreter.phdrs[1].p_flags = PF_R | PF_W | PF_X; interpreter.phdrs[1].p_offset = 0x0; @@ -1190,7 +1190,7 @@ TEST(ElfTest, ElfInterpreterNoExecute) { // The first segment really needs to start at 0 for a normal PIE binary, and // thus includes the headers. - uint64 const offset = interpreter.phdrs[1].p_offset; + uint64_t const offset = interpreter.phdrs[1].p_offset; // See comment in ElfTest.ELFInterpreter. interpreter.phdrs[1].p_flags = PF_R | PF_W | PF_X; interpreter.phdrs[1].p_offset = 0x0; diff --git a/test/syscalls/linux/fcntl.cc b/test/syscalls/linux/fcntl.cc index 6eb597eae..4f3aa81d6 100644 --- a/test/syscalls/linux/fcntl.cc +++ b/test/syscalls/linux/fcntl.cc @@ -46,9 +46,9 @@ ABSL_FLAG(bool, blocking, false, "Whether to set a blocking lock (otherwise non-blocking)."); ABSL_FLAG(bool, retry_eintr, false, "Whether to retry in the subprocess on EINTR."); -ABSL_FLAG(uint64, child_setlock_start, 0, "The value of struct flock start"); -ABSL_FLAG(uint64, child_setlock_len, 0, "The value of struct flock len"); -ABSL_FLAG(int32, socket_fd, -1, +ABSL_FLAG(uint64_t, child_setlock_start, 0, "The value of struct flock start"); +ABSL_FLAG(uint64_t, child_setlock_len, 0, "The value of struct flock len"); +ABSL_FLAG(int32_t, socket_fd, -1, "A socket to use for communicating more state back " "to the parent."); @@ -71,8 +71,8 @@ class FcntlLockTest : public ::testing::Test { EXPECT_THAT(close(fds_[1]), SyscallSucceeds()); } - int64 GetSubprocessFcntlTimeInUsec() { - int64 ret = 0; + int64_t GetSubprocessFcntlTimeInUsec() { + int64_t ret = 0; EXPECT_THAT(ReadFd(fds_[0], reinterpret_cast(&ret), sizeof(ret)), SyscallSucceedsWithValue(sizeof(ret))); return ret; @@ -676,7 +676,7 @@ TEST_F(FcntlLockTest, SetWriteLockThenBlockingWriteLock) { // We will wait kHoldLockForSec before we release our lock allowing the // subprocess to obtain it. constexpr absl::Duration kHoldLockFor = absl::Seconds(5); - const int64 kMinBlockTimeUsec = absl::ToInt64Microseconds(absl::Seconds(1)); + const int64_t kMinBlockTimeUsec = absl::ToInt64Microseconds(absl::Seconds(1)); absl::SleepFor(kHoldLockFor); @@ -685,7 +685,7 @@ TEST_F(FcntlLockTest, SetWriteLockThenBlockingWriteLock) { ASSERT_THAT(fcntl(fd.get(), F_SETLKW, &fl), SyscallSucceeds()); // Read the blocked time from the subprocess socket. - int64 subprocess_blocked_time_usec = GetSubprocessFcntlTimeInUsec(); + int64_t subprocess_blocked_time_usec = GetSubprocessFcntlTimeInUsec(); // We must have been waiting at least kMinBlockTime. EXPECT_GT(subprocess_blocked_time_usec, kMinBlockTimeUsec); @@ -729,7 +729,7 @@ TEST_F(FcntlLockTest, SetReadLockThenBlockingWriteLock) { // subprocess to obtain it. constexpr absl::Duration kHoldLockFor = absl::Seconds(5); - const int64 kMinBlockTimeUsec = absl::ToInt64Microseconds(absl::Seconds(1)); + const int64_t kMinBlockTimeUsec = absl::ToInt64Microseconds(absl::Seconds(1)); absl::SleepFor(kHoldLockFor); @@ -738,7 +738,7 @@ TEST_F(FcntlLockTest, SetReadLockThenBlockingWriteLock) { ASSERT_THAT(fcntl(fd.get(), F_SETLKW, &fl), SyscallSucceeds()); // Read the blocked time from the subprocess socket. - int64 subprocess_blocked_time_usec = GetSubprocessFcntlTimeInUsec(); + int64_t subprocess_blocked_time_usec = GetSubprocessFcntlTimeInUsec(); // We must have been waiting at least kMinBlockTime. EXPECT_GT(subprocess_blocked_time_usec, kMinBlockTimeUsec); @@ -782,7 +782,7 @@ TEST_F(FcntlLockTest, SetWriteLockThenBlockingReadLock) { // subprocess to obtain it. constexpr absl::Duration kHoldLockFor = absl::Seconds(5); - const int64 kMinBlockTimeUsec = absl::ToInt64Microseconds(absl::Seconds(1)); + const int64_t kMinBlockTimeUsec = absl::ToInt64Microseconds(absl::Seconds(1)); absl::SleepFor(kHoldLockFor); @@ -791,7 +791,7 @@ TEST_F(FcntlLockTest, SetWriteLockThenBlockingReadLock) { ASSERT_THAT(fcntl(fd.get(), F_SETLKW, &fl), SyscallSucceeds()); // Read the blocked time from the subprocess socket. - int64 subprocess_blocked_time_usec = GetSubprocessFcntlTimeInUsec(); + int64_t subprocess_blocked_time_usec = GetSubprocessFcntlTimeInUsec(); // We must have been waiting at least kMinBlockTime. EXPECT_GT(subprocess_blocked_time_usec, kMinBlockTimeUsec); diff --git a/test/syscalls/linux/fork.cc b/test/syscalls/linux/fork.cc index 486189697..371890110 100644 --- a/test/syscalls/linux/fork.cc +++ b/test/syscalls/linux/fork.cc @@ -270,7 +270,7 @@ TEST_F(ForkTest, Alarm) { // Child cannot affect parent private memory. TEST_F(ForkTest, PrivateMemory) { - std::atomic local(0); + std::atomic local(0); pid_t child1 = Fork(); if (child1 == 0) { diff --git a/test/syscalls/linux/futex.cc b/test/syscalls/linux/futex.cc index b4a7cc8d6..40c80a6e1 100644 --- a/test/syscalls/linux/futex.cc +++ b/test/syscalls/linux/futex.cc @@ -112,7 +112,7 @@ int futex_wake_bitset(bool priv, std::atomic* uaddr, int count, } int futex_wake_op(bool priv, std::atomic* uaddr1, std::atomic* uaddr2, - int nwake1, int nwake2, uint32 sub_op) { + int nwake1, int nwake2, uint32_t sub_op) { int op = FUTEX_WAKE_OP; if (priv) { op |= FUTEX_PRIVATE_FLAG; diff --git a/test/syscalls/linux/inotify.cc b/test/syscalls/linux/inotify.cc index 182d676d5..fdef646eb 100644 --- a/test/syscalls/linux/inotify.cc +++ b/test/syscalls/linux/inotify.cc @@ -48,26 +48,26 @@ constexpr int kBufSize = 1024; // C++-friendly version of struct inotify_event. struct Event { - int32 wd; - uint32 mask; - uint32 cookie; - uint32 len; + int32_t wd; + uint32_t mask; + uint32_t cookie; + uint32_t len; std::string name; - Event(uint32 mask, int32 wd, absl::string_view name, uint32 cookie) + Event(uint32_t mask, int32_t wd, absl::string_view name, uint32_t cookie) : wd(wd), mask(mask), cookie(cookie), len(name.size()), name(std::string(name)) {} - Event(uint32 mask, int32 wd, absl::string_view name) + Event(uint32_t mask, int32_t wd, absl::string_view name) : Event(mask, wd, name, 0) {} - Event(uint32 mask, int32 wd) : Event(mask, wd, "", 0) {} + Event(uint32_t mask, int32_t wd) : Event(mask, wd, "", 0) {} Event() : Event(0, 0, "", 0) {} }; // Prints the symbolic name for a struct inotify_event's 'mask' field. -std::string FlagString(uint32 flags) { +std::string FlagString(uint32_t flags) { std::vector names; #define EMIT(target) \ @@ -320,7 +320,7 @@ PosixErrorOr InotifyInit1(int flags) { } PosixErrorOr InotifyAddWatch(int fd, const std::string& path, - uint32 mask) { + uint32_t mask) { int wd; EXPECT_THAT(wd = inotify_add_watch(fd, path.c_str(), mask), SyscallSucceeds()); @@ -647,7 +647,7 @@ TEST(Inotify, MoveGeneratesEvents) { Event(IN_MOVED_TO, root_wd, Basename(newpath), events[1].cookie)})); EXPECT_NE(events[0].cookie, 0); EXPECT_EQ(events[0].cookie, events[1].cookie); - uint32 last_cookie = events[0].cookie; + uint32_t last_cookie = events[0].cookie; // Test move from root -> root/dir1. newpath = NewTempAbsPathInDir(dir1.path()); @@ -841,7 +841,7 @@ TEST(Inotify, ConcurrentThreadsGeneratingEvents) { } auto test_thread = [&files]() { - uint32 seed = time(nullptr); + uint32_t seed = time(nullptr); for (int i = 0; i < 20; i++) { const TempPath& file = files[rand_r(&seed) % files.size()]; const FileDescriptor file_fd = @@ -960,7 +960,7 @@ TEST(Inotify, BlockingReadOnInotifyFd) { t.Join(); // Make sure the event we got back is sane. - uint32 event_mask; + uint32_t event_mask; memcpy(&event_mask, buf.data() + offsetof(struct inotify_event, mask), sizeof(event_mask)); EXPECT_EQ(event_mask, IN_ACCESS); diff --git a/test/syscalls/linux/ip_socket_test_util.cc b/test/syscalls/linux/ip_socket_test_util.cc index f694a6360..6b472eb2f 100644 --- a/test/syscalls/linux/ip_socket_test_util.cc +++ b/test/syscalls/linux/ip_socket_test_util.cc @@ -24,12 +24,12 @@ namespace gvisor { namespace testing { -uint32 IPFromInetSockaddr(const struct sockaddr* addr) { +uint32_t IPFromInetSockaddr(const struct sockaddr* addr) { auto* in_addr = reinterpret_cast(addr); return in_addr->sin_addr.s_addr; } -uint16 PortFromInetSockaddr(const struct sockaddr* addr) { +uint16_t PortFromInetSockaddr(const struct sockaddr* addr) { auto* in_addr = reinterpret_cast(addr); return ntohs(in_addr->sin_port); } diff --git a/test/syscalls/linux/ip_socket_test_util.h b/test/syscalls/linux/ip_socket_test_util.h index 0eeca30dd..0f58e0f77 100644 --- a/test/syscalls/linux/ip_socket_test_util.h +++ b/test/syscalls/linux/ip_socket_test_util.h @@ -27,10 +27,10 @@ namespace gvisor { namespace testing { // Extracts the IP address from an inet sockaddr in network byte order. -uint32 IPFromInetSockaddr(const struct sockaddr* addr); +uint32_t IPFromInetSockaddr(const struct sockaddr* addr); // Extracts the port from an inet sockaddr in host byte order. -uint16 PortFromInetSockaddr(const struct sockaddr* addr); +uint16_t PortFromInetSockaddr(const struct sockaddr* addr); // InterfaceIndex returns the index of the named interface. PosixErrorOr InterfaceIndex(std::string name); diff --git a/test/syscalls/linux/itimer.cc b/test/syscalls/linux/itimer.cc index 52ffbe89d..b77e4cbd1 100644 --- a/test/syscalls/linux/itimer.cc +++ b/test/syscalls/linux/itimer.cc @@ -177,8 +177,8 @@ SignalTestResult ItimerSignalTest(int id, clock_t main_clock, SignalTestResult result; // Wait for the workers to be done and collect their sample counts. - result.worker_samples.push_back(reinterpret_cast(th1.Join())); - result.worker_samples.push_back(reinterpret_cast(th2.Join())); + result.worker_samples.push_back(reinterpret_cast(th1.Join())); + result.worker_samples.push_back(reinterpret_cast(th2.Join())); cleanup_itimer.Release()(); result.expected_total = (Now(main_clock) - start) / kPeriod; result.main_thread_samples = signal_test_num_samples.load(); diff --git a/test/syscalls/linux/kill.cc b/test/syscalls/linux/kill.cc index a2247fdeb..db29bd59c 100644 --- a/test/syscalls/linux/kill.cc +++ b/test/syscalls/linux/kill.cc @@ -32,8 +32,8 @@ #include "test/util/test_util.h" #include "test/util/thread_util.h" -ABSL_FLAG(int32, scratch_uid, 65534, "scratch UID"); -ABSL_FLAG(int32, scratch_gid, 65534, "scratch GID"); +ABSL_FLAG(int32_t, scratch_uid, 65534, "scratch UID"); +ABSL_FLAG(int32_t, scratch_gid, 65534, "scratch GID"); using ::testing::Ge; diff --git a/test/syscalls/linux/link.cc b/test/syscalls/linux/link.cc index 108a0c23e..e74fa2ed5 100644 --- a/test/syscalls/linux/link.cc +++ b/test/syscalls/linux/link.cc @@ -32,7 +32,7 @@ #include "test/util/test_util.h" #include "test/util/thread_util.h" -ABSL_FLAG(int32, scratch_uid, 65534, "scratch UID"); +ABSL_FLAG(int32_t, scratch_uid, 65534, "scratch UID"); namespace gvisor { namespace testing { @@ -55,7 +55,8 @@ TEST(LinkTest, CanCreateLinkFile) { const std::string newname = NewTempAbsPath(); // Get the initial link count. - uint64 initial_link_count = ASSERT_NO_ERRNO_AND_VALUE(Links(oldfile.path())); + uint64_t initial_link_count = + ASSERT_NO_ERRNO_AND_VALUE(Links(oldfile.path())); EXPECT_THAT(link(oldfile.path().c_str(), newname.c_str()), SyscallSucceeds()); diff --git a/test/syscalls/linux/memfd.cc b/test/syscalls/linux/memfd.cc index e10f250d1..e57b49a4a 100644 --- a/test/syscalls/linux/memfd.cc +++ b/test/syscalls/linux/memfd.cc @@ -61,7 +61,7 @@ int memfd_create(const std::string& name, unsigned int flags) { } PosixErrorOr MemfdCreate(const std::string& name, - uint32 flags) { + uint32_t flags) { int fd = memfd_create(name, flags); if (fd < 0) { return PosixError( diff --git a/test/syscalls/linux/memory_accounting.cc b/test/syscalls/linux/memory_accounting.cc index 987dbd151..94aea4077 100644 --- a/test/syscalls/linux/memory_accounting.cc +++ b/test/syscalls/linux/memory_accounting.cc @@ -33,7 +33,7 @@ using ::absl::StrFormat; // AnonUsageFromMeminfo scrapes the current anonymous memory usage from // /proc/meminfo and returns it in bytes. -PosixErrorOr AnonUsageFromMeminfo() { +PosixErrorOr AnonUsageFromMeminfo() { ASSIGN_OR_RETURN_ERRNO(auto meminfo, GetContents("/proc/meminfo")); std::vector lines(absl::StrSplit(meminfo, '\n')); @@ -47,7 +47,7 @@ PosixErrorOr AnonUsageFromMeminfo() { absl::StrSplit(line, ' ', absl::SkipEmpty())); if (parts.size() == 3) { // The size is the second field, let's try to parse it as a number. - ASSIGN_OR_RETURN_ERRNO(auto anon_kb, Atoi(parts[1])); + ASSIGN_OR_RETURN_ERRNO(auto anon_kb, Atoi(parts[1])); return anon_kb * 1024; } @@ -65,10 +65,10 @@ TEST(MemoryAccounting, AnonAccountingPreservedOnSaveRestore) { // the test. SKIP_IF(!IsRunningOnGvisor()); - uint64 anon_initial = ASSERT_NO_ERRNO_AND_VALUE(AnonUsageFromMeminfo()); + uint64_t anon_initial = ASSERT_NO_ERRNO_AND_VALUE(AnonUsageFromMeminfo()); // Cause some anonymous memory usage. - uint64 map_bytes = Megabytes(512); + uint64_t map_bytes = Megabytes(512); char* mem = static_cast(mmap(nullptr, map_bytes, PROT_READ | PROT_WRITE, MAP_POPULATE | MAP_ANON | MAP_PRIVATE, -1, 0)); @@ -77,11 +77,11 @@ TEST(MemoryAccounting, AnonAccountingPreservedOnSaveRestore) { // Write something to each page to prevent them from being decommited on // S/R. Zero pages are dropped on save. - for (uint64 i = 0; i < map_bytes; i += kPageSize) { + for (uint64_t i = 0; i < map_bytes; i += kPageSize) { mem[i] = 'a'; } - uint64 anon_after_alloc = ASSERT_NO_ERRNO_AND_VALUE(AnonUsageFromMeminfo()); + uint64_t anon_after_alloc = ASSERT_NO_ERRNO_AND_VALUE(AnonUsageFromMeminfo()); EXPECT_THAT(anon_after_alloc, EquivalentWithin(anon_initial + map_bytes, 0.03)); @@ -90,7 +90,7 @@ TEST(MemoryAccounting, AnonAccountingPreservedOnSaveRestore) { MaybeSave(); // Usage should remain the same across S/R. - uint64 anon_after_sr = ASSERT_NO_ERRNO_AND_VALUE(AnonUsageFromMeminfo()); + uint64_t anon_after_sr = ASSERT_NO_ERRNO_AND_VALUE(AnonUsageFromMeminfo()); EXPECT_THAT(anon_after_sr, EquivalentWithin(anon_after_alloc, 0.03)); } diff --git a/test/syscalls/linux/mempolicy.cc b/test/syscalls/linux/mempolicy.cc index 46bbbc923..9d5f47651 100644 --- a/test/syscalls/linux/mempolicy.cc +++ b/test/syscalls/linux/mempolicy.cc @@ -43,12 +43,12 @@ namespace { #define MPOL_MF_MOVE (1 << 1) #define MPOL_MF_MOVE_ALL (1 << 2) -int get_mempolicy(int *policy, uint64 *nmask, uint64 maxnode, void *addr, +int get_mempolicy(int *policy, uint64_t *nmask, uint64_t maxnode, void *addr, int flags) { return syscall(SYS_get_mempolicy, policy, nmask, maxnode, addr, flags); } -int set_mempolicy(int mode, uint64 *nmask, uint64 maxnode) { +int set_mempolicy(int mode, uint64_t *nmask, uint64_t maxnode) { return syscall(SYS_set_mempolicy, mode, nmask, maxnode); } @@ -68,8 +68,8 @@ Cleanup ScopedMempolicy() { // Temporarily change the memory policy for the calling thread within the // caller's scope. -PosixErrorOr ScopedSetMempolicy(int mode, uint64 *nmask, - uint64 maxnode) { +PosixErrorOr ScopedSetMempolicy(int mode, uint64_t *nmask, + uint64_t maxnode) { if (set_mempolicy(mode, nmask, maxnode)) { return PosixError(errno, "set_mempolicy"); } @@ -78,7 +78,7 @@ PosixErrorOr ScopedSetMempolicy(int mode, uint64 *nmask, TEST(MempolicyTest, CheckDefaultPolicy) { int mode = 0; - uint64 nodemask = 0; + uint64_t nodemask = 0; ASSERT_THAT(get_mempolicy(&mode, &nodemask, sizeof(nodemask) * BITS_PER_BYTE, nullptr, 0), SyscallSucceeds()); @@ -88,12 +88,12 @@ TEST(MempolicyTest, CheckDefaultPolicy) { } TEST(MempolicyTest, PolicyPreservedAfterSetMempolicy) { - uint64 nodemask = 0x1; + uint64_t nodemask = 0x1; auto cleanup = ASSERT_NO_ERRNO_AND_VALUE(ScopedSetMempolicy( MPOL_BIND, &nodemask, sizeof(nodemask) * BITS_PER_BYTE)); int mode = 0; - uint64 nodemask_after = 0x0; + uint64_t nodemask_after = 0x0; ASSERT_THAT(get_mempolicy(&mode, &nodemask_after, sizeof(nodemask_after) * BITS_PER_BYTE, nullptr, 0), SyscallSucceeds()); @@ -118,7 +118,7 @@ TEST(MempolicyTest, PolicyPreservedAfterSetMempolicy) { TEST(MempolicyTest, SetMempolicyRejectsInvalidInputs) { auto cleanup = ScopedMempolicy(); - uint64 nodemask; + uint64_t nodemask; if (IsRunningOnGvisor()) { // Invalid nodemask, we only support a single node on gvisor. @@ -165,7 +165,7 @@ TEST(MempolicyTest, EmptyNodemaskOnSet) { SyscallFailsWithErrno(EINVAL)); EXPECT_THAT(set_mempolicy(MPOL_PREFERRED, nullptr, 1), SyscallSucceeds()); - uint64 nodemask = 0x1; + uint64_t nodemask = 0x1; EXPECT_THAT(set_mempolicy(MPOL_DEFAULT, &nodemask, 0), SyscallFailsWithErrno(EINVAL)); EXPECT_THAT(set_mempolicy(MPOL_BIND, &nodemask, 0), @@ -175,7 +175,7 @@ TEST(MempolicyTest, EmptyNodemaskOnSet) { } TEST(MempolicyTest, QueryAvailableNodes) { - uint64 nodemask = 0; + uint64_t nodemask = 0; ASSERT_THAT( get_mempolicy(nullptr, &nodemask, sizeof(nodemask) * BITS_PER_BYTE, nullptr, MPOL_F_MEMS_ALLOWED), @@ -197,8 +197,8 @@ TEST(MempolicyTest, QueryAvailableNodes) { } TEST(MempolicyTest, GetMempolicyQueryNodeForAddress) { - uint64 dummy_stack_address; - auto dummy_heap_address = absl::make_unique(); + uint64_t dummy_stack_address; + auto dummy_heap_address = absl::make_unique(); int mode; for (auto ptr : {&dummy_stack_address, dummy_heap_address.get()}) { @@ -228,7 +228,7 @@ TEST(MempolicyTest, GetMempolicyQueryNodeForAddress) { TEST(MempolicyTest, GetMempolicyCanOmitPointers) { int mode; - uint64 nodemask; + uint64_t nodemask; // Omit nodemask pointer. ASSERT_THAT(get_mempolicy(&mode, nullptr, 0, nullptr, 0), SyscallSucceeds()); @@ -249,7 +249,7 @@ TEST(MempolicyTest, GetMempolicyNextInterleaveNode) { SyscallFailsWithErrno(EINVAL)); // Set default policy for thread to MPOL_INTERLEAVE. - uint64 nodemask = 0x1; + uint64_t nodemask = 0x1; auto cleanup = ASSERT_NO_ERRNO_AND_VALUE(ScopedSetMempolicy( MPOL_INTERLEAVE, &nodemask, sizeof(nodemask) * BITS_PER_BYTE)); diff --git a/test/syscalls/linux/mmap.cc b/test/syscalls/linux/mmap.cc index 9b2270c8d..1c4d9f1c7 100644 --- a/test/syscalls/linux/mmap.cc +++ b/test/syscalls/linux/mmap.cc @@ -50,13 +50,13 @@ namespace testing { namespace { -PosixErrorOr VirtualMemorySize() { +PosixErrorOr VirtualMemorySize() { ASSIGN_OR_RETURN_ERRNO(auto contents, GetContents("/proc/self/statm")); std::vector parts = absl::StrSplit(contents, ' '); if (parts.empty()) { return PosixError(EINVAL, "Unable to parse /proc/self/statm"); } - ASSIGN_OR_RETURN_ERRNO(auto pages, Atoi(parts[0])); + ASSIGN_OR_RETURN_ERRNO(auto pages, Atoi(parts[0])); return pages * getpagesize(); } @@ -245,7 +245,7 @@ TEST_F(MMapTest, MapDevZeroSharedFdNoPersistence) { // Create a second mapping via the same fd. void* psec_map = mmap(nullptr, kPageSize, PROT_READ | PROT_WRITE, MAP_SHARED, dev_zero.get(), 0); - ASSERT_THAT(reinterpret_cast(psec_map), SyscallSucceeds()); + ASSERT_THAT(reinterpret_cast(psec_map), SyscallSucceeds()); // Always unmap. auto cleanup_psec_map = Cleanup( @@ -690,10 +690,10 @@ TEST_F(MMapTest, ExceedLimitDataPrlimitPID) { } TEST_F(MMapTest, NoExceedLimitAS) { - constexpr uint64 kAllocBytes = 200 << 20; + constexpr uint64_t kAllocBytes = 200 << 20; // Add some headroom to the AS limit in case of e.g. unexpected stack // expansion. - constexpr uint64 kExtraASBytes = kAllocBytes + (20 << 20); + constexpr uint64_t kExtraASBytes = kAllocBytes + (20 << 20); static_assert(kAllocBytes < kExtraASBytes, "test depends on allocation not exceeding AS limit"); @@ -708,10 +708,10 @@ TEST_F(MMapTest, NoExceedLimitAS) { } TEST_F(MMapTest, ExceedLimitAS) { - constexpr uint64 kAllocBytes = 200 << 20; + constexpr uint64_t kAllocBytes = 200 << 20; // Add some headroom to the AS limit in case of e.g. unexpected stack // expansion. - constexpr uint64 kExtraASBytes = 20 << 20; + constexpr uint64_t kExtraASBytes = 20 << 20; static_assert(kAllocBytes > kExtraASBytes, "test depends on allocation exceeding AS limit"); @@ -1469,7 +1469,7 @@ TEST_F(MMapFileTest, InternalSigBusZeroing) { SyscallFailsWithErrno(EFAULT)); } -// Checks that mmaps with a length of uint64(-PAGE_SIZE + 1) or greater do not +// Checks that mmaps with a length of uint64_t(-PAGE_SIZE + 1) or greater do not // induce a sentry panic (due to "rounding up" to 0). TEST_F(MMapTest, HugeLength) { EXPECT_THAT(Map(0, static_cast(-kPageSize + 1), PROT_NONE, diff --git a/test/syscalls/linux/open.cc b/test/syscalls/linux/open.cc index a5e790729..267ae19f6 100644 --- a/test/syscalls/linux/open.cc +++ b/test/syscalls/linux/open.cc @@ -193,7 +193,7 @@ TEST_F(OpenTest, Fault) { TEST_F(OpenTest, AppendOnly) { // First write some data to the fresh file. - const int64 kBufSize = 1024; + const int64_t kBufSize = 1024; std::vector buf(kBufSize, 'a'); FileDescriptor fd0 = ASSERT_NO_ERRNO_AND_VALUE(Open(test_file_name_, O_RDWR)); diff --git a/test/syscalls/linux/partial_bad_buffer.cc b/test/syscalls/linux/partial_bad_buffer.cc index 55eb9361f..df7129acc 100644 --- a/test/syscalls/linux/partial_bad_buffer.cc +++ b/test/syscalls/linux/partial_bad_buffer.cc @@ -363,7 +363,7 @@ TEST_F(PartialBadBufferTest, SendMsgTCP) { // byte past the valid page and check that it triggers an EFAULT // correctly. Otherwise in gVisor the sendmsg call will just return with no // error with kPageSize bytes written successfully. - const uint32 buf_size = kPageSize + 1; + const uint32_t buf_size = kPageSize + 1; ASSERT_THAT(setsockopt(send_socket.get(), SOL_SOCKET, SO_SNDBUF, &buf_size, sizeof(buf_size)), SyscallSucceedsWithValue(0)); diff --git a/test/syscalls/linux/prctl_setuid.cc b/test/syscalls/linux/prctl_setuid.cc index ad39a8463..30f0d75b3 100644 --- a/test/syscalls/linux/prctl_setuid.cc +++ b/test/syscalls/linux/prctl_setuid.cc @@ -26,7 +26,7 @@ #include "test/util/test_util.h" #include "test/util/thread_util.h" -ABSL_FLAG(int32, scratch_uid, 65534, "scratch UID"); +ABSL_FLAG(int32_t, scratch_uid, 65534, "scratch UID"); // This flag is used to verify that after an exec PR_GET_KEEPCAPS // returns 0, the return code will be offset by kPrGetKeepCapsExitBase. ABSL_FLAG(bool, prctl_pr_get_keepcaps, false, diff --git a/test/syscalls/linux/proc.cc b/test/syscalls/linux/proc.cc index 0d5899ec9..bf9bb45d3 100644 --- a/test/syscalls/linux/proc.cc +++ b/test/syscalls/linux/proc.cc @@ -463,12 +463,12 @@ std::string AnonymousMapsEntryForMapping(const Mapping& m, int prot) { return AnonymousMapsEntry(m.addr(), m.len(), prot); } -PosixErrorOr> ReadProcSelfAuxv() { +PosixErrorOr> ReadProcSelfAuxv() { std::string auxv_file; RETURN_IF_ERRNO(GetContents("/proc/self/auxv", &auxv_file)); const Elf64_auxv_t* auxv_data = reinterpret_cast(auxv_file.data()); - std::map auxv_entries; + std::map auxv_entries; for (int i = 0; auxv_data[i].a_type != AT_NULL; i++) { auto a_type = auxv_data[i].a_type; EXPECT_EQ(0, auxv_entries.count(a_type)) << "a_type: " << a_type; @@ -877,7 +877,7 @@ TEST(ProcStat, Fields) { // All fields besides itime are valid base 10 numbers. for (size_t i = 1; i < fields.size(); i++) { - uint64 val; + uint64_t val; EXPECT_TRUE(absl::SimpleAtoi(fields[i], &val)) << proc_stat; } } @@ -904,7 +904,7 @@ TEST(ProcLoadavg, Fields) { EXPECT_EQ(fields.size(), 6) << proc_loadvg; double val; - uint64 val2; + uint64_t val2; // First three fields are floating point numbers. EXPECT_TRUE(absl::SimpleAtod(fields[0], &val)) << proc_loadvg; EXPECT_TRUE(absl::SimpleAtod(fields[1], &val)) << proc_loadvg; @@ -936,19 +936,19 @@ TEST_P(ProcPidStatTest, HasBasicFields) { // boot time will be very close, and the proc starttime field (which is the // delta of the two times) will be 0. For that unfortunate reason, we can // only check that starttime >= 0, and not that it is strictly > 0. - uint64 starttime; + uint64_t starttime; ASSERT_TRUE(absl::SimpleAtoi(fields[21], &starttime)); EXPECT_GE(starttime, 0); - uint64 vss; + uint64_t vss; ASSERT_TRUE(absl::SimpleAtoi(fields[22], &vss)); EXPECT_GT(vss, 0); - uint64 rss; + uint64_t rss; ASSERT_TRUE(absl::SimpleAtoi(fields[23], &rss)); EXPECT_GT(rss, 0); - uint64 rsslim; + uint64_t rsslim; ASSERT_TRUE(absl::SimpleAtoi(fields[24], &rsslim)); EXPECT_GT(rsslim, 0); } @@ -965,11 +965,11 @@ TEST_P(ProcPidStatmTest, HasBasicFields) { std::vector fields = absl::StrSplit(proc_pid_statm, ' '); ASSERT_GE(fields.size(), 7); - uint64 vss; + uint64_t vss; ASSERT_TRUE(absl::SimpleAtoi(fields[0], &vss)); EXPECT_GT(vss, 0); - uint64 rss; + uint64_t rss; ASSERT_TRUE(absl::SimpleAtoi(fields[1], &rss)); EXPECT_GT(rss, 0); } @@ -977,7 +977,7 @@ TEST_P(ProcPidStatmTest, HasBasicFields) { INSTANTIATE_TEST_SUITE_P(SelfAndNumericPid, ProcPidStatmTest, ::testing::Values("self", absl::StrCat(getpid()))); -PosixErrorOr CurrentRSS() { +PosixErrorOr CurrentRSS() { ASSIGN_OR_RETURN_ERRNO(auto proc_self_stat, GetContents("/proc/self/stat")); if (proc_self_stat.empty()) { return PosixError(EINVAL, "empty /proc/self/stat"); @@ -990,7 +990,7 @@ PosixErrorOr CurrentRSS() { absl::StrCat("/proc/self/stat has too few fields: ", proc_self_stat)); } - uint64 rss; + uint64_t rss; if (!absl::SimpleAtoi(fields[23], &rss)) { return PosixError( EINVAL, absl::StrCat("/proc/self/stat RSS field is not a number: ", @@ -1002,14 +1002,14 @@ PosixErrorOr CurrentRSS() { } // The size of mapping created by MapPopulateRSS. -constexpr uint64 kMappingSize = 100 << 20; +constexpr uint64_t kMappingSize = 100 << 20; // Tolerance on RSS comparisons to account for background thread mappings, // reclaimed pages, newly faulted pages, etc. -constexpr uint64 kRSSTolerance = 5 << 20; +constexpr uint64_t kRSSTolerance = 5 << 20; // Capture RSS before and after an anonymous mapping with passed prot. -void MapPopulateRSS(int prot, uint64* before, uint64* after) { +void MapPopulateRSS(int prot, uint64_t* before, uint64_t* after) { *before = ASSERT_NO_ERRNO_AND_VALUE(CurrentRSS()); // N.B. The kernel asynchronously accumulates per-task RSS counters into the @@ -1040,7 +1040,7 @@ void MapPopulateRSS(int prot, uint64* before, uint64* after) { // PROT_WRITE + MAP_POPULATE anonymous mappings are always committed. TEST(ProcSelfStat, PopulateWriteRSS) { - uint64 before, after; + uint64_t before, after; MapPopulateRSS(PROT_READ | PROT_WRITE, &before, &after); // Mapping is committed. @@ -1049,7 +1049,7 @@ TEST(ProcSelfStat, PopulateWriteRSS) { // PROT_NONE + MAP_POPULATE anonymous mappings are never committed. TEST(ProcSelfStat, PopulateNoneRSS) { - uint64 before, after; + uint64_t before, after; MapPopulateRSS(PROT_NONE, &before, &after); // Mapping not committed. @@ -1766,7 +1766,7 @@ TEST(ProcTask, VerifyTaskDirNlinks) { // Once we reach the test body, we can count on the thread count being stable // unless we spawn a new one. - uint64 initial_links = ASSERT_NO_ERRNO_AND_VALUE(Links("/proc/self/task")); + uint64_t initial_links = ASSERT_NO_ERRNO_AND_VALUE(Links("/proc/self/task")); ASSERT_GE(initial_links, 3); // For each new subtask, we should gain a new link. @@ -1864,9 +1864,9 @@ TEST(ProcFilesystems, Bug65172365) { } TEST(ProcFilesystems, PresenceOfShmMaxMniAll) { - uint64 shmmax = 0; - uint64 shmall = 0; - uint64 shmmni = 0; + uint64_t shmmax = 0; + uint64_t shmall = 0; + uint64_t shmmni = 0; std::string proc_file; proc_file = ASSERT_NO_ERRNO_AND_VALUE(GetContents("/proc/sys/kernel/shmmax")); ASSERT_FALSE(proc_file.empty()); diff --git a/test/syscalls/linux/proc_net_tcp.cc b/test/syscalls/linux/proc_net_tcp.cc index 77183420b..5b6e3e3cd 100644 --- a/test/syscalls/linux/proc_net_tcp.cc +++ b/test/syscalls/linux/proc_net_tcp.cc @@ -40,15 +40,15 @@ constexpr char kProcNetTCPHeader[] = // TCPEntry represents a single entry from /proc/net/tcp. struct TCPEntry { - uint32 local_addr; - uint16 local_port; + uint32_t local_addr; + uint16_t local_port; - uint32 remote_addr; - uint16 remote_port; + uint32_t remote_addr; + uint16_t remote_port; - uint64 state; - uint64 uid; - uint64 inode; + uint64_t state; + uint64_t uid; + uint64_t inode; }; // Finds the first entry in 'entries' for which 'predicate' returns true. @@ -69,8 +69,8 @@ bool FindBy(const std::vector& entries, TCPEntry* match, bool FindByLocalAddr(const std::vector& entries, TCPEntry* match, const struct sockaddr* addr) { - uint32 host = IPFromInetSockaddr(addr); - uint16 port = PortFromInetSockaddr(addr); + uint32_t host = IPFromInetSockaddr(addr); + uint16_t port = PortFromInetSockaddr(addr); return FindBy(entries, match, [host, port](const TCPEntry& e) { return (e.local_addr == host && e.local_port == port); }); @@ -78,8 +78,8 @@ bool FindByLocalAddr(const std::vector& entries, TCPEntry* match, bool FindByRemoteAddr(const std::vector& entries, TCPEntry* match, const struct sockaddr* addr) { - uint32 host = IPFromInetSockaddr(addr); - uint16 port = PortFromInetSockaddr(addr); + uint32_t host = IPFromInetSockaddr(addr); + uint16_t port = PortFromInetSockaddr(addr); return FindBy(entries, match, [host, port](const TCPEntry& e) { return (e.remote_addr == host && e.remote_port == port); }); @@ -131,8 +131,8 @@ PosixErrorOr> ProcNetTCPEntries() { ASSIGN_OR_RETURN_ERRNO(entry.remote_port, AtoiBase(fields[4], 16)); ASSIGN_OR_RETURN_ERRNO(entry.state, AtoiBase(fields[5], 16)); - ASSIGN_OR_RETURN_ERRNO(entry.uid, Atoi(fields[11])); - ASSIGN_OR_RETURN_ERRNO(entry.inode, Atoi(fields[13])); + ASSIGN_OR_RETURN_ERRNO(entry.uid, Atoi(fields[11])); + ASSIGN_OR_RETURN_ERRNO(entry.inode, Atoi(fields[13])); entries.push_back(entry); } @@ -234,8 +234,8 @@ TEST(ProcNetTCP, State) { FileDescriptor accepted = ASSERT_NO_ERRNO_AND_VALUE(Accept(server->get(), nullptr, nullptr)); - const uint32 accepted_local_host = IPFromInetSockaddr(&addr); - const uint16 accepted_local_port = PortFromInetSockaddr(&addr); + const uint32_t accepted_local_host = IPFromInetSockaddr(&addr); + const uint16_t accepted_local_port = PortFromInetSockaddr(&addr); entries = ASSERT_NO_ERRNO_AND_VALUE(ProcNetTCPEntries()); TCPEntry accepted_entry; @@ -258,14 +258,14 @@ constexpr char kProcNetTCP6Header[] = // TCP6Entry represents a single entry from /proc/net/tcp6. struct TCP6Entry { struct in6_addr local_addr; - uint16 local_port; + uint16_t local_port; struct in6_addr remote_addr; - uint16 remote_port; + uint16_t remote_port; - uint64 state; - uint64 uid; - uint64 inode; + uint64_t state; + uint64_t uid; + uint64_t inode; }; bool IPv6AddrEqual(const struct in6_addr* a1, const struct in6_addr* a2) { @@ -296,7 +296,7 @@ const struct in6_addr* IP6FromInetSockaddr(const struct sockaddr* addr) { bool FindByLocalAddr6(const std::vector& entries, TCP6Entry* match, const struct sockaddr* addr) { const struct in6_addr* local = IP6FromInetSockaddr(addr); - uint16 port = PortFromInetSockaddr(addr); + uint16_t port = PortFromInetSockaddr(addr); return FindBy6(entries, match, [local, port](const TCP6Entry& e) { return (IPv6AddrEqual(&e.local_addr, local) && e.local_port == port); }); @@ -305,22 +305,22 @@ bool FindByLocalAddr6(const std::vector& entries, TCP6Entry* match, bool FindByRemoteAddr6(const std::vector& entries, TCP6Entry* match, const struct sockaddr* addr) { const struct in6_addr* remote = IP6FromInetSockaddr(addr); - uint16 port = PortFromInetSockaddr(addr); + uint16_t port = PortFromInetSockaddr(addr); return FindBy6(entries, match, [remote, port](const TCP6Entry& e) { return (IPv6AddrEqual(&e.remote_addr, remote) && e.remote_port == port); }); } void ReadIPv6Address(std::string s, struct in6_addr* addr) { - uint32 a0, a1, a2, a3; + uint32_t a0, a1, a2, a3; const char* fmt = "%08X%08X%08X%08X"; EXPECT_EQ(sscanf(s.c_str(), fmt, &a0, &a1, &a2, &a3), 4); - uint8* b = addr->s6_addr; - *((uint32*)&b[0]) = a0; - *((uint32*)&b[4]) = a1; - *((uint32*)&b[8]) = a2; - *((uint32*)&b[12]) = a3; + uint8_t* b = addr->s6_addr; + *((uint32_t*)&b[0]) = a0; + *((uint32_t*)&b[4]) = a1; + *((uint32_t*)&b[8]) = a2; + *((uint32_t*)&b[12]) = a3; } // Returns a parsed representation of /proc/net/tcp6 entries. @@ -367,8 +367,8 @@ PosixErrorOr> ProcNetTCP6Entries() { ReadIPv6Address(fields[3], &entry.remote_addr); ASSIGN_OR_RETURN_ERRNO(entry.remote_port, AtoiBase(fields[4], 16)); ASSIGN_OR_RETURN_ERRNO(entry.state, AtoiBase(fields[5], 16)); - ASSIGN_OR_RETURN_ERRNO(entry.uid, Atoi(fields[11])); - ASSIGN_OR_RETURN_ERRNO(entry.inode, Atoi(fields[13])); + ASSIGN_OR_RETURN_ERRNO(entry.uid, Atoi(fields[11])); + ASSIGN_OR_RETURN_ERRNO(entry.inode, Atoi(fields[13])); entries.push_back(entry); } @@ -476,7 +476,7 @@ TEST(ProcNetTCP6, State) { ASSERT_NO_ERRNO_AND_VALUE(Accept(server->get(), nullptr, nullptr)); const struct in6_addr* local = IP6FromInetSockaddr(addr); - const uint16 accepted_local_port = PortFromInetSockaddr(addr); + const uint16_t accepted_local_port = PortFromInetSockaddr(addr); entries = ASSERT_NO_ERRNO_AND_VALUE(ProcNetTCP6Entries()); TCP6Entry accepted_entry; diff --git a/test/syscalls/linux/proc_net_udp.cc b/test/syscalls/linux/proc_net_udp.cc index 98c1e0cf1..786b4b4af 100644 --- a/test/syscalls/linux/proc_net_udp.cc +++ b/test/syscalls/linux/proc_net_udp.cc @@ -40,15 +40,15 @@ constexpr char kProcNetUDPHeader[] = // UDPEntry represents a single entry from /proc/net/udp. struct UDPEntry { - uint32 local_addr; - uint16 local_port; + uint32_t local_addr; + uint16_t local_port; - uint32 remote_addr; - uint16 remote_port; + uint32_t remote_addr; + uint16_t remote_port; - uint64 state; - uint64 uid; - uint64 inode; + uint64_t state; + uint64_t uid; + uint64_t inode; }; std::string DescribeFirstInetSocket(const SocketPair& sockets) { @@ -81,8 +81,8 @@ bool FindBy(const std::vector& entries, UDPEntry* match, bool FindByLocalAddr(const std::vector& entries, UDPEntry* match, const struct sockaddr* addr) { - uint32 host = IPFromInetSockaddr(addr); - uint16 port = PortFromInetSockaddr(addr); + uint32_t host = IPFromInetSockaddr(addr); + uint16_t port = PortFromInetSockaddr(addr); return FindBy(entries, match, [host, port](const UDPEntry& e) { return (e.local_addr == host && e.local_port == port); }); @@ -90,14 +90,14 @@ bool FindByLocalAddr(const std::vector& entries, UDPEntry* match, bool FindByRemoteAddr(const std::vector& entries, UDPEntry* match, const struct sockaddr* addr) { - uint32 host = IPFromInetSockaddr(addr); - uint16 port = PortFromInetSockaddr(addr); + uint32_t host = IPFromInetSockaddr(addr); + uint16_t port = PortFromInetSockaddr(addr); return FindBy(entries, match, [host, port](const UDPEntry& e) { return (e.remote_addr == host && e.remote_port == port); }); } -PosixErrorOr InodeFromSocketFD(int fd) { +PosixErrorOr InodeFromSocketFD(int fd) { ASSIGN_OR_RETURN_ERRNO(struct stat s, Fstat(fd)); if (!S_ISSOCK(s.st_mode)) { return PosixError(EINVAL, StrFormat("FD %d is not a socket", fd)); @@ -107,7 +107,7 @@ PosixErrorOr InodeFromSocketFD(int fd) { PosixErrorOr FindByFD(const std::vector& entries, UDPEntry* match, int fd) { - ASSIGN_OR_RETURN_ERRNO(uint64 inode, InodeFromSocketFD(fd)); + ASSIGN_OR_RETURN_ERRNO(uint64_t inode, InodeFromSocketFD(fd)); return FindBy(entries, match, [inode](const UDPEntry& e) { return (e.inode == inode); }); } @@ -158,8 +158,8 @@ PosixErrorOr> ProcNetUDPEntries() { ASSIGN_OR_RETURN_ERRNO(entry.remote_port, AtoiBase(fields[4], 16)); ASSIGN_OR_RETURN_ERRNO(entry.state, AtoiBase(fields[5], 16)); - ASSIGN_OR_RETURN_ERRNO(entry.uid, Atoi(fields[11])); - ASSIGN_OR_RETURN_ERRNO(entry.inode, Atoi(fields[13])); + ASSIGN_OR_RETURN_ERRNO(entry.uid, Atoi(fields[11])); + ASSIGN_OR_RETURN_ERRNO(entry.inode, Atoi(fields[13])); // Linux shares internal data structures between TCP and UDP sockets. The // proc entries for UDP sockets share some fields with TCP sockets, but @@ -267,7 +267,7 @@ TEST(ProcNetUDP, BoundEntry) { struct sockaddr addr; socklen_t len = sizeof(addr); ASSERT_THAT(getsockname(socket->get(), &addr, &len), SyscallSucceeds()); - uint16 port = PortFromInetSockaddr(&addr); + uint16_t port = PortFromInetSockaddr(&addr); std::vector entries = ASSERT_NO_ERRNO_AND_VALUE(ProcNetUDPEntries()); diff --git a/test/syscalls/linux/proc_net_unix.cc b/test/syscalls/linux/proc_net_unix.cc index 2fe63f215..66db0acaa 100644 --- a/test/syscalls/linux/proc_net_unix.cc +++ b/test/syscalls/linux/proc_net_unix.cc @@ -46,12 +46,12 @@ enum { // UnixEntry represents a single entry from /proc/net/unix. struct UnixEntry { uintptr_t addr; - uint64 refs; - uint64 protocol; - uint64 flags; - uint64 type; - uint64 state; - uint64 inode; + uint64_t refs; + uint64_t protocol; + uint64_t flags; + uint64_t type; + uint64_t state; + uint64_t inode; std::string path; }; diff --git a/test/syscalls/linux/proc_pid_uid_gid_map.cc b/test/syscalls/linux/proc_pid_uid_gid_map.cc index 8e268ebd1..748f7be58 100644 --- a/test/syscalls/linux/proc_pid_uid_gid_map.cc +++ b/test/syscalls/linux/proc_pid_uid_gid_map.cc @@ -117,13 +117,13 @@ void DenyPidSetgroups(pid_t pid) { } // Returns a valid UID/GID that isn't id. -uint32 another_id(uint32 id) { return (id + 1) % 65535; } +uint32_t another_id(uint32_t id) { return (id + 1) % 65535; } struct TestParam { std::string desc; int cap; std::function get_map_filename; - std::function get_current_id; + std::function get_current_id; }; std::string DescribeTestParam(const ::testing::TestParamInfo& info) { @@ -135,17 +135,17 @@ std::vector UidGidMapTestParams() { [](absl::string_view pid) { return absl::StrCat("/proc/", pid, "/uid_map"); }, - []() -> uint32 { return getuid(); }}, + []() -> uint32_t { return getuid(); }}, TestParam{"GID", CAP_SETGID, [](absl::string_view pid) { return absl::StrCat("/proc/", pid, "/gid_map"); }, - []() -> uint32 { return getgid(); }}}; + []() -> uint32_t { return getgid(); }}}; } class ProcUidGidMapTest : public ::testing::TestWithParam { protected: - uint32 CurrentID() { return GetParam().get_current_id(); } + uint32_t CurrentID() { return GetParam().get_current_id(); } }; class ProcSelfUidGidMapTest : public ProcUidGidMapTest { @@ -198,7 +198,7 @@ TEST_P(ProcSelfUidGidMapTest, IsInitiallyEmpty) { TEST_P(ProcSelfUidGidMapTest, IdentityMapOwnID) { SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(CanCreateUserNamespace())); - uint32 id = CurrentID(); + uint32_t id = CurrentID(); std::string line = absl::StrCat(id, " ", id, " 1"); EXPECT_THAT( InNewUserNamespaceWithMapFD([&](int fd) { @@ -213,7 +213,7 @@ TEST_P(ProcSelfUidGidMapTest, TrailingNewlineAndNULIgnored) { // and an invalid (incomplete) map entry are appended to the valid entry. The // newline should be accepted, and everything after the NUL should be ignored. SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(CanCreateUserNamespace())); - uint32 id = CurrentID(); + uint32_t id = CurrentID(); std::string line = absl::StrCat(id, " ", id, " 1\n\0 4 3"); EXPECT_THAT( InNewUserNamespaceWithMapFD([&](int fd) { @@ -227,8 +227,8 @@ TEST_P(ProcSelfUidGidMapTest, TrailingNewlineAndNULIgnored) { TEST_P(ProcSelfUidGidMapTest, NonIdentityMapOwnID) { SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(CanCreateUserNamespace())); - uint32 id = CurrentID(); - uint32 id2 = another_id(id); + uint32_t id = CurrentID(); + uint32_t id2 = another_id(id); std::string line = absl::StrCat(id2, " ", id, " 1"); EXPECT_THAT( InNewUserNamespaceWithMapFD([&](int fd) { @@ -243,8 +243,8 @@ TEST_P(ProcSelfUidGidMapTest, MapOtherID) { // Whether or not we have CAP_SET*ID is irrelevant: the process running in the // new (child) user namespace won't have any capabilities in the current // (parent) user namespace, which is needed. - uint32 id = CurrentID(); - uint32 id2 = another_id(id); + uint32_t id = CurrentID(); + uint32_t id2 = another_id(id); std::string line = absl::StrCat(id, " ", id2, " 1"); EXPECT_THAT(InNewUserNamespaceWithMapFD([&](int fd) { DenySelfSetgroups(); @@ -270,8 +270,8 @@ TEST_P(ProcPidUidGidMapTest, MapOtherIDPrivileged) { std::tie(child_pid, cleanup_child) = ASSERT_NO_ERRNO_AND_VALUE(CreateProcessInNewUserNamespace()); - uint32 id = CurrentID(); - uint32 id2 = another_id(id); + uint32_t id = CurrentID(); + uint32_t id2 = another_id(id); std::string line = absl::StrCat(id, " ", id2, " 1"); DenyPidSetgroups(child_pid); auto fd = ASSERT_NO_ERRNO_AND_VALUE(OpenMapFile(child_pid)); diff --git a/test/syscalls/linux/ptrace.cc b/test/syscalls/linux/ptrace.cc index 37dabb1ad..8f3800380 100644 --- a/test/syscalls/linux/ptrace.cc +++ b/test/syscalls/linux/ptrace.cc @@ -574,7 +574,7 @@ TEST_P(PtraceExecveTest, Execve_GetRegs_PeekUser_SIGKILL_TraceClone_TraceExit) { #ifdef __x86_64__ { // CS should be 0x33, indicating an 64-bit binary. - constexpr uint64 kAMD64UserCS = 0x33; + constexpr uint64_t kAMD64UserCS = 0x33; EXPECT_THAT(ptrace(PTRACE_PEEKUSER, leader_tid, offsetof(struct user_regs_struct, cs), 0), SyscallSucceedsWithValue(kAMD64UserCS)); @@ -862,7 +862,7 @@ TEST(PtraceTest, Int3) { TEST(PtraceTest, Sysemu_PokeUser) { constexpr int kSysemuHelperFirstExitCode = 126; - constexpr uint64 kSysemuInjectedExitGroupReturn = 42; + constexpr uint64_t kSysemuInjectedExitGroupReturn = 42; pid_t const child_pid = fork(); if (child_pid == 0) { diff --git a/test/syscalls/linux/pty.cc b/test/syscalls/linux/pty.cc index 5020372c1..dafe64d20 100644 --- a/test/syscalls/linux/pty.cc +++ b/test/syscalls/linux/pty.cc @@ -109,13 +109,13 @@ constexpr bool IsControlCharacter(char c) { return c <= 31; } struct Field { const char* name; - uint64 mask; - uint64 value; + uint64_t mask; + uint64_t value; }; // ParseFields returns a string representation of value, using the names in // fields. -std::string ParseFields(const Field* fields, size_t len, uint64 value) { +std::string ParseFields(const Field* fields, size_t len, uint64_t value) { bool first = true; std::string s; for (size_t i = 0; i < len; i++) { @@ -1213,8 +1213,8 @@ TEST_F(PtyTest, GetWindowSize) { } TEST_F(PtyTest, SetSlaveWindowSize) { - constexpr uint16 kRows = 343; - constexpr uint16 kCols = 2401; + constexpr uint16_t kRows = 343; + constexpr uint16_t kCols = 2401; struct winsize ws = {.ws_row = kRows, .ws_col = kCols}; ASSERT_THAT(ioctl(slave_.get(), TIOCSWINSZ, &ws), SyscallSucceeds()); @@ -1226,8 +1226,8 @@ TEST_F(PtyTest, SetSlaveWindowSize) { } TEST_F(PtyTest, SetMasterWindowSize) { - constexpr uint16 kRows = 343; - constexpr uint16 kCols = 2401; + constexpr uint16_t kRows = 343; + constexpr uint16_t kCols = 2401; struct winsize ws = {.ws_row = kRows, .ws_col = kCols}; ASSERT_THAT(ioctl(master_.get(), TIOCSWINSZ, &ws), SyscallSucceeds()); diff --git a/test/syscalls/linux/pwrite64.cc b/test/syscalls/linux/pwrite64.cc index 18f847929..b48fe540d 100644 --- a/test/syscalls/linux/pwrite64.cc +++ b/test/syscalls/linux/pwrite64.cc @@ -52,7 +52,7 @@ class Pwrite64 : public ::testing::Test { TEST_F(Pwrite64, AppendOnly) { int fd; ASSERT_THAT(fd = open(name_.c_str(), O_APPEND | O_RDWR), SyscallSucceeds()); - constexpr int64 kBufSize = 1024; + constexpr int64_t kBufSize = 1024; std::vector buf(kBufSize); std::fill(buf.begin(), buf.end(), 'a'); EXPECT_THAT(PwriteFd(fd, buf.data(), buf.size(), 0), @@ -64,7 +64,7 @@ TEST_F(Pwrite64, AppendOnly) { TEST_F(Pwrite64, InvalidArgs) { int fd; ASSERT_THAT(fd = open(name_.c_str(), O_APPEND | O_RDWR), SyscallSucceeds()); - constexpr int64 kBufSize = 1024; + constexpr int64_t kBufSize = 1024; std::vector buf(kBufSize); std::fill(buf.begin(), buf.end(), 'a'); EXPECT_THAT(PwriteFd(fd, buf.data(), buf.size(), -1), diff --git a/test/syscalls/linux/raw_socket_hdrincl.cc b/test/syscalls/linux/raw_socket_hdrincl.cc index 0c04b974e..0a27506aa 100644 --- a/test/syscalls/linux/raw_socket_hdrincl.cc +++ b/test/syscalls/linux/raw_socket_hdrincl.cc @@ -53,7 +53,7 @@ class RawHDRINCL : public ::testing::Test { // Fills in buf with an IP header, UDP header, and payload. Returns false if // buf_size isn't large enough to hold everything. bool FillPacket(char* buf, size_t buf_size, int port, const char* payload, - uint16 payload_size); + uint16_t payload_size); // The socket used for both reading and writing. int socket_; @@ -104,7 +104,7 @@ struct iphdr RawHDRINCL::LoopbackHeader() { } bool RawHDRINCL::FillPacket(char* buf, size_t buf_size, int port, - const char* payload, uint16 payload_size) { + const char* payload, uint16_t payload_size) { if (buf_size < sizeof(struct iphdr) + sizeof(struct udphdr) + payload_size) { return false; } diff --git a/test/syscalls/linux/rseq.cc b/test/syscalls/linux/rseq.cc index 9b2a76b91..106c045e3 100644 --- a/test/syscalls/linux/rseq.cc +++ b/test/syscalls/linux/rseq.cc @@ -43,7 +43,7 @@ namespace { // only be cleared by execve (or knowing the old rseq address), and glibc (based // on the current unmerged patches) register rseq before calling main()). -int RSeq(struct rseq* rseq, uint32 rseq_len, int flags, uint32 sig) { +int RSeq(struct rseq* rseq, uint32_t rseq_len, int flags, uint32_t sig) { return syscall(kRseqSyscall, rseq, rseq_len, flags, sig); } diff --git a/test/syscalls/linux/rseq/critical.h b/test/syscalls/linux/rseq/critical.h index 238143fd0..ac987a25e 100644 --- a/test/syscalls/linux/rseq/critical.h +++ b/test/syscalls/linux/rseq/critical.h @@ -18,7 +18,7 @@ #include "test/syscalls/linux/rseq/types.h" #include "test/syscalls/linux/rseq/uapi.h" -constexpr uint32 kRseqSignature = 0x90909090; +constexpr uint32_t kRseqSignature = 0x90909090; extern "C" { diff --git a/test/syscalls/linux/rseq/rseq.cc b/test/syscalls/linux/rseq/rseq.cc index 4fe7c5ecf..f036db26d 100644 --- a/test/syscalls/linux/rseq/rseq.cc +++ b/test/syscalls/linux/rseq/rseq.cc @@ -49,7 +49,7 @@ int strcmp(const char* s1, const char* s2) { return static_cast(*p1) - static_cast(*p2); } -int sys_rseq(struct rseq* rseq, uint32 rseq_len, int flags, uint32 sig) { +int sys_rseq(struct rseq* rseq, uint32_t rseq_len, int flags, uint32_t sig) { return raw_syscall(kRseqSyscall, rseq, rseq_len, flags, sig); } @@ -176,10 +176,10 @@ int TestAbort() { struct rseq_cs cs = {}; cs.version = 0; cs.flags = 0; - cs.start_ip = reinterpret_cast(&rseq_loop_start); - cs.post_commit_offset = reinterpret_cast(&rseq_loop_post_commit) - - reinterpret_cast(&rseq_loop_start); - cs.abort_ip = reinterpret_cast(&rseq_loop_abort); + cs.start_ip = reinterpret_cast(&rseq_loop_start); + cs.post_commit_offset = reinterpret_cast(&rseq_loop_post_commit) - + reinterpret_cast(&rseq_loop_start); + cs.abort_ip = reinterpret_cast(&rseq_loop_abort); // Loops until abort. If this returns then abort occurred. rseq_loop(&r, &cs); @@ -198,10 +198,10 @@ int TestAbortBefore() { struct rseq_cs cs = {}; cs.version = 0; cs.flags = 0; - cs.start_ip = reinterpret_cast(&rseq_loop_start); - cs.post_commit_offset = reinterpret_cast(&rseq_loop_post_commit) - - reinterpret_cast(&rseq_loop_start); - cs.abort_ip = reinterpret_cast(&rseq_loop_early_abort); + cs.start_ip = reinterpret_cast(&rseq_loop_start); + cs.post_commit_offset = reinterpret_cast(&rseq_loop_post_commit) - + reinterpret_cast(&rseq_loop_start); + cs.abort_ip = reinterpret_cast(&rseq_loop_early_abort); // Loops until abort. If this returns then abort occurred. rseq_loop(&r, &cs); @@ -220,10 +220,10 @@ int TestAbortSignature() { struct rseq_cs cs = {}; cs.version = 0; cs.flags = 0; - cs.start_ip = reinterpret_cast(&rseq_loop_start); - cs.post_commit_offset = reinterpret_cast(&rseq_loop_post_commit) - - reinterpret_cast(&rseq_loop_start); - cs.abort_ip = reinterpret_cast(&rseq_loop_abort); + cs.start_ip = reinterpret_cast(&rseq_loop_start); + cs.post_commit_offset = reinterpret_cast(&rseq_loop_post_commit) - + reinterpret_cast(&rseq_loop_start); + cs.abort_ip = reinterpret_cast(&rseq_loop_abort); // Loops until abort. This should SIGSEGV on abort. rseq_loop(&r, &cs); @@ -242,10 +242,10 @@ int TestAbortPreCommit() { struct rseq_cs cs = {}; cs.version = 0; cs.flags = 0; - cs.start_ip = reinterpret_cast(&rseq_loop_start); - cs.post_commit_offset = reinterpret_cast(&rseq_loop_post_commit) - - reinterpret_cast(&rseq_loop_start); - cs.abort_ip = reinterpret_cast(&rseq_loop_pre_commit); + cs.start_ip = reinterpret_cast(&rseq_loop_start); + cs.post_commit_offset = reinterpret_cast(&rseq_loop_post_commit) - + reinterpret_cast(&rseq_loop_start); + cs.abort_ip = reinterpret_cast(&rseq_loop_pre_commit); // Loops until abort. This should SIGSEGV on abort. rseq_loop(&r, &cs); @@ -264,10 +264,10 @@ int TestAbortClearsCS() { struct rseq_cs cs = {}; cs.version = 0; cs.flags = 0; - cs.start_ip = reinterpret_cast(&rseq_loop_start); - cs.post_commit_offset = reinterpret_cast(&rseq_loop_post_commit) - - reinterpret_cast(&rseq_loop_start); - cs.abort_ip = reinterpret_cast(&rseq_loop_abort); + cs.start_ip = reinterpret_cast(&rseq_loop_start); + cs.post_commit_offset = reinterpret_cast(&rseq_loop_post_commit) - + reinterpret_cast(&rseq_loop_start); + cs.abort_ip = reinterpret_cast(&rseq_loop_abort); // Loops until abort. If this returns then abort occurred. rseq_loop(&r, &cs); @@ -290,10 +290,10 @@ int TestInvalidAbortClearsCS() { struct rseq_cs cs = {}; cs.version = 0; cs.flags = 0; - cs.start_ip = reinterpret_cast(&rseq_loop_start); - cs.post_commit_offset = reinterpret_cast(&rseq_loop_post_commit) - - reinterpret_cast(&rseq_loop_start); - cs.abort_ip = reinterpret_cast(&rseq_loop_abort); + cs.start_ip = reinterpret_cast(&rseq_loop_start); + cs.post_commit_offset = reinterpret_cast(&rseq_loop_post_commit) - + reinterpret_cast(&rseq_loop_start); + cs.abort_ip = reinterpret_cast(&rseq_loop_abort); __atomic_store_n(&r.rseq_cs, &cs, __ATOMIC_RELAXED); diff --git a/test/syscalls/linux/rseq/types.h b/test/syscalls/linux/rseq/types.h index 7f1e0c5c2..b6afe9817 100644 --- a/test/syscalls/linux/rseq/types.h +++ b/test/syscalls/linux/rseq/types.h @@ -18,14 +18,14 @@ using size_t = __SIZE_TYPE__; using uintptr_t = __UINTPTR_TYPE__; -using uint8 = __UINT8_TYPE__; -using uint16 = __UINT16_TYPE__; -using uint32 = __UINT32_TYPE__; -using uint64 = __UINT64_TYPE__; +using uint8_t = __UINT8_TYPE__; +using uint16_t = __UINT16_TYPE__; +using uint32_t = __UINT32_TYPE__; +using uint64_t = __UINT64_TYPE__; -using int8 = __INT8_TYPE__; -using int16 = __INT16_TYPE__; -using int32 = __INT32_TYPE__; -using int64 = __INT64_TYPE__; +using int8_t = __INT8_TYPE__; +using int16_t = __INT16_TYPE__; +using int32_t = __INT32_TYPE__; +using int64_t = __INT64_TYPE__; #endif // GVISOR_TEST_SYSCALLS_LINUX_RSEQ_TYPES_H_ diff --git a/test/syscalls/linux/seccomp.cc b/test/syscalls/linux/seccomp.cc index 7a2c1191a..7e41fe7d8 100644 --- a/test/syscalls/linux/seccomp.cc +++ b/test/syscalls/linux/seccomp.cc @@ -49,12 +49,12 @@ namespace testing { namespace { // A syscall not implemented by Linux that we don't expect to be called. -constexpr uint32 kFilteredSyscall = SYS_vserver; +constexpr uint32_t kFilteredSyscall = SYS_vserver; // Applies a seccomp-bpf filter that returns `filtered_result` for // `sysno` and allows all other syscalls. Async-signal-safe. -void ApplySeccompFilter(uint32 sysno, uint32 filtered_result, - uint32 flags = 0) { +void ApplySeccompFilter(uint32_t sysno, uint32_t filtered_result, + uint32_t flags = 0) { // "Prior to [PR_SET_SECCOMP], the task must call prctl(PR_SET_NO_NEW_PRIVS, // 1) or run with CAP_SYS_ADMIN privileges in its namespace." - // Documentation/prctl/seccomp_filter.txt @@ -162,7 +162,7 @@ TEST(SeccompTest, RetKillOnlyKillsOneThread) { TEST(SeccompTest, RetTrapCausesSIGSYS) { pid_t const pid = fork(); if (pid == 0) { - constexpr uint16 kTrapValue = 0xdead; + constexpr uint16_t kTrapValue = 0xdead; RegisterSignalHandler( SIGSYS, +[](int signo, siginfo_t* info, void* ucv) { ucontext_t* uc = static_cast(ucv); @@ -191,7 +191,7 @@ TEST(SeccompTest, RetTrapCausesSIGSYS) { #ifdef __x86_64__ -constexpr uint64 kVsyscallTimeEntry = 0xffffffffff600400; +constexpr uint64_t kVsyscallTimeEntry = 0xffffffffff600400; time_t vsyscall_time(time_t* t) { return reinterpret_cast(kVsyscallTimeEntry)(t); @@ -202,7 +202,7 @@ TEST(SeccompTest, SeccompAppliesToVsyscall) { pid_t const pid = fork(); if (pid == 0) { - constexpr uint16 kTrapValue = 0xdead; + constexpr uint16_t kTrapValue = 0xdead; RegisterSignalHandler( SIGSYS, +[](int signo, siginfo_t* info, void* ucv) { ucontext_t* uc = static_cast(ucv); @@ -335,7 +335,7 @@ TEST(SeccompTest, TsyncAppliesToAllThreads) { // This test will validate that seccomp(2) rejects unsupported flags. TEST(SeccompTest, SeccompRejectsUnknownFlags) { - constexpr uint32 kInvalidFlag = 123; + constexpr uint32_t kInvalidFlag = 123; ASSERT_THAT( syscall(__NR_seccomp, SECCOMP_SET_MODE_FILTER, kInvalidFlag, nullptr), SyscallFailsWithErrno(EINVAL)); diff --git a/test/syscalls/linux/semaphore.cc b/test/syscalls/linux/semaphore.cc index a9e8a44c1..e9b131ca9 100644 --- a/test/syscalls/linux/semaphore.cc +++ b/test/syscalls/linux/semaphore.cc @@ -274,7 +274,7 @@ TEST(SemaphoreTest, SemOpRandom) { // Protects the seed below. absl::Mutex mutex; - uint32 seed = time(nullptr); + uint32_t seed = time(nullptr); int count = 0; // Tracks semaphore value. bool done = false; // Tells waiters to stop after signal threads are done. @@ -284,7 +284,7 @@ TEST(SemaphoreTest, SemOpRandom) { for (auto& dec : decs) { dec = absl::make_unique([&sem, &mutex, &count, &seed, &done] { for (size_t i = 0; i < 500; ++i) { - int16 val; + int16_t val; { absl::MutexLock l(&mutex); if (done) { @@ -325,7 +325,7 @@ TEST(SemaphoreTest, SemOpRandom) { for (auto& inc : incs) { inc = absl::make_unique([&sem, &mutex, &count, &seed] { for (size_t i = 0; i < 500; ++i) { - int16 val; + int16_t val; { absl::MutexLock l(&mutex); val = (rand_r(&seed) % 10 + 1); // Rand between 1 and 10. @@ -415,14 +415,14 @@ TEST(SemaphoreTest, SemCtlValAll) { ASSERT_THAT(sem.get(), SyscallSucceeds()); // Semaphores must start with 0. - uint16 get[3] = {10, 10, 10}; + uint16_t get[3] = {10, 10, 10}; EXPECT_THAT(semctl(sem.get(), 1, GETALL, get), SyscallSucceedsWithValue(0)); for (auto v : get) { EXPECT_EQ(v, 0); } // SetAll and check that they were set. - uint16 vals[3] = {0, 10, 20}; + uint16_t vals[3] = {0, 10, 20}; EXPECT_THAT(semctl(sem.get(), 1, SETALL, vals), SyscallSucceedsWithValue(0)); EXPECT_THAT(semctl(sem.get(), 1, GETALL, get), SyscallSucceedsWithValue(0)); for (size_t i = 0; i < ABSL_ARRAYSIZE(vals); ++i) { diff --git a/test/syscalls/linux/shm.cc b/test/syscalls/linux/shm.cc index 80700615f..7ba752599 100644 --- a/test/syscalls/linux/shm.cc +++ b/test/syscalls/linux/shm.cc @@ -30,7 +30,7 @@ namespace { using ::testing::_; -const uint64 kAllocSize = kPageSize * 128ULL; +const uint64_t kAllocSize = kPageSize * 128ULL; PosixErrorOr Shmat(int shmid, const void* shmaddr, int shmflg) { const intptr_t addr = @@ -320,11 +320,11 @@ TEST(ShmTest, RemovedSegmentsAreDestroyed) { Shmget(IPC_PRIVATE, kAllocSize, IPC_CREAT | 0777)); const char* addr = ASSERT_NO_ERRNO_AND_VALUE(Shmat(shm.id(), nullptr, 0)); - const uint64 alloc_pages = kAllocSize / kPageSize; + const uint64_t alloc_pages = kAllocSize / kPageSize; struct shm_info info; ASSERT_NO_ERRNO(Shmctl(0 /*ignored*/, SHM_INFO, &info)); - const uint64 before = info.shm_tot; + const uint64_t before = info.shm_tot; ASSERT_NO_ERRNO(shm.Rmid()); ASSERT_NO_ERRNO(Shmdt(addr)); @@ -400,7 +400,7 @@ TEST(ShmDeathTest, SegmentNotAccessibleAfterDetach) { TEST(ShmTest, RequestingSegmentSmallerThanSHMMINFails) { struct shminfo info; ASSERT_NO_ERRNO(Shmctl(0, IPC_INFO, &info)); - const uint64 size = info.shmmin - 1; + const uint64_t size = info.shmmin - 1; EXPECT_THAT(Shmget(IPC_PRIVATE, size, IPC_CREAT | 0777), PosixErrorIs(EINVAL, _)); } @@ -408,7 +408,7 @@ TEST(ShmTest, RequestingSegmentSmallerThanSHMMINFails) { TEST(ShmTest, RequestingSegmentLargerThanSHMMAXFails) { struct shminfo info; ASSERT_NO_ERRNO(Shmctl(0, IPC_INFO, &info)); - const uint64 size = info.shmmax + kPageSize; + const uint64_t size = info.shmmax + kPageSize; EXPECT_THAT(Shmget(IPC_PRIVATE, size, IPC_CREAT | 0777), PosixErrorIs(EINVAL, _)); } diff --git a/test/syscalls/linux/sigaltstack.cc b/test/syscalls/linux/sigaltstack.cc index 9a0816e10..62b04ef1d 100644 --- a/test/syscalls/linux/sigaltstack.cc +++ b/test/syscalls/linux/sigaltstack.cc @@ -114,7 +114,7 @@ TEST(SigaltstackTest, ResetByExecve) { volatile bool badhandler_on_sigaltstack = true; // Set by the handler. char* volatile badhandler_low_water_mark = nullptr; // Set by the handler. -volatile uint8 badhandler_recursive_faults = 0; // Consumed by the handler. +volatile uint8_t badhandler_recursive_faults = 0; // Consumed by the handler. void badhandler(int sig, siginfo_t* siginfo, void* arg) { char stack_var = 0; diff --git a/test/syscalls/linux/sigiret.cc b/test/syscalls/linux/sigiret.cc index 207506569..a47c781ea 100644 --- a/test/syscalls/linux/sigiret.cc +++ b/test/syscalls/linux/sigiret.cc @@ -28,8 +28,8 @@ namespace testing { namespace { -constexpr uint64 kOrigRcx = 0xdeadbeeffacefeed; -constexpr uint64 kOrigR11 = 0xfacefeedbaad1dea; +constexpr uint64_t kOrigRcx = 0xdeadbeeffacefeed; +constexpr uint64_t kOrigR11 = 0xfacefeedbaad1dea; volatile int gotvtalrm, ready; @@ -40,8 +40,8 @@ void sigvtalrm(int sig, siginfo_t* siginfo, void* _uc) { // - test is in the busy-wait loop waiting for signal. // - %rcx and %r11 values in mcontext_t match kOrigRcx and kOrigR11. if (ready && - static_cast(uc->uc_mcontext.gregs[REG_RCX]) == kOrigRcx && - static_cast(uc->uc_mcontext.gregs[REG_R11]) == kOrigR11) { + static_cast(uc->uc_mcontext.gregs[REG_RCX]) == kOrigRcx && + static_cast(uc->uc_mcontext.gregs[REG_R11]) == kOrigR11) { // Modify the values %rcx and %r11 in the ucontext. These are the // values seen by the application after the signal handler returns. uc->uc_mcontext.gregs[REG_RCX] = ~kOrigRcx; @@ -69,8 +69,8 @@ TEST(SigIretTest, CheckRcxR11) { ASSERT_NO_ERRNO_AND_VALUE(ScopedItimer(ITIMER_VIRTUAL, itimer)); // Initialize %rcx and %r11 and spin until the signal handler returns. - uint64 rcx = kOrigRcx; - uint64 r11 = kOrigR11; + uint64_t rcx = kOrigRcx; + uint64_t r11 = kOrigR11; asm volatile( "movq %[rcx], %%rcx;" // %rcx = rcx "movq %[r11], %%r11;" // %r11 = r11 @@ -91,7 +91,7 @@ TEST(SigIretTest, CheckRcxR11) { EXPECT_EQ(r11, ~kOrigR11); } -constexpr uint64 kNonCanonicalRip = 0xCCCC000000000000; +constexpr uint64_t kNonCanonicalRip = 0xCCCC000000000000; // Test that a non-canonical signal handler faults as expected. TEST(SigIretTest, BadHandler) { diff --git a/test/syscalls/linux/socket_bind_to_device_distribution.cc b/test/syscalls/linux/socket_bind_to_device_distribution.cc index c705da1b4..5ed57625c 100644 --- a/test/syscalls/linux/socket_bind_to_device_distribution.cc +++ b/test/syscalls/linux/socket_bind_to_device_distribution.cc @@ -77,13 +77,13 @@ class BindToDeviceDistributionTest } }; -PosixErrorOr AddrPort(int family, sockaddr_storage const& addr) { +PosixErrorOr AddrPort(int family, sockaddr_storage const& addr) { switch (family) { case AF_INET: - return static_cast( + return static_cast( reinterpret_cast(&addr)->sin_port); case AF_INET6: - return static_cast( + return static_cast( reinterpret_cast(&addr)->sin6_port); default: return PosixError(EINVAL, @@ -91,7 +91,7 @@ PosixErrorOr AddrPort(int family, sockaddr_storage const& addr) { } } -PosixError SetAddrPort(int family, sockaddr_storage* addr, uint16 port) { +PosixError SetAddrPort(int family, sockaddr_storage* addr, uint16_t port) { switch (family) { case AF_INET: reinterpret_cast(addr)->sin_port = port; @@ -157,7 +157,7 @@ TEST_P(BindToDeviceDistributionTest, Tcp) { getsockname(listener_fds[0].get(), reinterpret_cast(&listen_addr), &addrlen), SyscallSucceeds()); - uint16 const port = + uint16_t const port = ASSERT_NO_ERRNO_AND_VALUE(AddrPort(listener.family(), listen_addr)); ASSERT_NO_ERRNO(SetAddrPort(connector.family(), &conn_addr, port)); } @@ -190,7 +190,7 @@ TEST_P(BindToDeviceDistributionTest, Tcp) { // cause the test to use absurd amounts of memory. // // See: https://tools.ietf.org/html/rfc2525#page-50 section 2.17 - uint16 data; + uint16_t data; EXPECT_THAT( RetryEINTR(recv)(fd.ValueOrDie().get(), &data, sizeof(data), 0), SyscallSucceedsWithValue(sizeof(data))); @@ -296,7 +296,7 @@ TEST_P(BindToDeviceDistributionTest, Udp) { getsockname(listener_fds[0].get(), reinterpret_cast(&listen_addr), &addrlen), SyscallSucceeds()); - uint16 const port = + uint16_t const port = ASSERT_NO_ERRNO_AND_VALUE(AddrPort(listener.family(), listen_addr)); ASSERT_NO_ERRNO(SetAddrPort(listener.family(), &listen_addr, port)); ASSERT_NO_ERRNO(SetAddrPort(connector.family(), &conn_addr, port)); diff --git a/test/syscalls/linux/socket_generic.cc b/test/syscalls/linux/socket_generic.cc index ee9856f7f..e8f24a59e 100644 --- a/test/syscalls/linux/socket_generic.cc +++ b/test/syscalls/linux/socket_generic.cc @@ -507,7 +507,7 @@ TEST_P(AllSocketPairTest, SoRcvTimeoIsSetLargerArg) { struct timeval_with_extra { struct timeval tv; - int64 extra_data; + int64_t extra_data; } ABSL_ATTRIBUTE_PACKED; timeval_with_extra tv_extra; diff --git a/test/syscalls/linux/socket_inet_loopback.cc b/test/syscalls/linux/socket_inet_loopback.cc index 12df2b35a..2f9821555 100644 --- a/test/syscalls/linux/socket_inet_loopback.cc +++ b/test/syscalls/linux/socket_inet_loopback.cc @@ -47,13 +47,13 @@ namespace { using ::testing::Gt; -PosixErrorOr AddrPort(int family, sockaddr_storage const& addr) { +PosixErrorOr AddrPort(int family, sockaddr_storage const& addr) { switch (family) { case AF_INET: - return static_cast( + return static_cast( reinterpret_cast(&addr)->sin_port); case AF_INET6: - return static_cast( + return static_cast( reinterpret_cast(&addr)->sin6_port); default: return PosixError(EINVAL, @@ -61,7 +61,7 @@ PosixErrorOr AddrPort(int family, sockaddr_storage const& addr) { } } -PosixError SetAddrPort(int family, sockaddr_storage* addr, uint16 port) { +PosixError SetAddrPort(int family, sockaddr_storage* addr, uint16_t port) { switch (family) { case AF_INET: reinterpret_cast(addr)->sin_port = port; @@ -276,7 +276,7 @@ void tcpSimpleConnectTest(TestAddress const& listener, ASSERT_THAT(getsockname(listen_fd.get(), reinterpret_cast(&listen_addr), &addrlen), SyscallSucceeds()); - uint16 const port = + uint16_t const port = ASSERT_NO_ERRNO_AND_VALUE(AddrPort(listener.family(), listen_addr)); // Connect to the listening socket. @@ -339,7 +339,7 @@ TEST_P(SocketInetLoopbackTest, TCPListenClose) { ASSERT_THAT(getsockname(listen_fd.get(), reinterpret_cast(&listen_addr), &addrlen), SyscallSucceeds()); - uint16 const port = + uint16_t const port = ASSERT_NO_ERRNO_AND_VALUE(AddrPort(listener.family(), listen_addr)); DisableSave ds; // Too many system calls. @@ -400,7 +400,7 @@ TEST_P(SocketInetLoopbackTest, TCPbacklog) { ASSERT_THAT(getsockname(listen_fd.get(), reinterpret_cast(&listen_addr), &addrlen), SyscallSucceeds()); - uint16 const port = + uint16_t const port = ASSERT_NO_ERRNO_AND_VALUE(AddrPort(listener.family(), listen_addr)); int i = 0; while (1) { @@ -468,7 +468,7 @@ TEST_P(SocketInetLoopbackTest, TCPFinWait2Test_NoRandomSave) { reinterpret_cast(&listen_addr), &addrlen), SyscallSucceeds()); - uint16 const port = + uint16_t const port = ASSERT_NO_ERRNO_AND_VALUE(AddrPort(listener.family(), listen_addr)); // Connect to the listening socket. @@ -576,7 +576,7 @@ TEST_P(SocketInetLoopbackTest, TCPLinger2TimeoutAfterClose_NoRandomSave) { reinterpret_cast(&listen_addr), &addrlen), SyscallSucceeds()); - uint16 const port = + uint16_t const port = ASSERT_NO_ERRNO_AND_VALUE(AddrPort(listener.family(), listen_addr)); // Connect to the listening socket. @@ -650,7 +650,7 @@ TEST_P(SocketInetLoopbackTest, TCPResetAfterClose) { reinterpret_cast(&listen_addr), &addrlen), SyscallSucceeds()); - uint16 const port = + uint16_t const port = ASSERT_NO_ERRNO_AND_VALUE(AddrPort(listener.family(), listen_addr)); // Connect to the listening socket. @@ -717,7 +717,7 @@ TEST_P(SocketInetLoopbackTest, TCPTimeWaitTest_NoRandomSave) { reinterpret_cast(&listen_addr), &addrlen), SyscallSucceeds()); - uint16 const port = + uint16_t const port = ASSERT_NO_ERRNO_AND_VALUE(AddrPort(listener.family(), listen_addr)); // Connect to the listening socket. @@ -794,7 +794,7 @@ TEST_P(SocketInetLoopbackTest, AcceptedInheritsTCPUserTimeout) { reinterpret_cast(&listen_addr), &addrlen), SyscallSucceeds()); - const uint16 port = + const uint16_t port = ASSERT_NO_ERRNO_AND_VALUE(AddrPort(listener.family(), listen_addr)); // Set the userTimeout on the listening socket. @@ -898,7 +898,7 @@ TEST_P(SocketInetReusePortTest, TcpPortReuseMultiThread_NoRandomSave) { getsockname(listener_fds[0].get(), reinterpret_cast(&listen_addr), &addrlen), SyscallSucceeds()); - uint16 const port = + uint16_t const port = ASSERT_NO_ERRNO_AND_VALUE(AddrPort(listener.family(), listen_addr)); ASSERT_NO_ERRNO(SetAddrPort(listener.family(), &listen_addr, port)); ASSERT_NO_ERRNO(SetAddrPort(connector.family(), &conn_addr, port)); @@ -935,7 +935,7 @@ TEST_P(SocketInetReusePortTest, TcpPortReuseMultiThread_NoRandomSave) { // cause the test to use absurd amounts of memory. // // See: https://tools.ietf.org/html/rfc2525#page-50 section 2.17 - uint16 data; + uint16_t data; EXPECT_THAT( RetryEINTR(recv)(fd.ValueOrDie().get(), &data, sizeof(data), 0), SyscallSucceedsWithValue(sizeof(data))); @@ -1022,7 +1022,7 @@ TEST_P(SocketInetReusePortTest, UdpPortReuseMultiThread) { getsockname(listener_fds[0].get(), reinterpret_cast(&listen_addr), &addrlen), SyscallSucceeds()); - uint16 const port = + uint16_t const port = ASSERT_NO_ERRNO_AND_VALUE(AddrPort(listener.family(), listen_addr)); ASSERT_NO_ERRNO(SetAddrPort(listener.family(), &listen_addr, port)); ASSERT_NO_ERRNO(SetAddrPort(connector.family(), &conn_addr, port)); @@ -1138,7 +1138,7 @@ TEST_P(SocketInetReusePortTest, UdpPortReuseMultiThreadShort) { getsockname(listener_fds[0].get(), reinterpret_cast(&listen_addr), &addrlen), SyscallSucceeds()); - uint16 const port = + uint16_t const port = ASSERT_NO_ERRNO_AND_VALUE(AddrPort(listener.family(), listen_addr)); ASSERT_NO_ERRNO(SetAddrPort(listener.family(), &listen_addr, port)); ASSERT_NO_ERRNO(SetAddrPort(connector.family(), &conn_addr, port)); @@ -1174,7 +1174,7 @@ TEST_P(SocketInetReusePortTest, UdpPortReuseMultiThreadShort) { pollfds[i].events = POLLIN; } - std::map portToFD; + std::map portToFD; int received = 0; while (received < kConnectAttempts * 2) { @@ -1196,7 +1196,7 @@ TEST_P(SocketInetReusePortTest, UdpPortReuseMultiThreadShort) { fd, &data, sizeof(data), 0, reinterpret_cast(&addr), &addrlen), SyscallSucceedsWithValue(sizeof(data))); - uint16 const port = + uint16_t const port = ASSERT_NO_ERRNO_AND_VALUE(AddrPort(connector.family(), addr)); auto prev_port = portToFD.find(port); // Check that all packets from one client have been delivered to the @@ -1257,7 +1257,7 @@ TEST_P(SocketMultiProtocolInetLoopbackTest, V4MappedLoopbackOnlyReservesV4) { ASSERT_THAT(getsockname(fd_dual.get(), reinterpret_cast(&addr_dual), &addrlen), SyscallSucceeds()); - uint16 const port = + uint16_t const port = ASSERT_NO_ERRNO_AND_VALUE(AddrPort(test_addr_dual.family(), addr_dual)); // Verify that we can still bind the v6 loopback on the same port. @@ -1309,7 +1309,7 @@ TEST_P(SocketMultiProtocolInetLoopbackTest, V4MappedAnyOnlyReservesV4) { ASSERT_THAT(getsockname(fd_dual.get(), reinterpret_cast(&addr_dual), &addrlen), SyscallSucceeds()); - uint16 const port = + uint16_t const port = ASSERT_NO_ERRNO_AND_VALUE(AddrPort(test_addr_dual.family(), addr_dual)); // Verify that we can still bind the v6 loopback on the same port. @@ -1360,7 +1360,7 @@ TEST_P(SocketMultiProtocolInetLoopbackTest, DualStackV6AnyReservesEverything) { ASSERT_THAT(getsockname(fd_dual.get(), reinterpret_cast(&addr_dual), &addrlen), SyscallSucceeds()); - uint16 const port = + uint16_t const port = ASSERT_NO_ERRNO_AND_VALUE(AddrPort(test_addr_dual.family(), addr_dual)); // Verify that binding the v6 loopback with the same port fails. @@ -1419,7 +1419,7 @@ TEST_P(SocketMultiProtocolInetLoopbackTest, V6OnlyV6AnyReservesV6) { ASSERT_THAT(getsockname(fd_dual.get(), reinterpret_cast(&addr_dual), &addrlen), SyscallSucceeds()); - uint16 const port = + uint16_t const port = ASSERT_NO_ERRNO_AND_VALUE(AddrPort(test_addr_dual.family(), addr_dual)); // Verify that binding the v6 loopback with the same port fails. @@ -1498,7 +1498,7 @@ TEST_P(SocketMultiProtocolInetLoopbackTest, V6EphemeralPortReserved) { reinterpret_cast(&connected_addr), &connected_addr_len), SyscallSucceeds()); - uint16 const ephemeral_port = + uint16_t const ephemeral_port = ASSERT_NO_ERRNO_AND_VALUE(AddrPort(test_addr.family(), connected_addr)); // Verify that we actually got an ephemeral port. @@ -1603,7 +1603,7 @@ TEST_P(SocketMultiProtocolInetLoopbackTest, V6EphemeralPortReservedReuseAddr) { reinterpret_cast(&connected_addr), &connected_addr_len), SyscallSucceeds()); - uint16 const ephemeral_port = + uint16_t const ephemeral_port = ASSERT_NO_ERRNO_AND_VALUE(AddrPort(test_addr.family(), connected_addr)); // Verify that we actually got an ephemeral port. @@ -1665,7 +1665,7 @@ TEST_P(SocketMultiProtocolInetLoopbackTest, V4MappedEphemeralPortReserved) { reinterpret_cast(&connected_addr), &connected_addr_len), SyscallSucceeds()); - uint16 const ephemeral_port = + uint16_t const ephemeral_port = ASSERT_NO_ERRNO_AND_VALUE(AddrPort(test_addr.family(), connected_addr)); // Verify that we actually got an ephemeral port. @@ -1794,7 +1794,7 @@ TEST_P(SocketMultiProtocolInetLoopbackTest, reinterpret_cast(&connected_addr), &connected_addr_len), SyscallSucceeds()); - uint16 const ephemeral_port = + uint16_t const ephemeral_port = ASSERT_NO_ERRNO_AND_VALUE(AddrPort(test_addr.family(), connected_addr)); // Verify that we actually got an ephemeral port. @@ -1856,7 +1856,7 @@ TEST_P(SocketMultiProtocolInetLoopbackTest, V4EphemeralPortReserved) { reinterpret_cast(&connected_addr), &connected_addr_len), SyscallSucceeds()); - uint16 const ephemeral_port = + uint16_t const ephemeral_port = ASSERT_NO_ERRNO_AND_VALUE(AddrPort(test_addr.family(), connected_addr)); // Verify that we actually got an ephemeral port. @@ -1988,7 +1988,7 @@ TEST_P(SocketMultiProtocolInetLoopbackTest, V4EphemeralPortReservedReuseAddr) { reinterpret_cast(&connected_addr), &connected_addr_len), SyscallSucceeds()); - uint16 const ephemeral_port = + uint16_t const ephemeral_port = ASSERT_NO_ERRNO_AND_VALUE(AddrPort(test_addr.family(), connected_addr)); // Verify that we actually got an ephemeral port. diff --git a/test/syscalls/linux/socket_ip_unbound.cc b/test/syscalls/linux/socket_ip_unbound.cc index 4a8337159..ca597e267 100644 --- a/test/syscalls/linux/socket_ip_unbound.cc +++ b/test/syscalls/linux/socket_ip_unbound.cc @@ -223,7 +223,7 @@ TEST_P(IPUnboundSocketTest, CheckSkipECN) { TOSOption t = GetTOSOption(GetParam().domain); EXPECT_THAT(setsockopt(socket->get(), t.level, t.option, &set, set_sz), SyscallSucceedsWithValue(0)); - int expect = static_cast(set); + int expect = static_cast(set); if (GetParam().protocol == IPPROTO_TCP) { expect &= ~INET_ECN_MASK; } @@ -267,7 +267,7 @@ TEST_P(IPUnboundSocketTest, SmallTOSOptionSize) { EXPECT_THAT(setsockopt(socket->get(), t.level, t.option, &set, i), SyscallSucceedsWithValue(0)); expect_tos = set; - expect_sz = sizeof(uint8); + expect_sz = sizeof(uint8_t); } else { EXPECT_THAT(setsockopt(socket->get(), t.level, t.option, &set, i), SyscallFailsWithErrno(EINVAL)); @@ -314,7 +314,7 @@ TEST_P(IPUnboundSocketTest, NegativeTOS) { SyscallSucceedsWithValue(0)); int expect; if (GetParam().domain == AF_INET) { - expect = static_cast(set); + expect = static_cast(set); if (GetParam().protocol == IPPROTO_TCP) { expect &= ~INET_ECN_MASK; } @@ -340,7 +340,7 @@ TEST_P(IPUnboundSocketTest, InvalidNegativeTOS) { if (GetParam().domain == AF_INET) { EXPECT_THAT(setsockopt(socket->get(), t.level, t.option, &set, set_sz), SyscallSucceedsWithValue(0)); - expect = static_cast(set); + expect = static_cast(set); if (GetParam().protocol == IPPROTO_TCP) { expect &= ~INET_ECN_MASK; } diff --git a/test/syscalls/linux/socket_netdevice.cc b/test/syscalls/linux/socket_netdevice.cc index 689014a59..405dbbd73 100644 --- a/test/syscalls/linux/socket_netdevice.cc +++ b/test/syscalls/linux/socket_netdevice.cc @@ -70,14 +70,14 @@ TEST(NetdeviceTest, Netmask) { // netmask obtained via ioctl. FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(NetlinkBoundSocket(NETLINK_ROUTE)); - uint32 port = ASSERT_NO_ERRNO_AND_VALUE(NetlinkPortID(fd.get())); + uint32_t port = ASSERT_NO_ERRNO_AND_VALUE(NetlinkPortID(fd.get())); struct request { struct nlmsghdr hdr; struct rtgenmsg rgm; }; - constexpr uint32 kSeq = 12345; + constexpr uint32_t kSeq = 12345; struct request req; req.hdr.nlmsg_len = sizeof(req); @@ -109,7 +109,7 @@ TEST(NetdeviceTest, Netmask) { struct ifaddrmsg *ifaddrmsg = reinterpret_cast(NLMSG_DATA(hdr)); - if (ifaddrmsg->ifa_index == static_cast(ifr.ifr_ifindex) && + if (ifaddrmsg->ifa_index == static_cast(ifr.ifr_ifindex) && ifaddrmsg->ifa_family == AF_INET) { prefixlen = ifaddrmsg->ifa_prefixlen; } @@ -120,7 +120,7 @@ TEST(NetdeviceTest, Netmask) { // Netmask is stored big endian in struct sockaddr_in, so we do the same for // comparison. - uint32 mask = 0xffffffff << (32 - prefixlen); + uint32_t mask = 0xffffffff << (32 - prefixlen); mask = absl::gbswap_32(mask); // Check that the loopback interface has the correct subnet mask. diff --git a/test/syscalls/linux/socket_netlink_route.cc b/test/syscalls/linux/socket_netlink_route.cc index 5612f1a13..ef567f512 100644 --- a/test/syscalls/linux/socket_netlink_route.cc +++ b/test/syscalls/linux/socket_netlink_route.cc @@ -116,14 +116,14 @@ void CheckGetLinkResponse(const struct nlmsghdr* hdr, int seq, int port) { TEST(NetlinkRouteTest, GetLinkDump) { FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(NetlinkBoundSocket(NETLINK_ROUTE)); - uint32 port = ASSERT_NO_ERRNO_AND_VALUE(NetlinkPortID(fd.get())); + uint32_t port = ASSERT_NO_ERRNO_AND_VALUE(NetlinkPortID(fd.get())); struct request { struct nlmsghdr hdr; struct ifinfomsg ifm; }; - constexpr uint32 kSeq = 12345; + constexpr uint32_t kSeq = 12345; struct request req = {}; req.hdr.nlmsg_len = sizeof(req); @@ -164,7 +164,7 @@ TEST(NetlinkRouteTest, MsgHdrMsgUnsuppType) { struct ifinfomsg ifm; }; - constexpr uint32 kSeq = 12345; + constexpr uint32_t kSeq = 12345; struct request req = {}; req.hdr.nlmsg_len = sizeof(req); @@ -198,7 +198,7 @@ TEST(NetlinkRouteTest, MsgHdrMsgTrunc) { struct ifinfomsg ifm; }; - constexpr uint32 kSeq = 12345; + constexpr uint32_t kSeq = 12345; struct request req = {}; req.hdr.nlmsg_len = sizeof(req); @@ -238,7 +238,7 @@ TEST(NetlinkRouteTest, MsgTruncMsgHdrMsgTrunc) { struct ifinfomsg ifm; }; - constexpr uint32 kSeq = 12345; + constexpr uint32_t kSeq = 12345; struct request req = {}; req.hdr.nlmsg_len = sizeof(req); @@ -274,7 +274,7 @@ TEST(NetlinkRouteTest, MsgTruncMsgHdrMsgTrunc) { TEST(NetlinkRouteTest, ControlMessageIgnored) { FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(NetlinkBoundSocket(NETLINK_ROUTE)); - uint32 port = ASSERT_NO_ERRNO_AND_VALUE(NetlinkPortID(fd.get())); + uint32_t port = ASSERT_NO_ERRNO_AND_VALUE(NetlinkPortID(fd.get())); struct request { struct nlmsghdr control_hdr; @@ -282,7 +282,7 @@ TEST(NetlinkRouteTest, ControlMessageIgnored) { struct ifinfomsg ifm; }; - constexpr uint32 kSeq = 12345; + constexpr uint32_t kSeq = 12345; struct request req = {}; @@ -310,14 +310,14 @@ TEST(NetlinkRouteTest, ControlMessageIgnored) { TEST(NetlinkRouteTest, GetAddrDump) { FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(NetlinkBoundSocket(NETLINK_ROUTE)); - uint32 port = ASSERT_NO_ERRNO_AND_VALUE(NetlinkPortID(fd.get())); + uint32_t port = ASSERT_NO_ERRNO_AND_VALUE(NetlinkPortID(fd.get())); struct request { struct nlmsghdr hdr; struct rtgenmsg rgm; }; - constexpr uint32 kSeq = 12345; + constexpr uint32_t kSeq = 12345; struct request req; req.hdr.nlmsg_len = sizeof(req); @@ -371,14 +371,14 @@ TEST(NetlinkRouteTest, LookupAll) { TEST(NetlinkRouteTest, GetRouteDump) { FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(NetlinkBoundSocket(NETLINK_ROUTE)); - uint32 port = ASSERT_NO_ERRNO_AND_VALUE(NetlinkPortID(fd.get())); + uint32_t port = ASSERT_NO_ERRNO_AND_VALUE(NetlinkPortID(fd.get())); struct request { struct nlmsghdr hdr; struct rtmsg rtm; }; - constexpr uint32 kSeq = 12345; + constexpr uint32_t kSeq = 12345; struct request req = {}; req.hdr.nlmsg_len = sizeof(req); @@ -454,7 +454,7 @@ TEST(NetlinkRouteTest, RecvmsgTrunc) { struct rtgenmsg rgm; }; - constexpr uint32 kSeq = 12345; + constexpr uint32_t kSeq = 12345; struct request req; req.hdr.nlmsg_len = sizeof(req); @@ -531,7 +531,7 @@ TEST(NetlinkRouteTest, RecvmsgTruncPeek) { struct rtgenmsg rgm; }; - constexpr uint32 kSeq = 12345; + constexpr uint32_t kSeq = 12345; struct request req; req.hdr.nlmsg_len = sizeof(req); @@ -611,7 +611,7 @@ TEST(NetlinkRouteTest, NoPasscredNoCreds) { struct rtgenmsg rgm; }; - constexpr uint32 kSeq = 12345; + constexpr uint32_t kSeq = 12345; struct request req; req.hdr.nlmsg_len = sizeof(req); @@ -659,7 +659,7 @@ TEST(NetlinkRouteTest, PasscredCreds) { struct rtgenmsg rgm; }; - constexpr uint32 kSeq = 12345; + constexpr uint32_t kSeq = 12345; struct request req; req.hdr.nlmsg_len = sizeof(req); diff --git a/test/syscalls/linux/socket_netlink_util.cc b/test/syscalls/linux/socket_netlink_util.cc index 17f99c238..723f5d728 100644 --- a/test/syscalls/linux/socket_netlink_util.cc +++ b/test/syscalls/linux/socket_netlink_util.cc @@ -40,7 +40,7 @@ PosixErrorOr NetlinkBoundSocket(int protocol) { return std::move(fd); } -PosixErrorOr NetlinkPortID(int fd) { +PosixErrorOr NetlinkPortID(int fd) { struct sockaddr_nl addr; socklen_t addrlen = sizeof(addr); @@ -48,7 +48,7 @@ PosixErrorOr NetlinkPortID(int fd) { getsockname(fd, reinterpret_cast(&addr), &addrlen)); MaybeSave(); - return static_cast(addr.nl_pid); + return static_cast(addr.nl_pid); } PosixError NetlinkRequestResponse( diff --git a/test/syscalls/linux/socket_netlink_util.h b/test/syscalls/linux/socket_netlink_util.h index bd0c1d79b..76e772c48 100644 --- a/test/syscalls/linux/socket_netlink_util.h +++ b/test/syscalls/linux/socket_netlink_util.h @@ -30,7 +30,7 @@ namespace testing { PosixErrorOr NetlinkBoundSocket(int protocol); // Returns the port ID of the passed socket. -PosixErrorOr NetlinkPortID(int fd); +PosixErrorOr NetlinkPortID(int fd); // Send the passed request and call fn will all response netlink messages. PosixError NetlinkRequestResponse( diff --git a/test/syscalls/linux/socket_test_util.cc b/test/syscalls/linux/socket_test_util.cc index 2169ff1c6..eff7d577e 100644 --- a/test/syscalls/linux/socket_test_util.cc +++ b/test/syscalls/linux/socket_test_util.cc @@ -507,7 +507,7 @@ void TransferTest(int fd1, int fd2) { // Initializes the given buffer with random data. void RandomizeBuffer(char* ptr, size_t len) { - uint32 seed = time(nullptr); + uint32_t seed = time(nullptr); for (size_t i = 0; i < len; ++i) { ptr[i] = static_cast(rand_r(&seed)); } diff --git a/test/syscalls/linux/splice.cc b/test/syscalls/linux/splice.cc index 562b6a8d4..85232cb1f 100644 --- a/test/syscalls/linux/splice.cc +++ b/test/syscalls/linux/splice.cc @@ -139,7 +139,7 @@ TEST(SpliceTest, PipeOffsets) { // Event FDs may be used with splice without an offset. TEST(SpliceTest, FromEventFD) { // Open the input eventfd with an initial value so that it is readable. - constexpr uint64 kEventFDValue = 1; + constexpr uint64_t kEventFDValue = 1; int efd; ASSERT_THAT(efd = eventfd(kEventFDValue, 0), SyscallSucceeds()); const FileDescriptor in_fd(efd); diff --git a/test/syscalls/linux/stat.cc b/test/syscalls/linux/stat.cc index 6b259cb89..30de2f8ff 100644 --- a/test/syscalls/linux/stat.cc +++ b/test/syscalls/linux/stat.cc @@ -568,35 +568,35 @@ TEST(SimpleStatTest, AnonDeviceAllocatesUniqueInodesAcrossSaveRestore) { // struct kernel_statx_timestamp is a Linux statx_timestamp struct. struct kernel_statx_timestamp { - int64 tv_sec; - uint32 tv_nsec; - int32 __reserved; + int64_t tv_sec; + uint32_t tv_nsec; + int32_t __reserved; }; // struct kernel_statx is a Linux statx struct. Old versions of glibc do not // expose it. See include/uapi/linux/stat.h struct kernel_statx { - uint32 stx_mask; - uint32 stx_blksize; - uint64 stx_attributes; - uint32 stx_nlink; - uint32 stx_uid; - uint32 stx_gid; - uint16 stx_mode; - uint16 __spare0[1]; - uint64 stx_ino; - uint64 stx_size; - uint64 stx_blocks; - uint64 stx_attributes_mask; + uint32_t stx_mask; + uint32_t stx_blksize; + uint64_t stx_attributes; + uint32_t stx_nlink; + uint32_t stx_uid; + uint32_t stx_gid; + uint16_t stx_mode; + uint16_t __spare0[1]; + uint64_t stx_ino; + uint64_t stx_size; + uint64_t stx_blocks; + uint64_t stx_attributes_mask; struct kernel_statx_timestamp stx_atime; struct kernel_statx_timestamp stx_btime; struct kernel_statx_timestamp stx_ctime; struct kernel_statx_timestamp stx_mtime; - uint32 stx_rdev_major; - uint32 stx_rdev_minor; - uint32 stx_dev_major; - uint32 stx_dev_minor; - uint64 __spare2[14]; + uint32_t stx_rdev_major; + uint32_t stx_rdev_minor; + uint32_t stx_dev_major; + uint32_t stx_dev_minor; + uint64_t __spare2[14]; }; int statx(int dirfd, const char *pathname, int flags, unsigned int mask, diff --git a/test/syscalls/linux/sticky.cc b/test/syscalls/linux/sticky.cc index abcabaffb..7e73325bf 100644 --- a/test/syscalls/linux/sticky.cc +++ b/test/syscalls/linux/sticky.cc @@ -29,8 +29,8 @@ #include "test/util/test_util.h" #include "test/util/thread_util.h" -ABSL_FLAG(int32, scratch_uid, 65534, "first scratch UID"); -ABSL_FLAG(int32, scratch_gid, 65534, "first scratch GID"); +ABSL_FLAG(int32_t, scratch_uid, 65534, "first scratch UID"); +ABSL_FLAG(int32_t, scratch_gid, 65534, "first scratch GID"); namespace gvisor { namespace testing { diff --git a/test/syscalls/linux/sysret.cc b/test/syscalls/linux/sysret.cc index d98d6be91..819fa655a 100644 --- a/test/syscalls/linux/sysret.cc +++ b/test/syscalls/linux/sysret.cc @@ -26,8 +26,8 @@ namespace testing { namespace { -constexpr uint64 kNonCanonicalRip = 0xCCCC000000000000; -constexpr uint64 kNonCanonicalRsp = 0xFFFF000000000000; +constexpr uint64_t kNonCanonicalRip = 0xCCCC000000000000; +constexpr uint64_t kNonCanonicalRsp = 0xFFFF000000000000; class SysretTest : public ::testing::Test { protected: @@ -60,12 +60,12 @@ class SysretTest : public ::testing::Test { ASSERT_THAT(ptrace(PTRACE_DETACH, child_, 0, 0), SyscallSucceeds()); } - void SetRip(uint64 newrip) { + void SetRip(uint64_t newrip) { regs_.rip = newrip; ASSERT_THAT(ptrace(PTRACE_SETREGS, child_, 0, ®s_), SyscallSucceeds()); } - void SetRsp(uint64 newrsp) { + void SetRsp(uint64_t newrsp) { regs_.rsp = newrsp; ASSERT_THAT(ptrace(PTRACE_SETREGS, child_, 0, ®s_), SyscallSucceeds()); } diff --git a/test/syscalls/linux/tcp_socket.cc b/test/syscalls/linux/tcp_socket.cc index cb304d6f5..33a5ac66c 100644 --- a/test/syscalls/linux/tcp_socket.cc +++ b/test/syscalls/linux/tcp_socket.cc @@ -640,7 +640,7 @@ TEST_P(TcpSocketTest, Tiocinq) { size_t size = sizeof(buf); ASSERT_THAT(RetryEINTR(write)(s_, buf, size), SyscallSucceedsWithValue(size)); - uint32 seed = time(nullptr); + uint32_t seed = time(nullptr); const size_t max_chunk = size / 10; while (size > 0) { size_t chunk = (rand_r(&seed) % max_chunk) + 1; diff --git a/test/syscalls/linux/time.cc b/test/syscalls/linux/time.cc index 03e028f50..c7eead17e 100644 --- a/test/syscalls/linux/time.cc +++ b/test/syscalls/linux/time.cc @@ -28,7 +28,7 @@ constexpr long kFudgeSeconds = 5; // Mimics the time(2) wrapper from glibc prior to 2.15. time_t vsyscall_time(time_t* t) { - constexpr uint64 kVsyscallTimeEntry = 0xffffffffff600400; + constexpr uint64_t kVsyscallTimeEntry = 0xffffffffff600400; return reinterpret_cast(kVsyscallTimeEntry)(t); } @@ -63,7 +63,7 @@ TEST(TimeTest, VsyscallTime_InvalidAddressSIGSEGV) { } int vsyscall_gettimeofday(struct timeval* tv, struct timezone* tz) { - constexpr uint64 kVsyscallGettimeofdayEntry = 0xffffffffff600000; + constexpr uint64_t kVsyscallGettimeofdayEntry = 0xffffffffff600000; return reinterpret_cast( kVsyscallGettimeofdayEntry)(tv, tz); } diff --git a/test/syscalls/linux/timerfd.cc b/test/syscalls/linux/timerfd.cc index d87dbc666..86ed87b7c 100644 --- a/test/syscalls/linux/timerfd.cc +++ b/test/syscalls/linux/timerfd.cc @@ -69,9 +69,9 @@ TEST_P(TimerfdTest, SingleShot) { // The timer should fire exactly once since the interval is zero. absl::SleepFor(kDelay + TimerSlack()); - uint64 val = 0; - ASSERT_THAT(ReadFd(tfd.get(), &val, sizeof(uint64)), - SyscallSucceedsWithValue(sizeof(uint64))); + uint64_t val = 0; + ASSERT_THAT(ReadFd(tfd.get(), &val, sizeof(uint64_t)), + SyscallSucceedsWithValue(sizeof(uint64_t))); EXPECT_EQ(1, val); } @@ -89,9 +89,9 @@ TEST_P(TimerfdTest, Periodic) { // Expect to see at least kPeriods expirations. More may occur due to the // timer slack, or due to delays from scheduling or save/restore. absl::SleepFor(kPeriods * kDelay + TimerSlack()); - uint64 val = 0; - ASSERT_THAT(ReadFd(tfd.get(), &val, sizeof(uint64)), - SyscallSucceedsWithValue(sizeof(uint64))); + uint64_t val = 0; + ASSERT_THAT(ReadFd(tfd.get(), &val, sizeof(uint64_t)), + SyscallSucceedsWithValue(sizeof(uint64_t))); EXPECT_GE(val, kPeriods); } @@ -106,9 +106,9 @@ TEST_P(TimerfdTest, BlockingRead) { SyscallSucceeds()); // read should block until the timer fires. - uint64 val = 0; - ASSERT_THAT(ReadFd(tfd.get(), &val, sizeof(uint64)), - SyscallSucceedsWithValue(sizeof(uint64))); + uint64_t val = 0; + ASSERT_THAT(ReadFd(tfd.get(), &val, sizeof(uint64_t)), + SyscallSucceedsWithValue(sizeof(uint64_t))); auto const end_time = absl::Now(); EXPECT_EQ(1, val); EXPECT_GE((end_time - start_time) + TimerSlack(), kDelay); @@ -122,8 +122,8 @@ TEST_P(TimerfdTest, NonblockingRead_NoRandomSave) { // Since the timer is initially disabled and has never fired, read should // return EAGAIN. - uint64 val = 0; - ASSERT_THAT(ReadFd(tfd.get(), &val, sizeof(uint64)), + uint64_t val = 0; + ASSERT_THAT(ReadFd(tfd.get(), &val, sizeof(uint64_t)), SyscallFailsWithErrno(EAGAIN)); DisableSave ds; // Timing-sensitive. @@ -135,19 +135,19 @@ TEST_P(TimerfdTest, NonblockingRead_NoRandomSave) { SyscallSucceeds()); // Since the timer has not yet fired, read should return EAGAIN. - ASSERT_THAT(ReadFd(tfd.get(), &val, sizeof(uint64)), + ASSERT_THAT(ReadFd(tfd.get(), &val, sizeof(uint64_t)), SyscallFailsWithErrno(EAGAIN)); ds.reset(); // No longer timing-sensitive. // After the timer fires, read should indicate 1 expiration. absl::SleepFor(kDelay + TimerSlack()); - ASSERT_THAT(ReadFd(tfd.get(), &val, sizeof(uint64)), - SyscallSucceedsWithValue(sizeof(uint64))); + ASSERT_THAT(ReadFd(tfd.get(), &val, sizeof(uint64_t)), + SyscallSucceedsWithValue(sizeof(uint64_t))); EXPECT_EQ(1, val); // The successful read should have reset the number of expirations. - ASSERT_THAT(ReadFd(tfd.get(), &val, sizeof(uint64)), + ASSERT_THAT(ReadFd(tfd.get(), &val, sizeof(uint64_t)), SyscallFailsWithErrno(EAGAIN)); } @@ -179,8 +179,8 @@ TEST_P(TimerfdTest, BlockingPoll_SetTimeResetsExpirations) { its.it_value.tv_sec = 0; ASSERT_THAT(timerfd_settime(tfd.get(), /* flags = */ 0, &its, nullptr), SyscallSucceeds()); - uint64 val = 0; - ASSERT_THAT(ReadFd(tfd.get(), &val, sizeof(uint64)), + uint64_t val = 0; + ASSERT_THAT(ReadFd(tfd.get(), &val, sizeof(uint64_t)), SyscallFailsWithErrno(EAGAIN)); } @@ -198,16 +198,16 @@ TEST_P(TimerfdTest, SetAbsoluteTime) { SyscallSucceeds()); absl::SleepFor(kDelay + TimerSlack()); - uint64 val = 0; - ASSERT_THAT(ReadFd(tfd.get(), &val, sizeof(uint64)), - SyscallSucceedsWithValue(sizeof(uint64))); + uint64_t val = 0; + ASSERT_THAT(ReadFd(tfd.get(), &val, sizeof(uint64_t)), + SyscallSucceedsWithValue(sizeof(uint64_t))); EXPECT_EQ(1, val); } TEST_P(TimerfdTest, IllegalReadWrite) { auto const tfd = ASSERT_NO_ERRNO_AND_VALUE(TimerfdCreate(GetParam(), TFD_NONBLOCK)); - uint64 val = 0; + uint64_t val = 0; EXPECT_THAT(PreadFd(tfd.get(), &val, sizeof(val), 0), SyscallFailsWithErrno(ESPIPE)); EXPECT_THAT(WriteFd(tfd.get(), &val, sizeof(val)), @@ -244,9 +244,9 @@ TEST(TimerfdClockRealtimeTest, ClockRealtime) { ASSERT_THAT(timerfd_settime(tfd.get(), /* flags = */ 0, &its, nullptr), SyscallSucceeds()); - uint64 val = 0; - ASSERT_THAT(ReadFd(tfd.get(), &val, sizeof(uint64)), - SyscallSucceedsWithValue(sizeof(uint64))); + uint64_t val = 0; + ASSERT_THAT(ReadFd(tfd.get(), &val, sizeof(uint64_t)), + SyscallSucceedsWithValue(sizeof(uint64_t))); EXPECT_EQ(1, val); } diff --git a/test/syscalls/linux/udp_socket_test_cases.cc b/test/syscalls/linux/udp_socket_test_cases.cc index af94d7baa..a2f6ef8cc 100644 --- a/test/syscalls/linux/udp_socket_test_cases.cc +++ b/test/syscalls/linux/udp_socket_test_cases.cc @@ -34,7 +34,7 @@ namespace gvisor { namespace testing { // Gets a pointer to the port component of the given address. -uint16* Port(struct sockaddr_storage* addr) { +uint16_t* Port(struct sockaddr_storage* addr) { switch (addr->ss_family) { case AF_INET: { auto sin = reinterpret_cast(addr); @@ -331,7 +331,7 @@ TEST_P(UdpSocketTest, Connect) { EXPECT_EQ(memcmp(&peer, addr_[2], addrlen_), 0); } -void ConnectAny(AddressFamily family, int sockfd, uint16 port) { +void ConnectAny(AddressFamily family, int sockfd, uint16_t port) { struct sockaddr_storage addr = {}; // Precondition check. @@ -1398,7 +1398,7 @@ TEST_P(UdpSocketTest, SetAndReceiveTOS) { received_iov.iov_len = kDataLength; received_msg.msg_iov = &received_iov; received_msg.msg_iovlen = 1; - size_t cmsg_data_len = sizeof(int8); + size_t cmsg_data_len = sizeof(int8_t); if (sent_type == IPV6_TCLASS) { cmsg_data_len = sizeof(int); } @@ -1413,7 +1413,7 @@ TEST_P(UdpSocketTest, SetAndReceiveTOS) { EXPECT_EQ(cmsg->cmsg_len, CMSG_LEN(cmsg_data_len)); EXPECT_EQ(cmsg->cmsg_level, sent_level); EXPECT_EQ(cmsg->cmsg_type, sent_type); - int8 received_tos = 0; + int8_t received_tos = 0; memcpy(&received_tos, CMSG_DATA(cmsg), sizeof(received_tos)); EXPECT_EQ(received_tos, sent_tos); } @@ -1453,7 +1453,7 @@ TEST_P(UdpSocketTest, SendAndReceiveTOS) { sent_iov.iov_len = kDataLength; sent_msg.msg_iov = &sent_iov; sent_msg.msg_iovlen = 1; - size_t cmsg_data_len = sizeof(int8); + size_t cmsg_data_len = sizeof(int8_t); if (sent_level == SOL_IPV6) { sent_type = IPV6_TCLASS; cmsg_data_len = sizeof(int); @@ -1467,7 +1467,7 @@ TEST_P(UdpSocketTest, SendAndReceiveTOS) { sent_cmsg->cmsg_len = CMSG_LEN(cmsg_data_len); sent_cmsg->cmsg_level = sent_level; sent_cmsg->cmsg_type = sent_type; - *(int8*)CMSG_DATA(sent_cmsg) = sent_tos; + *(int8_t*)CMSG_DATA(sent_cmsg) = sent_tos; ASSERT_THAT(RetryEINTR(sendmsg)(t_, &sent_msg, 0), SyscallSucceedsWithValue(kDataLength)); @@ -1491,7 +1491,7 @@ TEST_P(UdpSocketTest, SendAndReceiveTOS) { EXPECT_EQ(cmsg->cmsg_len, CMSG_LEN(cmsg_data_len)); EXPECT_EQ(cmsg->cmsg_level, sent_level); EXPECT_EQ(cmsg->cmsg_type, sent_type); - int8 received_tos = 0; + int8_t received_tos = 0; memcpy(&received_tos, CMSG_DATA(cmsg), sizeof(received_tos)); EXPECT_EQ(received_tos, sent_tos); } diff --git a/test/syscalls/linux/uidgid.cc b/test/syscalls/linux/uidgid.cc index e0e39e5e3..6218fbce1 100644 --- a/test/syscalls/linux/uidgid.cc +++ b/test/syscalls/linux/uidgid.cc @@ -27,10 +27,10 @@ #include "test/util/thread_util.h" #include "test/util/uid_util.h" -ABSL_FLAG(int32, scratch_uid1, 65534, "first scratch UID"); -ABSL_FLAG(int32, scratch_uid2, 65533, "second scratch UID"); -ABSL_FLAG(int32, scratch_gid1, 65534, "first scratch GID"); -ABSL_FLAG(int32, scratch_gid2, 65533, "second scratch GID"); +ABSL_FLAG(int32_t, scratch_uid1, 65534, "first scratch UID"); +ABSL_FLAG(int32_t, scratch_uid2, 65533, "second scratch UID"); +ABSL_FLAG(int32_t, scratch_gid1, 65534, "first scratch GID"); +ABSL_FLAG(int32_t, scratch_gid2, 65533, "second scratch GID"); using ::testing::UnorderedElementsAreArray; diff --git a/test/syscalls/linux/utimes.cc b/test/syscalls/linux/utimes.cc index e7bae9c07..3a927a430 100644 --- a/test/syscalls/linux/utimes.cc +++ b/test/syscalls/linux/utimes.cc @@ -163,12 +163,12 @@ TEST(FutimesatTest, OnRelPath) { TEST(FutimesatTest, InvalidNsec) { auto f = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); struct timeval times[4][2] = {{ - {0, 1}, // Valid - {1, static_cast(1e7)} // Invalid + {0, 1}, // Valid + {1, static_cast(1e7)} // Invalid }, { - {1, static_cast(1e7)}, // Invalid - {0, 1} // Valid + {1, static_cast(1e7)}, // Invalid + {0, 1} // Valid }, { {0, 1}, // Valid @@ -288,14 +288,15 @@ TEST(UtimeTest, ZeroAtimeandMtime) { TEST(UtimensatTest, InvalidNsec) { auto f = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); - struct timespec times[2][2] = {{ - {0, UTIME_OMIT}, // Valid - {2, static_cast(1e10)} // Invalid - }, - { - {2, static_cast(1e10)}, // Invalid - {0, UTIME_OMIT} // Valid - }}; + struct timespec times[2][2] = { + { + {0, UTIME_OMIT}, // Valid + {2, static_cast(1e10)} // Invalid + }, + { + {2, static_cast(1e10)}, // Invalid + {0, UTIME_OMIT} // Valid + }}; for (unsigned int i = 0; i < sizeof(times) / sizeof(times[0]); i++) { std::cout << "test:" << i << "\n"; diff --git a/test/syscalls/linux/vfork.cc b/test/syscalls/linux/vfork.cc index 153b3bd69..0aaba482d 100644 --- a/test/syscalls/linux/vfork.cc +++ b/test/syscalls/linux/vfork.cc @@ -51,7 +51,7 @@ constexpr absl::Duration kChildDelay = absl::Seconds(10); // errno, so kChildExitCode is chosen to be an unlikely errno: constexpr int kChildExitCode = 118; // ENOTNAM: Not a XENIX named type file -int64 MonotonicNow() { +int64_t MonotonicNow() { struct timespec now; TEST_PCHECK(clock_gettime(CLOCK_MONOTONIC, &now) == 0); return now.tv_sec * 1000000000ll + now.tv_nsec; @@ -62,7 +62,7 @@ TEST(VforkTest, ParentStopsUntilChildExits) { // N.B. Run the test in a single-threaded subprocess because // vfork is not safe in a multi-threaded process. - const int64 start = MonotonicNow(); + const int64_t start = MonotonicNow(); pid_t pid = vfork(); if (pid == 0) { @@ -72,7 +72,7 @@ TEST(VforkTest, ParentStopsUntilChildExits) { TEST_PCHECK_MSG(pid > 0, "vfork failed"); MaybeSave(); - const int64 end = MonotonicNow(); + const int64_t end = MonotonicNow(); absl::Duration dur = absl::Nanoseconds(end - start); @@ -92,7 +92,7 @@ TEST(VforkTest, ParentStopsUntilChildExecves_NoRandomSave) { char* const* const child_argv = owned_child_argv.get(); const auto test = [&] { - const int64 start = MonotonicNow(); + const int64_t start = MonotonicNow(); pid_t pid = vfork(); if (pid == 0) { @@ -104,7 +104,7 @@ TEST(VforkTest, ParentStopsUntilChildExecves_NoRandomSave) { // since the test expects an upper bound on the time spent // stopped. int saved_errno = errno; - const int64 end = MonotonicNow(); + const int64_t end = MonotonicNow(); errno = saved_errno; TEST_PCHECK_MSG(pid > 0, "vfork failed"); MaybeSave(); @@ -143,7 +143,7 @@ TEST(VforkTest, ExecedChildExitDoesntUnstopParent_NoRandomSave) { // pid1 exec'd and is now sleeping. SleepSafe(kChildDelay / 2); - const int64 start = MonotonicNow(); + const int64_t start = MonotonicNow(); pid_t pid2 = vfork(); if (pid2 == 0) { @@ -153,7 +153,7 @@ TEST(VforkTest, ExecedChildExitDoesntUnstopParent_NoRandomSave) { TEST_PCHECK_MSG(pid2 > 0, "vfork failed"); MaybeSave(); - const int64 end = MonotonicNow(); + const int64_t end = MonotonicNow(); absl::Duration dur = absl::Nanoseconds(end - start); diff --git a/test/syscalls/linux/vsyscall.cc b/test/syscalls/linux/vsyscall.cc index 99e8c6cea..2c2303358 100644 --- a/test/syscalls/linux/vsyscall.cc +++ b/test/syscalls/linux/vsyscall.cc @@ -25,7 +25,7 @@ namespace testing { namespace { time_t vsyscall_time(time_t* t) { - constexpr uint64 kVsyscallTimeEntry = 0xffffffffff600400; + constexpr uint64_t kVsyscallTimeEntry = 0xffffffffff600400; return reinterpret_cast(kVsyscallTimeEntry)(t); } diff --git a/test/syscalls/linux/wait.cc b/test/syscalls/linux/wait.cc index 709b87a21..944149d5e 100644 --- a/test/syscalls/linux/wait.cc +++ b/test/syscalls/linux/wait.cc @@ -64,7 +64,7 @@ static const size_t kStackSize = 2 * kPageSize; // The child thread created in CloneAndExit runs this function. // This child does not have the TLS setup, so it must not use glibc functions. int CloneChild(void* priv) { - int64 sleep = reinterpret_cast(priv); + int64_t sleep = reinterpret_cast(priv); SleepSafe(absl::Seconds(sleep)); // glibc's _exit(2) function wrapper will helpfully call exit_group(2), @@ -75,7 +75,7 @@ int CloneChild(void* priv) { // ForkAndExit forks a child process which exits with exit_code, after // sleeping for the specified duration (seconds). -pid_t ForkAndExit(int exit_code, int64 sleep) { +pid_t ForkAndExit(int exit_code, int64_t sleep) { pid_t child = fork(); if (child == 0) { SleepSafe(absl::Seconds(sleep)); @@ -84,16 +84,16 @@ pid_t ForkAndExit(int exit_code, int64 sleep) { return child; } -int64 clock_gettime_nsecs(clockid_t id) { +int64_t clock_gettime_nsecs(clockid_t id) { struct timespec ts; TEST_PCHECK(clock_gettime(id, &ts) == 0); return (ts.tv_sec * 1000000000 + ts.tv_nsec); } -void spin(int64 sec) { - int64 ns = sec * 1000000000; - int64 start = clock_gettime_nsecs(CLOCK_THREAD_CPUTIME_ID); - int64 end = start + ns; +void spin(int64_t sec) { + int64_t ns = sec * 1000000000; + int64_t start = clock_gettime_nsecs(CLOCK_THREAD_CPUTIME_ID); + int64_t end = start + ns; do { constexpr int kLoopCount = 1000000; // large and arbitrary @@ -105,7 +105,7 @@ void spin(int64 sec) { // ForkSpinAndExit forks a child process which exits with exit_code, after // spinning for the specified duration (seconds). -pid_t ForkSpinAndExit(int exit_code, int64 spintime) { +pid_t ForkSpinAndExit(int exit_code, int64_t spintime) { pid_t child = fork(); if (child == 0) { spin(spintime); @@ -141,7 +141,7 @@ int FreeStack(uintptr_t addr) { // CloneAndExit clones a child thread, which exits with 0 after sleeping for // the specified duration (must be in seconds). extra_flags are ORed against // the standard clone(2) flags. -int CloneAndExit(int64 sleep, uintptr_t stack, int extra_flags) { +int CloneAndExit(int64_t sleep, uintptr_t stack, int extra_flags) { return clone(CloneChild, reinterpret_cast(stack), CLONE_FILES | CLONE_FS | CLONE_SIGHAND | CLONE_VM | extra_flags, reinterpret_cast(sleep)); diff --git a/test/util/mount_util.h b/test/util/mount_util.h index 51119f22f..23eea51a2 100644 --- a/test/util/mount_util.h +++ b/test/util/mount_util.h @@ -33,9 +33,9 @@ namespace testing { // destroyed. inline PosixErrorOr Mount(const std::string &source, const std::string &target, - const std::string &fstype, uint64 mountflags, - const std::string &data, - uint64 umountflags) { + const std::string &fstype, + uint64_t mountflags, const std::string &data, + uint64_t umountflags) { if (mount(source.c_str(), target.c_str(), fstype.c_str(), mountflags, data.c_str()) == -1) { return PosixError(errno, "mount failed"); diff --git a/test/util/multiprocess_util.cc b/test/util/multiprocess_util.cc index ba601f300..8b676751b 100644 --- a/test/util/multiprocess_util.cc +++ b/test/util/multiprocess_util.cc @@ -135,7 +135,7 @@ PosixErrorOr ForkAndExec(const std::string& filename, return ForkAndExecHelper(exec_fn, fn, child, execve_errno); } -PosixErrorOr ForkAndExecveat(const int32 dirfd, +PosixErrorOr ForkAndExecveat(const int32_t dirfd, const std::string& pathname, const ExecveArray& argv, const ExecveArray& envv, const int flags, diff --git a/test/util/multiprocess_util.h b/test/util/multiprocess_util.h index 342e73a52..3e736261b 100644 --- a/test/util/multiprocess_util.h +++ b/test/util/multiprocess_util.h @@ -103,13 +103,14 @@ inline PosixErrorOr ForkAndExec(const std::string& filename, } // Equivalent to ForkAndExec, except using dirfd and flags with execveat. -PosixErrorOr ForkAndExecveat(int32 dirfd, const std::string& pathname, +PosixErrorOr ForkAndExecveat(int32_t dirfd, + const std::string& pathname, const ExecveArray& argv, const ExecveArray& envv, int flags, const std::function& fn, pid_t* child, int* execve_errno); -inline PosixErrorOr ForkAndExecveat(int32 dirfd, +inline PosixErrorOr ForkAndExecveat(int32_t dirfd, const std::string& pathname, const ExecveArray& argv, const ExecveArray& envv, int flags, diff --git a/test/util/proc_util.cc b/test/util/proc_util.cc index c81f363ef..34d636ba9 100644 --- a/test/util/proc_util.cc +++ b/test/util/proc_util.cc @@ -72,7 +72,7 @@ PosixErrorOr ParseProcMapsLine(absl::string_view line) { ASSIGN_OR_RETURN_ERRNO(map_entry.major, AtoiBase(device[0], 16)); ASSIGN_OR_RETURN_ERRNO(map_entry.minor, AtoiBase(device[1], 16)); - ASSIGN_OR_RETURN_ERRNO(map_entry.inode, Atoi(parts[4])); + ASSIGN_OR_RETURN_ERRNO(map_entry.inode, Atoi(parts[4])); if (parts.size() == 6) { // A filename is present. However, absl::StrSplit retained the whitespace // between the inode number and the filename. diff --git a/test/util/temp_path.cc b/test/util/temp_path.cc index f5096dd53..35aacb172 100644 --- a/test/util/temp_path.cc +++ b/test/util/temp_path.cc @@ -32,7 +32,7 @@ namespace testing { namespace { -std::atomic global_temp_file_number = ATOMIC_VAR_INIT(1); +std::atomic global_temp_file_number = ATOMIC_VAR_INIT(1); // Return a new temp filename, intended to be unique system-wide. // diff --git a/test/util/test_util.cc b/test/util/test_util.cc index 51f4b4539..848504c88 100644 --- a/test/util/test_util.cc +++ b/test/util/test_util.cc @@ -79,7 +79,7 @@ bool IsRunningWithHostinet() { #endif // defined(__x86_64__) CPUVendor GetCPUVendor() { - uint32 eax, ebx, ecx, edx; + uint32_t eax, ebx, ecx, edx; std::string vendor_str; // Get vendor string (issue CPUID with eax = 0) GETCPUID(eax, ebx, ecx, edx, 0, 0); @@ -179,36 +179,36 @@ PosixErrorOr> GetOpenFDs() { return ret_fds; } -PosixErrorOr Links(const std::string& path) { +PosixErrorOr Links(const std::string& path) { struct stat st; if (stat(path.c_str(), &st)) { return PosixError(errno, absl::StrCat("Failed to stat ", path)); } - return static_cast(st.st_nlink); + return static_cast(st.st_nlink); } void RandomizeBuffer(void* buffer, size_t len) { struct timespec ts = {}; clock_gettime(CLOCK_MONOTONIC, &ts); - uint32 seed = static_cast(ts.tv_nsec); + uint32_t seed = static_cast(ts.tv_nsec); char* const buf = static_cast(buffer); for (size_t i = 0; i < len; i++) { buf[i] = rand_r(&seed) % 255; } } -std::vector> GenerateIovecs(uint64 total_size, +std::vector> GenerateIovecs(uint64_t total_size, void* buf, size_t buflen) { std::vector> result; - for (uint64 offset = 0; offset < total_size;) { + for (uint64_t offset = 0; offset < total_size;) { auto& iovec_array = *result.emplace(result.end()); for (; offset < total_size && iovec_array.size() < IOV_MAX; offset += buflen) { struct iovec iov = {}; iov.iov_base = buf; - iov.iov_len = std::min(total_size - offset, buflen); + iov.iov_len = std::min(total_size - offset, buflen); iovec_array.push_back(iov); } } @@ -216,15 +216,15 @@ std::vector> GenerateIovecs(uint64 total_size, return result; } -uint64 Megabytes(uint64 n) { +uint64_t Megabytes(uint64_t n) { // Overflow check, upper 20 bits in n shouldn't be set. TEST_CHECK(!(0xfffff00000000000 & n)); return n << 20; } -bool Equivalent(uint64 current, uint64 target, double tolerance) { +bool Equivalent(uint64_t current, uint64_t target, double tolerance) { auto abs_diff = target > current ? target - current : current - target; - return abs_diff <= static_cast(tolerance * target); + return abs_diff <= static_cast(tolerance * target); } } // namespace testing diff --git a/test/util/test_util.h b/test/util/test_util.h index 6eb46ac76..b3235c7e3 100644 --- a/test/util/test_util.h +++ b/test/util/test_util.h @@ -264,7 +264,7 @@ std::ostream& operator<<(std::ostream& out, OpenFd const& ofd); PosixErrorOr> GetOpenFDs(); // Returns the number of hard links to a path. -PosixErrorOr Links(const std::string& path); +PosixErrorOr Links(const std::string& path); namespace internal { @@ -706,7 +706,7 @@ inline PosixErrorOr Atoi(absl::string_view str) { return ret; } -inline PosixErrorOr AtoiBase(absl::string_view str, int base) { +inline PosixErrorOr AtoiBase(absl::string_view str, int base) { if (base > 255 || base < 2) { return PosixError(EINVAL, "Invalid Base"); } @@ -737,16 +737,16 @@ inline PosixErrorOr Atof(absl::string_view str) { // Return the smallest number of iovec arrays that can be used to write // "total_bytes" number of bytes, each iovec writing one "buf". -std::vector> GenerateIovecs(uint64 total_size, +std::vector> GenerateIovecs(uint64_t total_size, void* buf, size_t buflen); // Returns bytes in 'n' megabytes. Used for readability. -uint64 Megabytes(uint64 n); +uint64_t Megabytes(uint64_t n); // Predicate for checking that a value is within some tolerance of another // value. Returns true iff current is in the range [target * (1 - tolerance), // target * (1 + tolerance)]. -bool Equivalent(uint64 current, uint64 target, double tolerance); +bool Equivalent(uint64_t current, uint64_t target, double tolerance); // Matcher wrapping the Equivalent predicate. MATCHER_P2(EquivalentWithin, target, tolerance, @@ -756,7 +756,7 @@ MATCHER_P2(EquivalentWithin, target, tolerance, if (target == 0) { *result_listener << ::absl::StreamFormat("difference of infinity%%"); } else { - int64 delta = static_cast(arg) - static_cast(target); + int64_t delta = static_cast(arg) - static_cast(target); double delta_percent = static_cast(delta) / static_cast(target) * 100; *result_listener << ::absl::StreamFormat("difference of %.2f%%", diff --git a/test/util/test_util_test.cc b/test/util/test_util_test.cc index 024304535..f42100374 100644 --- a/test/util/test_util_test.cc +++ b/test/util/test_util_test.cc @@ -171,7 +171,7 @@ MATCHER_P(IovecsListEq, expected, "") { return false; } - for (uint64 i = 0; i < expected.size(); ++i) { + for (uint64_t i = 0; i < expected.size(); ++i) { const std::vector& actual_iovecs = arg[i]; const std::vector& expected_iovecs = expected[i]; if (actual_iovecs.size() != expected_iovecs.size()) { @@ -181,7 +181,7 @@ MATCHER_P(IovecsListEq, expected, "") { return false; } - for (uint64 j = 0; j < expected_iovecs.size(); ++j) { + for (uint64_t j = 0; j < expected_iovecs.size(); ++j) { const struct iovec& actual_iov = actual_iovecs[j]; const struct iovec& expected_iov = expected_iovecs[j]; if (actual_iov.iov_base != expected_iov.iov_base) { -- cgit v1.2.3 From a944fcd94626bb278d5edd5453c5be16c72b7ee5 Mon Sep 17 00:00:00 2001 From: Nicolas Lacasse Date: Tue, 21 Jan 2020 16:38:42 -0800 Subject: Install Bazel 2.0.0 on kokoro images. PiperOrigin-RevId: 290850738 --- kokoro/ubuntu1604/20_bazel.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kokoro/ubuntu1604/20_bazel.sh b/kokoro/ubuntu1604/20_bazel.sh index b9a894024..b33e1656c 100755 --- a/kokoro/ubuntu1604/20_bazel.sh +++ b/kokoro/ubuntu1604/20_bazel.sh @@ -16,7 +16,7 @@ set -xeo pipefail -declare -r BAZEL_VERSION=0.29.1 +declare -r BAZEL_VERSION=2.0.0 # Install bazel dependencies. apt-get update && apt-get install -y openjdk-8-jdk-headless unzip -- cgit v1.2.3 From 1effdc091b441c4b1ada4327c1422cd360f80f98 Mon Sep 17 00:00:00 2001 From: Ian Gudger Date: Tue, 21 Jan 2020 16:59:24 -0800 Subject: TMutex based on sync.Mutex. Updates #231 PiperOrigin-RevId: 290854399 --- pkg/sync/BUILD | 2 ++ pkg/sync/tmutex_test.go | 71 +++++++++++++++++++++++++++++++++++++++++++++++ pkg/sync/tmutex_unsafe.go | 49 ++++++++++++++++++++++++++++++++ 3 files changed, 122 insertions(+) create mode 100644 pkg/sync/tmutex_test.go create mode 100644 pkg/sync/tmutex_unsafe.go diff --git a/pkg/sync/BUILD b/pkg/sync/BUILD index e8cd16b8f..97c4b3b1e 100644 --- a/pkg/sync/BUILD +++ b/pkg/sync/BUILD @@ -38,6 +38,7 @@ go_library( "race_unsafe.go", "seqcount.go", "syncutil.go", + "tmutex_unsafe.go", ], importpath = "gvisor.dev/gvisor/pkg/sync", ) @@ -48,6 +49,7 @@ go_test( srcs = [ "downgradable_rwmutex_test.go", "seqcount_test.go", + "tmutex_test.go", ], embed = [":sync"], ) diff --git a/pkg/sync/tmutex_test.go b/pkg/sync/tmutex_test.go new file mode 100644 index 000000000..c640bae23 --- /dev/null +++ b/pkg/sync/tmutex_test.go @@ -0,0 +1,71 @@ +// Copyright 2019 The gVisor Authors. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package sync + +import ( + "sync" + "testing" + "unsafe" +) + +// TestStructSize verifies that syncMutex's size hasn't drifted from the +// standard library's version. +// +// The correctness of this package relies on these remaining in sync. +func TestStructSize(t *testing.T) { + const ( + got = unsafe.Sizeof(syncMutex{}) + want = unsafe.Sizeof(sync.Mutex{}) + ) + if got != want { + t.Errorf("got sizeof(syncMutex) = %d, want = sizeof(sync.Mutex) = %d", got, want) + } +} + +// TestFieldValues verifies that the semantics of syncMutex.state from the +// standard library's implementation. +// +// The correctness of this package relies on these remaining in sync. +func TestFieldValues(t *testing.T) { + var m TMutex + m.Lock() + if got := *m.state(); got != mutexLocked { + t.Errorf("got locked sync.Mutex.state = %d, want = %d", got, mutexLocked) + } + m.Unlock() + if got := *m.state(); got != mutexUnlocked { + t.Errorf("got unlocked sync.Mutex.state = %d, want = %d", got, mutexUnlocked) + } +} + +func TestDoubleTryLock(t *testing.T) { + var m TMutex + if !m.TryLock() { + t.Fatal("failed to aquire lock") + } + if m.TryLock() { + t.Fatal("unexpectedly succeeded in aquiring locked mutex") + } +} + +func TestTryLockAfterLock(t *testing.T) { + var m TMutex + m.Lock() + if m.TryLock() { + t.Fatal("unexpectedly succeeded in aquiring locked mutex") + } +} + +func TestTryLockUnlock(t *testing.T) { + var m TMutex + if !m.TryLock() { + t.Fatal("failed to aquire lock") + } + m.Unlock() + if !m.TryLock() { + t.Fatal("failed to aquire lock after unlock") + } +} diff --git a/pkg/sync/tmutex_unsafe.go b/pkg/sync/tmutex_unsafe.go new file mode 100644 index 000000000..3c32f8371 --- /dev/null +++ b/pkg/sync/tmutex_unsafe.go @@ -0,0 +1,49 @@ +// Copyright 2019 The gVisor Authors. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build go1.13 +// +build !go1.15 + +// When updating the build constraint (above), check that syncMutex matches the +// standard library sync.Mutex definition. + +package sync + +import ( + "sync" + "sync/atomic" + "unsafe" +) + +// TMutex is a try lock. +type TMutex struct { + sync.Mutex +} + +type syncMutex struct { + state int32 + sema uint32 +} + +func (m *TMutex) state() *int32 { + return &(*syncMutex)(unsafe.Pointer(&m.Mutex)).state +} + +const ( + mutexUnlocked = 0 + mutexLocked = 1 +) + +// TryLock tries to aquire the mutex. It returns true if it succeeds and false +// otherwise. TryLock does not block. +func (m *TMutex) TryLock() bool { + if atomic.CompareAndSwapInt32(m.state(), mutexUnlocked, mutexLocked) { + if RaceEnabled { + RaceAcquire(unsafe.Pointer(&m.Mutex)) + } + return true + } + return false +} -- cgit v1.2.3 From d0e75f2bef4e16356693987db6ae6bbdce749618 Mon Sep 17 00:00:00 2001 From: Ian Gudger Date: Tue, 21 Jan 2020 18:34:24 -0800 Subject: Add trylock support to DowngradableRWMutex. Updates #231 PiperOrigin-RevId: 290868875 --- pkg/sync/downgradable_rwmutex_test.go | 55 ++++++++++++++++++++++++++ pkg/sync/downgradable_rwmutex_unsafe.go | 68 +++++++++++++++++++++++++++++---- 2 files changed, 115 insertions(+), 8 deletions(-) diff --git a/pkg/sync/downgradable_rwmutex_test.go b/pkg/sync/downgradable_rwmutex_test.go index f04496bc5..b5cb28ec0 100644 --- a/pkg/sync/downgradable_rwmutex_test.go +++ b/pkg/sync/downgradable_rwmutex_test.go @@ -148,3 +148,58 @@ func TestDowngradableRWMutex(t *testing.T) { HammerDowngradableRWMutex(10, 10, n) HammerDowngradableRWMutex(10, 5, n) } + +func TestRWDoubleTryLock(t *testing.T) { + var m DowngradableRWMutex + if !m.TryLock() { + t.Fatal("failed to aquire lock") + } + if m.TryLock() { + t.Fatal("unexpectedly succeeded in aquiring locked mutex") + } +} + +func TestRWTryLockAfterLock(t *testing.T) { + var m DowngradableRWMutex + m.Lock() + if m.TryLock() { + t.Fatal("unexpectedly succeeded in aquiring locked mutex") + } +} + +func TestRWTryLockUnlock(t *testing.T) { + var m DowngradableRWMutex + if !m.TryLock() { + t.Fatal("failed to aquire lock") + } + m.Unlock() + if !m.TryLock() { + t.Fatal("failed to aquire lock after unlock") + } +} + +func TestTryRLockAfterLock(t *testing.T) { + var m DowngradableRWMutex + m.Lock() + if m.TryRLock() { + t.Fatal("unexpectedly succeeded in aquiring locked mutex") + } +} + +func TestTryLockAfterRLock(t *testing.T) { + var m DowngradableRWMutex + m.RLock() + if m.TryLock() { + t.Fatal("unexpectedly succeeded in aquiring locked mutex") + } +} + +func TestDoubleTryRLock(t *testing.T) { + var m DowngradableRWMutex + if !m.TryRLock() { + t.Fatal("failed to aquire lock") + } + if !m.TryRLock() { + t.Fatal("failed to read aquire read locked lock") + } +} diff --git a/pkg/sync/downgradable_rwmutex_unsafe.go b/pkg/sync/downgradable_rwmutex_unsafe.go index 9bb55cd3a..0d321f5e3 100644 --- a/pkg/sync/downgradable_rwmutex_unsafe.go +++ b/pkg/sync/downgradable_rwmutex_unsafe.go @@ -19,7 +19,6 @@ package sync import ( - "sync" "sync/atomic" "unsafe" ) @@ -30,18 +29,43 @@ func runtimeSemacquire(s *uint32) //go:linkname runtimeSemrelease sync.runtime_Semrelease func runtimeSemrelease(s *uint32, handoff bool, skipframes int) -// DowngradableRWMutex is identical to sync.RWMutex, but adds the DowngradeLock -// method. +// DowngradableRWMutex is identical to sync.RWMutex, but adds the DowngradeLock, +// TryLock and TryRLock methods. type DowngradableRWMutex struct { - w sync.Mutex // held if there are pending writers - writerSem uint32 // semaphore for writers to wait for completing readers - readerSem uint32 // semaphore for readers to wait for completing writers - readerCount int32 // number of pending readers - readerWait int32 // number of departing readers + w TMutex // held if there are pending writers + writerSem uint32 // semaphore for writers to wait for completing readers + readerSem uint32 // semaphore for readers to wait for completing writers + readerCount int32 // number of pending readers + readerWait int32 // number of departing readers } const rwmutexMaxReaders = 1 << 30 +// TryRLock locks rw for reading. It returns true if it succeeds and false +// otherwise. It does not block. +func (rw *DowngradableRWMutex) TryRLock() bool { + if RaceEnabled { + RaceDisable() + } + for { + rc := atomic.LoadInt32(&rw.readerCount) + if rc < 0 { + if RaceEnabled { + RaceEnable() + } + return false + } + if !atomic.CompareAndSwapInt32(&rw.readerCount, rc, rc+1) { + continue + } + if RaceEnabled { + RaceEnable() + RaceAcquire(unsafe.Pointer(&rw.readerSem)) + } + return true + } +} + // RLock locks rw for reading. func (rw *DowngradableRWMutex) RLock() { if RaceEnabled { @@ -78,6 +102,34 @@ func (rw *DowngradableRWMutex) RUnlock() { } } +// TryLock locks rw for writing. It returns true if it succeeds and false +// otherwise. It does not block. +func (rw *DowngradableRWMutex) TryLock() bool { + if RaceEnabled { + RaceDisable() + } + // First, resolve competition with other writers. + if !rw.w.TryLock() { + if RaceEnabled { + RaceEnable() + } + return false + } + // Only proceed if there are no readers. + if !atomic.CompareAndSwapInt32(&rw.readerCount, 0, -rwmutexMaxReaders) { + rw.w.Unlock() + if RaceEnabled { + RaceEnable() + } + return false + } + if RaceEnabled { + RaceEnable() + RaceAcquire(unsafe.Pointer(&rw.writerSem)) + } + return true +} + // Lock locks rw for writing. func (rw *DowngradableRWMutex) Lock() { if RaceEnabled { -- cgit v1.2.3 From 6a59e7f510a7b12f8b3bd768dfe569033ef07d30 Mon Sep 17 00:00:00 2001 From: Ian Gudger Date: Tue, 21 Jan 2020 19:23:26 -0800 Subject: Rename DowngradableRWMutex to RWmutex. Also renames TMutex to Mutex. These custom mutexes aren't any worse than the standard library versions (same code), so having both seems redundant. PiperOrigin-RevId: 290873587 --- pkg/sentry/fs/overlay.go | 2 +- pkg/sentry/mm/mm.go | 4 +-- pkg/sync/aliases.go | 6 ---- pkg/sync/downgradable_rwmutex_test.go | 50 ++++++++++++++++----------------- pkg/sync/downgradable_rwmutex_unsafe.go | 26 ++++++++--------- pkg/sync/tmutex_test.go | 8 +++--- pkg/sync/tmutex_unsafe.go | 8 +++--- 7 files changed, 49 insertions(+), 55 deletions(-) diff --git a/pkg/sentry/fs/overlay.go b/pkg/sentry/fs/overlay.go index 4cad55327..f7702f8f4 100644 --- a/pkg/sentry/fs/overlay.go +++ b/pkg/sentry/fs/overlay.go @@ -198,7 +198,7 @@ type overlayEntry struct { upper *Inode // dirCacheMu protects dirCache. - dirCacheMu sync.DowngradableRWMutex `state:"nosave"` + dirCacheMu sync.RWMutex `state:"nosave"` // dirCache is cache of DentAttrs from upper and lower Inodes. dirCache *SortedDentryMap diff --git a/pkg/sentry/mm/mm.go b/pkg/sentry/mm/mm.go index fa86ebced..78cc9e6e4 100644 --- a/pkg/sentry/mm/mm.go +++ b/pkg/sentry/mm/mm.go @@ -80,7 +80,7 @@ type MemoryManager struct { users int32 // mappingMu is analogous to Linux's struct mm_struct::mmap_sem. - mappingMu sync.DowngradableRWMutex `state:"nosave"` + mappingMu sync.RWMutex `state:"nosave"` // vmas stores virtual memory areas. Since vmas are stored by value, // clients should usually use vmaIterator.ValuePtr() instead of @@ -123,7 +123,7 @@ type MemoryManager struct { // activeMu is loosely analogous to Linux's struct // mm_struct::page_table_lock. - activeMu sync.DowngradableRWMutex `state:"nosave"` + activeMu sync.RWMutex `state:"nosave"` // pmas stores platform mapping areas used to implement vmas. Since pmas // are stored by value, clients should usually use pmaIterator.ValuePtr() diff --git a/pkg/sync/aliases.go b/pkg/sync/aliases.go index 20c7ca041..d2d7132fa 100644 --- a/pkg/sync/aliases.go +++ b/pkg/sync/aliases.go @@ -11,12 +11,6 @@ import ( // Aliases of standard library types. type ( - // Mutex is an alias of sync.Mutex. - Mutex = sync.Mutex - - // RWMutex is an alias of sync.RWMutex. - RWMutex = sync.RWMutex - // Cond is an alias of sync.Cond. Cond = sync.Cond diff --git a/pkg/sync/downgradable_rwmutex_test.go b/pkg/sync/downgradable_rwmutex_test.go index b5cb28ec0..ce667e825 100644 --- a/pkg/sync/downgradable_rwmutex_test.go +++ b/pkg/sync/downgradable_rwmutex_test.go @@ -18,7 +18,7 @@ import ( "testing" ) -func parallelReader(m *DowngradableRWMutex, clocked, cunlock, cdone chan bool) { +func parallelReader(m *RWMutex, clocked, cunlock, cdone chan bool) { m.RLock() clocked <- true <-cunlock @@ -28,7 +28,7 @@ func parallelReader(m *DowngradableRWMutex, clocked, cunlock, cdone chan bool) { func doTestParallelReaders(numReaders, gomaxprocs int) { runtime.GOMAXPROCS(gomaxprocs) - var m DowngradableRWMutex + var m RWMutex clocked := make(chan bool) cunlock := make(chan bool) cdone := make(chan bool) @@ -55,7 +55,7 @@ func TestParallelReaders(t *testing.T) { doTestParallelReaders(4, 2) } -func reader(rwm *DowngradableRWMutex, numIterations int, activity *int32, cdone chan bool) { +func reader(rwm *RWMutex, numIterations int, activity *int32, cdone chan bool) { for i := 0; i < numIterations; i++ { rwm.RLock() n := atomic.AddInt32(activity, 1) @@ -70,7 +70,7 @@ func reader(rwm *DowngradableRWMutex, numIterations int, activity *int32, cdone cdone <- true } -func writer(rwm *DowngradableRWMutex, numIterations int, activity *int32, cdone chan bool) { +func writer(rwm *RWMutex, numIterations int, activity *int32, cdone chan bool) { for i := 0; i < numIterations; i++ { rwm.Lock() n := atomic.AddInt32(activity, 10000) @@ -85,7 +85,7 @@ func writer(rwm *DowngradableRWMutex, numIterations int, activity *int32, cdone cdone <- true } -func downgradingWriter(rwm *DowngradableRWMutex, numIterations int, activity *int32, cdone chan bool) { +func downgradingWriter(rwm *RWMutex, numIterations int, activity *int32, cdone chan bool) { for i := 0; i < numIterations; i++ { rwm.Lock() n := atomic.AddInt32(activity, 10000) @@ -112,7 +112,7 @@ func HammerDowngradableRWMutex(gomaxprocs, numReaders, numIterations int) { runtime.GOMAXPROCS(gomaxprocs) // Number of active readers + 10000 * number of active writers. var activity int32 - var rwm DowngradableRWMutex + var rwm RWMutex cdone := make(chan bool) go writer(&rwm, numIterations, &activity, cdone) go downgradingWriter(&rwm, numIterations, &activity, cdone) @@ -150,56 +150,56 @@ func TestDowngradableRWMutex(t *testing.T) { } func TestRWDoubleTryLock(t *testing.T) { - var m DowngradableRWMutex - if !m.TryLock() { + var rwm RWMutex + if !rwm.TryLock() { t.Fatal("failed to aquire lock") } - if m.TryLock() { + if rwm.TryLock() { t.Fatal("unexpectedly succeeded in aquiring locked mutex") } } func TestRWTryLockAfterLock(t *testing.T) { - var m DowngradableRWMutex - m.Lock() - if m.TryLock() { + var rwm RWMutex + rwm.Lock() + if rwm.TryLock() { t.Fatal("unexpectedly succeeded in aquiring locked mutex") } } func TestRWTryLockUnlock(t *testing.T) { - var m DowngradableRWMutex - if !m.TryLock() { + var rwm RWMutex + if !rwm.TryLock() { t.Fatal("failed to aquire lock") } - m.Unlock() - if !m.TryLock() { + rwm.Unlock() + if !rwm.TryLock() { t.Fatal("failed to aquire lock after unlock") } } func TestTryRLockAfterLock(t *testing.T) { - var m DowngradableRWMutex - m.Lock() - if m.TryRLock() { + var rwm RWMutex + rwm.Lock() + if rwm.TryRLock() { t.Fatal("unexpectedly succeeded in aquiring locked mutex") } } func TestTryLockAfterRLock(t *testing.T) { - var m DowngradableRWMutex - m.RLock() - if m.TryLock() { + var rwm RWMutex + rwm.RLock() + if rwm.TryLock() { t.Fatal("unexpectedly succeeded in aquiring locked mutex") } } func TestDoubleTryRLock(t *testing.T) { - var m DowngradableRWMutex - if !m.TryRLock() { + var rwm RWMutex + if !rwm.TryRLock() { t.Fatal("failed to aquire lock") } - if !m.TryRLock() { + if !rwm.TryRLock() { t.Fatal("failed to read aquire read locked lock") } } diff --git a/pkg/sync/downgradable_rwmutex_unsafe.go b/pkg/sync/downgradable_rwmutex_unsafe.go index 0d321f5e3..ea6cdc447 100644 --- a/pkg/sync/downgradable_rwmutex_unsafe.go +++ b/pkg/sync/downgradable_rwmutex_unsafe.go @@ -29,10 +29,10 @@ func runtimeSemacquire(s *uint32) //go:linkname runtimeSemrelease sync.runtime_Semrelease func runtimeSemrelease(s *uint32, handoff bool, skipframes int) -// DowngradableRWMutex is identical to sync.RWMutex, but adds the DowngradeLock, +// RWMutex is identical to sync.RWMutex, but adds the DowngradeLock, // TryLock and TryRLock methods. -type DowngradableRWMutex struct { - w TMutex // held if there are pending writers +type RWMutex struct { + w Mutex // held if there are pending writers writerSem uint32 // semaphore for writers to wait for completing readers readerSem uint32 // semaphore for readers to wait for completing writers readerCount int32 // number of pending readers @@ -43,7 +43,7 @@ const rwmutexMaxReaders = 1 << 30 // TryRLock locks rw for reading. It returns true if it succeeds and false // otherwise. It does not block. -func (rw *DowngradableRWMutex) TryRLock() bool { +func (rw *RWMutex) TryRLock() bool { if RaceEnabled { RaceDisable() } @@ -67,7 +67,7 @@ func (rw *DowngradableRWMutex) TryRLock() bool { } // RLock locks rw for reading. -func (rw *DowngradableRWMutex) RLock() { +func (rw *RWMutex) RLock() { if RaceEnabled { RaceDisable() } @@ -82,14 +82,14 @@ func (rw *DowngradableRWMutex) RLock() { } // RUnlock undoes a single RLock call. -func (rw *DowngradableRWMutex) RUnlock() { +func (rw *RWMutex) RUnlock() { if RaceEnabled { RaceReleaseMerge(unsafe.Pointer(&rw.writerSem)) RaceDisable() } if r := atomic.AddInt32(&rw.readerCount, -1); r < 0 { if r+1 == 0 || r+1 == -rwmutexMaxReaders { - panic("RUnlock of unlocked DowngradableRWMutex") + panic("RUnlock of unlocked RWMutex") } // A writer is pending. if atomic.AddInt32(&rw.readerWait, -1) == 0 { @@ -104,7 +104,7 @@ func (rw *DowngradableRWMutex) RUnlock() { // TryLock locks rw for writing. It returns true if it succeeds and false // otherwise. It does not block. -func (rw *DowngradableRWMutex) TryLock() bool { +func (rw *RWMutex) TryLock() bool { if RaceEnabled { RaceDisable() } @@ -131,7 +131,7 @@ func (rw *DowngradableRWMutex) TryLock() bool { } // Lock locks rw for writing. -func (rw *DowngradableRWMutex) Lock() { +func (rw *RWMutex) Lock() { if RaceEnabled { RaceDisable() } @@ -150,7 +150,7 @@ func (rw *DowngradableRWMutex) Lock() { } // Unlock unlocks rw for writing. -func (rw *DowngradableRWMutex) Unlock() { +func (rw *RWMutex) Unlock() { if RaceEnabled { RaceRelease(unsafe.Pointer(&rw.writerSem)) RaceRelease(unsafe.Pointer(&rw.readerSem)) @@ -159,7 +159,7 @@ func (rw *DowngradableRWMutex) Unlock() { // Announce to readers there is no active writer. r := atomic.AddInt32(&rw.readerCount, rwmutexMaxReaders) if r >= rwmutexMaxReaders { - panic("Unlock of unlocked DowngradableRWMutex") + panic("Unlock of unlocked RWMutex") } // Unblock blocked readers, if any. for i := 0; i < int(r); i++ { @@ -173,7 +173,7 @@ func (rw *DowngradableRWMutex) Unlock() { } // DowngradeLock atomically unlocks rw for writing and locks it for reading. -func (rw *DowngradableRWMutex) DowngradeLock() { +func (rw *RWMutex) DowngradeLock() { if RaceEnabled { RaceRelease(unsafe.Pointer(&rw.readerSem)) RaceDisable() @@ -181,7 +181,7 @@ func (rw *DowngradableRWMutex) DowngradeLock() { // Announce to readers there is no active writer and one additional reader. r := atomic.AddInt32(&rw.readerCount, rwmutexMaxReaders+1) if r >= rwmutexMaxReaders+1 { - panic("DowngradeLock of unlocked DowngradableRWMutex") + panic("DowngradeLock of unlocked RWMutex") } // Unblock blocked readers, if any. Note that this loop starts as 1 since r // includes this goroutine. diff --git a/pkg/sync/tmutex_test.go b/pkg/sync/tmutex_test.go index c640bae23..0838248b4 100644 --- a/pkg/sync/tmutex_test.go +++ b/pkg/sync/tmutex_test.go @@ -30,7 +30,7 @@ func TestStructSize(t *testing.T) { // // The correctness of this package relies on these remaining in sync. func TestFieldValues(t *testing.T) { - var m TMutex + var m Mutex m.Lock() if got := *m.state(); got != mutexLocked { t.Errorf("got locked sync.Mutex.state = %d, want = %d", got, mutexLocked) @@ -42,7 +42,7 @@ func TestFieldValues(t *testing.T) { } func TestDoubleTryLock(t *testing.T) { - var m TMutex + var m Mutex if !m.TryLock() { t.Fatal("failed to aquire lock") } @@ -52,7 +52,7 @@ func TestDoubleTryLock(t *testing.T) { } func TestTryLockAfterLock(t *testing.T) { - var m TMutex + var m Mutex m.Lock() if m.TryLock() { t.Fatal("unexpectedly succeeded in aquiring locked mutex") @@ -60,7 +60,7 @@ func TestTryLockAfterLock(t *testing.T) { } func TestTryLockUnlock(t *testing.T) { - var m TMutex + var m Mutex if !m.TryLock() { t.Fatal("failed to aquire lock") } diff --git a/pkg/sync/tmutex_unsafe.go b/pkg/sync/tmutex_unsafe.go index 3c32f8371..3dd15578b 100644 --- a/pkg/sync/tmutex_unsafe.go +++ b/pkg/sync/tmutex_unsafe.go @@ -17,8 +17,8 @@ import ( "unsafe" ) -// TMutex is a try lock. -type TMutex struct { +// Mutex is a try lock. +type Mutex struct { sync.Mutex } @@ -27,7 +27,7 @@ type syncMutex struct { sema uint32 } -func (m *TMutex) state() *int32 { +func (m *Mutex) state() *int32 { return &(*syncMutex)(unsafe.Pointer(&m.Mutex)).state } @@ -38,7 +38,7 @@ const ( // TryLock tries to aquire the mutex. It returns true if it succeeds and false // otherwise. TryLock does not block. -func (m *TMutex) TryLock() bool { +func (m *Mutex) TryLock() bool { if atomic.CompareAndSwapInt32(m.state(), mutexUnlocked, mutexLocked) { if RaceEnabled { RaceAcquire(unsafe.Pointer(&m.Mutex)) -- cgit v1.2.3 From d59a3cc959cb14b0bed14b62e33ee4178b89b346 Mon Sep 17 00:00:00 2001 From: Haibo Xu Date: Wed, 22 Jan 2020 05:51:57 +0000 Subject: Enable fault() syscall test on arm64. Signed-off-by: Haibo Xu Change-Id: I9b2b2e0d84946c10cf136abeef6c60642fa3b6ec --- test/syscalls/linux/fault.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/syscalls/linux/fault.cc b/test/syscalls/linux/fault.cc index f6e19026f..a85750382 100644 --- a/test/syscalls/linux/fault.cc +++ b/test/syscalls/linux/fault.cc @@ -37,6 +37,9 @@ int GetPcFromUcontext(ucontext_t* uc, uintptr_t* pc) { #elif defined(__i386__) *pc = uc->uc_mcontext.gregs[REG_EIP]; return 1; +#elif defined(__aarch64__) + *pc = uc->uc_mcontext.pc; + return 1; #else return 0; #endif -- cgit v1.2.3 From 38fe05eb699550dc1ae5f6773f0190cad83d5ae8 Mon Sep 17 00:00:00 2001 From: Marek Majkowski Date: Wed, 22 Jan 2020 11:34:29 +0000 Subject: gonet PacketConn.RemoteAddr() incorrectly returns *net.TCPAddr, should be *net.UDPAddr PacketConn.LocalAddr() already returns *net.UDPAddr correctly. --- pkg/tcpip/adapters/gonet/gonet.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/tcpip/adapters/gonet/gonet.go b/pkg/tcpip/adapters/gonet/gonet.go index a2f44b496..3bba4028b 100644 --- a/pkg/tcpip/adapters/gonet/gonet.go +++ b/pkg/tcpip/adapters/gonet/gonet.go @@ -622,7 +622,7 @@ func (c *PacketConn) RemoteAddr() net.Addr { if err != nil { return nil } - return fullToTCPAddr(a) + return fullToUDPAddr(a) } // Read implements net.Conn.Read -- cgit v1.2.3 From 747137c120bca27aeb259817d30ef60e01521621 Mon Sep 17 00:00:00 2001 From: Kevin Krakauer Date: Wed, 22 Jan 2020 10:23:44 -0800 Subject: Address GitHub comments. --- pkg/tcpip/iptables/types.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/tcpip/iptables/types.go b/pkg/tcpip/iptables/types.go index a0bfc8b41..a8b972f1b 100644 --- a/pkg/tcpip/iptables/types.go +++ b/pkg/tcpip/iptables/types.go @@ -153,7 +153,7 @@ func (table *Table) SetMetadata(metadata interface{}) { // packets this rule applies to. If there are no matchers in the rule, it // applies to any packet. type Rule struct { - // IPHeaderFilter holds basic IP filtering fields common to every rule. + // Filter holds basic IP filtering fields common to every rule. Filter IPHeaderFilter // Matchers is the list of matchers for this rule. -- cgit v1.2.3 From cb3906ae00575859a6910b8edc62ab9d531d1c85 Mon Sep 17 00:00:00 2001 From: Adin Scannell Date: Wed, 22 Jan 2020 10:38:03 -0800 Subject: Add tools for generating images. This formalizes the adhoc scripts previously in kokoro. The image targets can be used by e.g. benchmarks in order to automated image prepation. PiperOrigin-RevId: 290982744 --- kokoro/ubuntu1604/10_core.sh | 30 ------ kokoro/ubuntu1604/20_bazel.sh | 28 ----- kokoro/ubuntu1604/25_docker.sh | 35 ------ kokoro/ubuntu1604/30_containerd.sh | 76 ------------- kokoro/ubuntu1604/40_kokoro.sh | 57 ---------- kokoro/ubuntu1604/README.md | 34 ------ kokoro/ubuntu1604/build.sh | 20 ---- kokoro/ubuntu1804/10_core.sh | 1 - kokoro/ubuntu1804/20_bazel.sh | 1 - kokoro/ubuntu1804/25_docker.sh | 1 - kokoro/ubuntu1804/30_containerd.sh | 1 - kokoro/ubuntu1804/40_kokoro.sh | 1 - kokoro/ubuntu1804/build.sh | 20 ---- tools/images/BUILD | 68 ++++++++++++ tools/images/build.sh | 101 ++++++++++++++++++ tools/images/defs.bzl | 178 +++++++++++++++++++++++++++++++ tools/images/execute.sh | 152 ++++++++++++++++++++++++++ tools/images/test.cc | 23 ++++ tools/images/ubuntu1604/10_core.sh | 30 ++++++ tools/images/ubuntu1604/20_bazel.sh | 28 +++++ tools/images/ubuntu1604/25_docker.sh | 35 ++++++ tools/images/ubuntu1604/30_containerd.sh | 76 +++++++++++++ tools/images/ubuntu1604/40_kokoro.sh | 57 ++++++++++ tools/images/ubuntu1604/BUILD | 7 ++ tools/images/ubuntu1804/BUILD | 7 ++ tools/installers/BUILD | 22 ++++ tools/installers/head.sh | 21 ++++ tools/installers/master.sh | 20 ++++ tools/installers/shim.sh | 24 +++++ 29 files changed, 849 insertions(+), 305 deletions(-) delete mode 100755 kokoro/ubuntu1604/10_core.sh delete mode 100755 kokoro/ubuntu1604/20_bazel.sh delete mode 100755 kokoro/ubuntu1604/25_docker.sh delete mode 100755 kokoro/ubuntu1604/30_containerd.sh delete mode 100755 kokoro/ubuntu1604/40_kokoro.sh delete mode 100644 kokoro/ubuntu1604/README.md delete mode 100755 kokoro/ubuntu1604/build.sh delete mode 120000 kokoro/ubuntu1804/10_core.sh delete mode 120000 kokoro/ubuntu1804/20_bazel.sh delete mode 120000 kokoro/ubuntu1804/25_docker.sh delete mode 120000 kokoro/ubuntu1804/30_containerd.sh delete mode 120000 kokoro/ubuntu1804/40_kokoro.sh delete mode 100755 kokoro/ubuntu1804/build.sh create mode 100644 tools/images/BUILD create mode 100755 tools/images/build.sh create mode 100644 tools/images/defs.bzl create mode 100755 tools/images/execute.sh create mode 100644 tools/images/test.cc create mode 100755 tools/images/ubuntu1604/10_core.sh create mode 100755 tools/images/ubuntu1604/20_bazel.sh create mode 100755 tools/images/ubuntu1604/25_docker.sh create mode 100755 tools/images/ubuntu1604/30_containerd.sh create mode 100755 tools/images/ubuntu1604/40_kokoro.sh create mode 100644 tools/images/ubuntu1604/BUILD create mode 100644 tools/images/ubuntu1804/BUILD create mode 100644 tools/installers/BUILD create mode 100755 tools/installers/head.sh create mode 100755 tools/installers/master.sh create mode 100755 tools/installers/shim.sh diff --git a/kokoro/ubuntu1604/10_core.sh b/kokoro/ubuntu1604/10_core.sh deleted file mode 100755 index 46dda6bb1..000000000 --- a/kokoro/ubuntu1604/10_core.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/bash - -# Copyright 2019 The gVisor Authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -set -xeo pipefail - -# Install all essential build tools. -apt-get update && apt-get -y install make git-core build-essential linux-headers-$(uname -r) pkg-config - -# Install a recent go toolchain. -if ! [[ -d /usr/local/go ]]; then - wget https://dl.google.com/go/go1.13.5.linux-amd64.tar.gz - tar -xvf go1.13.5.linux-amd64.tar.gz - mv go /usr/local -fi - -# Link the Go binary from /usr/bin; replacing anything there. -(cd /usr/bin && rm -f go && sudo ln -fs /usr/local/go/bin/go go) diff --git a/kokoro/ubuntu1604/20_bazel.sh b/kokoro/ubuntu1604/20_bazel.sh deleted file mode 100755 index b33e1656c..000000000 --- a/kokoro/ubuntu1604/20_bazel.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash - -# Copyright 2019 The gVisor Authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -set -xeo pipefail - -declare -r BAZEL_VERSION=2.0.0 - -# Install bazel dependencies. -apt-get update && apt-get install -y openjdk-8-jdk-headless unzip - -# Use the release installer. -curl -L -o bazel-${BAZEL_VERSION}-installer-linux-x86_64.sh https://github.com/bazelbuild/bazel/releases/download/${BAZEL_VERSION}/bazel-${BAZEL_VERSION}-installer-linux-x86_64.sh -chmod a+x bazel-${BAZEL_VERSION}-installer-linux-x86_64.sh -./bazel-${BAZEL_VERSION}-installer-linux-x86_64.sh -rm -f bazel-${BAZEL_VERSION}-installer-linux-x86_64.sh diff --git a/kokoro/ubuntu1604/25_docker.sh b/kokoro/ubuntu1604/25_docker.sh deleted file mode 100755 index 1d3defcd3..000000000 --- a/kokoro/ubuntu1604/25_docker.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/bash - -# Copyright 2019 The gVisor Authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Add dependencies. -apt-get update && apt-get -y install \ - apt-transport-https \ - ca-certificates \ - curl \ - gnupg-agent \ - software-properties-common - -# Install the key. -curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - - -# Add the repository. -add-apt-repository \ - "deb [arch=amd64] https://download.docker.com/linux/ubuntu \ - $(lsb_release -cs) \ - stable" - -# Install docker. -apt-get update && apt-get install -y docker-ce docker-ce-cli containerd.io diff --git a/kokoro/ubuntu1604/30_containerd.sh b/kokoro/ubuntu1604/30_containerd.sh deleted file mode 100755 index a7472bd1c..000000000 --- a/kokoro/ubuntu1604/30_containerd.sh +++ /dev/null @@ -1,76 +0,0 @@ -#!/bin/bash - -# Copyright 2019 The gVisor Authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -set -xeo pipefail - -# Helper for Go packages below. -install_helper() { - PACKAGE="${1}" - TAG="${2}" - GOPATH="${3}" - - # Clone the repository. - mkdir -p "${GOPATH}"/src/$(dirname "${PACKAGE}") && \ - git clone https://"${PACKAGE}" "${GOPATH}"/src/"${PACKAGE}" - - # Checkout and build the repository. - (cd "${GOPATH}"/src/"${PACKAGE}" && \ - git checkout "${TAG}" && \ - GOPATH="${GOPATH}" make && \ - GOPATH="${GOPATH}" make install) -} - -# Install dependencies for the crictl tests. -apt-get install -y btrfs-tools libseccomp-dev - -# Install containerd & cri-tools. -GOPATH=$(mktemp -d --tmpdir gopathXXXXX) -install_helper github.com/containerd/containerd v1.2.2 "${GOPATH}" -install_helper github.com/kubernetes-sigs/cri-tools v1.11.0 "${GOPATH}" - -# Install gvisor-containerd-shim. -declare -r base="https://storage.googleapis.com/cri-containerd-staging/gvisor-containerd-shim" -declare -r latest=$(mktemp --tmpdir gvisor-containerd-shim-latest.XXXXXX) -declare -r shim_path=$(mktemp --tmpdir gvisor-containerd-shim.XXXXXX) -wget --no-verbose "${base}"/latest -O ${latest} -wget --no-verbose "${base}"/gvisor-containerd-shim-$(cat ${latest}) -O ${shim_path} -chmod +x ${shim_path} -mv ${shim_path} /usr/local/bin - -# Configure containerd-shim. -declare -r shim_config_path=/etc/containerd -declare -r shim_config_tmp_path=$(mktemp --tmpdir gvisor-containerd-shim.XXXXXX.toml) -mkdir -p ${shim_config_path} -cat > ${shim_config_tmp_path} <<-EOF - runc_shim = "/usr/local/bin/containerd-shim" - -[runsc_config] - debug = "true" - debug-log = "/tmp/runsc-logs/" - strace = "true" - file-access = "shared" -EOF -mv ${shim_config_tmp_path} ${shim_config_path} - -# Configure CNI. -(cd "${GOPATH}" && GOPATH="${GOPATH}" \ - src/github.com/containerd/containerd/script/setup/install-cni) - -# Cleanup the above. -rm -rf "${GOPATH}" -rm -rf "${latest}" -rm -rf "${shim_path}" -rm -rf "${shim_config_tmp_path}" diff --git a/kokoro/ubuntu1604/40_kokoro.sh b/kokoro/ubuntu1604/40_kokoro.sh deleted file mode 100755 index 5f2dfc858..000000000 --- a/kokoro/ubuntu1604/40_kokoro.sh +++ /dev/null @@ -1,57 +0,0 @@ -#!/bin/bash - -# Copyright 2019 The gVisor Authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -set -xeo pipefail - -# Declare kokoro's required public keys. -declare -r ssh_public_keys=( - "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDg7L/ZaEauETWrPklUTky3kvxqQfe2Ax/2CsSqhNIGNMnK/8d79CHlmY9+dE1FFQ/RzKNCaltgy7XcN/fCYiCZr5jm2ZtnLuGNOTzupMNhaYiPL419qmL+5rZXt4/dWTrsHbFRACxT8j51PcRMO5wgbL0Bg2XXimbx8kDFaurL2gqduQYqlu4lxWCaJqOL71WogcimeL63Nq/yeH5PJPWpqE4P9VUQSwAzBWFK/hLeds/AiP3MgVS65qHBnhq0JsHy8JQsqjZbG7Iidt/Ll0+gqzEbi62gDIcczG4KC0iOVzDDP/1BxDtt1lKeA23ll769Fcm3rJyoBMYxjvdw1TDx sabujp@trigger.mtv.corp.google.com" - "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBNgGK/hCdjmulHfRE3hp4rZs38NCR8yAh0eDsztxqGcuXnuSnL7jOlRrbcQpremJ84omD4eKrIpwJUs+YokMdv4= sabujp@trigger.svl.corp.google.com" -) - -# Install dependencies. -apt-get update && apt-get install -y rsync coreutils python-psutil qemu-kvm python-pip python3-pip zip - -# junitparser is used to merge junit xml files. -pip install junitparser - -# We need a kbuilder user. -if useradd -c "kbuilder user" -m -s /bin/bash kbuilder; then - # User was added successfully; we add the relevant SSH keys here. - mkdir -p ~kbuilder/.ssh - (IFS=$'\n'; echo "${ssh_public_keys[*]}") > ~kbuilder/.ssh/authorized_keys - chmod 0600 ~kbuilder/.ssh/authorized_keys - chown -R kbuilder ~kbuilder/.ssh -fi - -# Give passwordless sudo access. -cat > /etc/sudoers.d/kokoro </dev/null +function cleanup { + gcloud compute instances delete --quiet --zone "${ZONE}" "${INSTANCE_NAME}" +} +trap cleanup EXIT + +# Wait for the instance to become available (up to 5 minutes). +declare timeout=300 +declare success=0 +declare -r start=$(date +%s) +declare -r end=$((${start}+${timeout})) +while [[ "$(date +%s)" -lt "${end}" ]] && [[ "${success}" -lt 3 ]]; do + if gcloud compute ssh --zone "${ZONE}" "${USERNAME}"@"${INSTANCE_NAME}" -- env - true 2>/dev/null; then + success=$((${success}+1)) + fi +done +if [[ "${success}" -eq "0" ]]; then + echo "connect timed out after ${timeout} seconds." + exit 1 +fi + +# Run the install scripts provided. +for arg; do + gcloud compute ssh --zone "${ZONE}" "${USERNAME}"@"${INSTANCE_NAME}" -- sudo bash - <"${arg}" >/dev/null +done + +# Stop the instance; required before creating an image. +gcloud compute instances stop --quiet --zone "${ZONE}" "${INSTANCE_NAME}" >/dev/null + +# Create a snapshot of the instance disk. +gcloud compute disks snapshot \ + --quiet \ + --zone "${ZONE}" \ + --snapshot-names="${SNAPSHOT_NAME}" \ + "${INSTANCE_NAME}" >/dev/null + +# Create the disk image. +gcloud compute images create \ + --quiet \ + --source-snapshot="${SNAPSHOT_NAME}" \ + --licenses="https://www.googleapis.com/compute/v1/projects/vm-options/global/licenses/enable-vmx" \ + "${IMAGE_NAME}" >/dev/null + +# Finish up. +echo "${IMAGE_NAME}" diff --git a/tools/images/defs.bzl b/tools/images/defs.bzl new file mode 100644 index 000000000..d8e422a5d --- /dev/null +++ b/tools/images/defs.bzl @@ -0,0 +1,178 @@ +"""Image configuration. + +Images can be generated by using the vm_image rule. For example, + + vm_image( + name = "ubuntu", + project = "...", + family = "...", + scripts = [ + "script.sh", + "other.sh", + ], + ) + +This will always create an vm_image in the current default gcloud project. The +rule has a text file as its output containing the image name. This will enforce +serialization for all dependent rules. + +Images are always named per the hash of all the hermetic input scripts. This +allows images to be memoized quickly and easily. + +The vm_test rule can be used to execute a command remotely. For example, + + vm_test( + name = "mycommand", + image = ":myimage", + targets = [":test"], + ) +""" + +def _vm_image_impl(ctx): + script_paths = [] + for script in ctx.files.scripts: + script_paths.append(script.short_path) + + resolved_inputs, argv, runfiles_manifests = ctx.resolve_command( + command = "USERNAME=%s ZONE=$(cat %s) IMAGE_PROJECT=%s IMAGE_FAMILY=%s %s %s > %s" % + ( + ctx.attr.username, + ctx.files.zone[0].path, + ctx.attr.project, + ctx.attr.family, + ctx.executable.builder.path, + " ".join(script_paths), + ctx.outputs.out.path, + ), + tools = [ctx.attr.builder] + ctx.attr.scripts, + ) + + ctx.actions.run_shell( + tools = resolved_inputs, + outputs = [ctx.outputs.out], + progress_message = "Building image...", + execution_requirements = {"local": "true"}, + command = argv, + input_manifests = runfiles_manifests, + ) + return [DefaultInfo(files = depset([ctx.outputs.out]))] + +_vm_image = rule( + attrs = { + "builder": attr.label( + executable = True, + default = "//tools/images:builder", + cfg = "host", + ), + "username": attr.string(default = "$(whoami)"), + "zone": attr.label( + default = "//tools/images:zone", + cfg = "host", + ), + "family": attr.string(mandatory = True), + "project": attr.string(mandatory = True), + "scripts": attr.label_list(allow_files = True), + }, + outputs = { + "out": "%{name}.txt", + }, + implementation = _vm_image_impl, +) + +def vm_image(**kwargs): + _vm_image( + tags = [ + "local", + "manual", + ], + **kwargs + ) + +def _vm_test_impl(ctx): + runner = ctx.actions.declare_file("%s-executer" % ctx.label.name) + + # Note that the remote execution case must actually generate an + # intermediate target in order to collect all the relevant runfiles so that + # they can be copied over for remote execution. + runner_content = "\n".join([ + "#!/bin/bash", + "export ZONE=$(cat %s)" % ctx.files.zone[0].short_path, + "export USERNAME=%s" % ctx.attr.username, + "export IMAGE=$(cat %s)" % ctx.files.image[0].short_path, + "export SUDO=%s" % "true" if ctx.attr.sudo else "false", + "%s %s" % ( + ctx.executable.executer.short_path, + " ".join([ + target.files_to_run.executable.short_path + for target in ctx.attr.targets + ]), + ), + "", + ]) + ctx.actions.write(runner, runner_content, is_executable = True) + + # Return with all transitive files. + runfiles = ctx.runfiles( + transitive_files = depset(transitive = [ + depset(target.data_runfiles.files) + for target in ctx.attr.targets + if hasattr(target, "data_runfiles") + ]), + files = ctx.files.executer + ctx.files.zone + ctx.files.image + + ctx.files.targets, + collect_default = True, + collect_data = True, + ) + return [DefaultInfo(executable = runner, runfiles = runfiles)] + +_vm_test = rule( + attrs = { + "image": attr.label( + mandatory = True, + cfg = "host", + ), + "executer": attr.label( + executable = True, + default = "//tools/images:executer", + cfg = "host", + ), + "username": attr.string(default = "$(whoami)"), + "zone": attr.label( + default = "//tools/images:zone", + cfg = "host", + ), + "sudo": attr.bool(default = True), + "machine": attr.string(default = "n1-standard-1"), + "targets": attr.label_list( + mandatory = True, + allow_empty = False, + cfg = "target", + ), + }, + test = True, + implementation = _vm_test_impl, +) + +def vm_test( + installer = "//tools/installers:head", + **kwargs): + """Runs the given targets as a remote test. + + Args: + installer: Script to run before all targets. + **kwargs: All test arguments. Should include targets and image. + """ + targets = kwargs.pop("targets", []) + if installer: + targets = [installer] + targets + targets = [ + ] + targets + _vm_test( + tags = [ + "local", + "manual", + ], + targets = targets, + local = 1, + **kwargs + ) diff --git a/tools/images/execute.sh b/tools/images/execute.sh new file mode 100755 index 000000000..ba4b1ac0e --- /dev/null +++ b/tools/images/execute.sh @@ -0,0 +1,152 @@ +#!/bin/bash + +# Copyright 2019 The gVisor Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -xeo pipefail + +# Required input. +if ! [[ -v IMAGE ]]; then + echo "no image provided: set IMAGE." + exit 1 +fi + +# Parameters. +declare -r USERNAME=${USERNAME:-test} +declare -r KEYNAME=$(mktemp --tmpdir -u key-XXXXXX) +declare -r SSHKEYS=$(mktemp --tmpdir -u sshkeys-XXXXXX) +declare -r INSTANCE_NAME=$(mktemp -u test-XXXXXX | tr A-Z a-z) +declare -r MACHINE=${MACHINE:-n1-standard-1} +declare -r ZONE=${ZONE:-us-central1-f} +declare -r SUDO=${SUDO:-false} + +# This script is executed as a test rule, which will reset the value of HOME. +# Unfortunately, it is needed to load the gconfig credentials. We will reset +# HOME when we actually execute in the remote environment, defined below. +export HOME=$(eval echo ~$(whoami)) + +# Generate unique keys for this test. +[[ -f "${KEYNAME}" ]] || ssh-keygen -t rsa -N "" -f "${KEYNAME}" -C "${USERNAME}" +cat > "${SSHKEYS}" </dev/null; then + success=$((${success}+1)) + fi +done +if [[ "${success}" -eq "0" ]]; then + echo "connect timed out after ${timeout} seconds." + exit 1 +fi + +# Copy the local directory over. +tar czf - --dereference --exclude=.git . | + gcloud compute ssh \ + --ssh-key-file="${KEYNAME}" \ + --zone "${ZONE}" \ + "${USERNAME}"@"${INSTANCE_NAME}" -- tar xzf - + +# Execute the command remotely. +for cmd; do + # Setup relevant environment. + # + # N.B. This is not a complete test environment, but is complete enough to + # provide rudimentary sharding and test output support. + declare -a PREFIX=( "env" ) + if [[ -v TEST_SHARD_INDEX ]]; then + PREFIX+=( "TEST_SHARD_INDEX=${TEST_SHARD_INDEX}" ) + fi + if [[ -v TEST_SHARD_STATUS_FILE ]]; then + SHARD_STATUS_FILE=$(mktemp -u test-shard-status-XXXXXX) + PREFIX+=( "TEST_SHARD_STATUS_FILE=/tmp/${SHARD_STATUS_FILE}" ) + fi + if [[ -v TEST_TOTAL_SHARDS ]]; then + PREFIX+=( "TEST_TOTAL_SHARDS=${TEST_TOTAL_SHARDS}" ) + fi + if [[ -v TEST_TMPDIR ]]; then + REMOTE_TMPDIR=$(mktemp -u test-XXXXXX) + PREFIX+=( "TEST_TMPDIR=/tmp/${REMOTE_TMPDIR}" ) + # Create remotely. + gcloud compute ssh \ + --ssh-key-file="${KEYNAME}" \ + --zone "${ZONE}" \ + "${USERNAME}"@"${INSTANCE_NAME}" -- \ + mkdir -p "/tmp/${REMOTE_TMPDIR}" + fi + if [[ -v XML_OUTPUT_FILE ]]; then + TEST_XML_OUTPUT=$(mktemp -u xml-output-XXXXXX) + PREFIX+=( "XML_OUTPUT_FILE=/tmp/${TEST_XML_OUTPUT}" ) + fi + if [[ "${SUDO}" == "true" ]]; then + PREFIX+=( "sudo" "-E" ) + fi + + # Execute the command. + gcloud compute ssh \ + --ssh-key-file="${KEYNAME}" \ + --zone "${ZONE}" \ + "${USERNAME}"@"${INSTANCE_NAME}" -- \ + "${PREFIX[@]}" "${cmd}" + + # Collect relevant results. + if [[ -v TEST_SHARD_STATUS_FILE ]]; then + gcloud compute scp \ + --ssh-key-file="${KEYNAME}" \ + --zone "${ZONE}" \ + "${USERNAME}"@"${INSTANCE_NAME}":/tmp/"${SHARD_STATUS_FILE}" \ + "${TEST_SHARD_STATUS_FILE}" 2>/dev/null || true # Allowed to fail. + fi + if [[ -v XML_OUTPUT_FILE ]]; then + gcloud compute scp \ + --ssh-key-file="${KEYNAME}" \ + --zone "${ZONE}" \ + "${USERNAME}"@"${INSTANCE_NAME}":/tmp/"${TEST_XML_OUTPUT}" \ + "${XML_OUTPUT_FILE}" 2>/dev/null || true # Allowed to fail. + fi + + # Clean up the temporary directory. + if [[ -v TEST_TMPDIR ]]; then + gcloud compute ssh \ + --ssh-key-file="${KEYNAME}" \ + --zone "${ZONE}" \ + "${USERNAME}"@"${INSTANCE_NAME}" -- \ + rm -rf "/tmp/${REMOTE_TMPDIR}" + fi +done diff --git a/tools/images/test.cc b/tools/images/test.cc new file mode 100644 index 000000000..4f31d93c5 --- /dev/null +++ b/tools/images/test.cc @@ -0,0 +1,23 @@ +// Copyright 2020 The gVisor Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "gtest/gtest.h" + +namespace { + +TEST(Image, Sanity) { + // Do nothing. +} + +} // namespace diff --git a/tools/images/ubuntu1604/10_core.sh b/tools/images/ubuntu1604/10_core.sh new file mode 100755 index 000000000..46dda6bb1 --- /dev/null +++ b/tools/images/ubuntu1604/10_core.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +# Copyright 2019 The gVisor Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -xeo pipefail + +# Install all essential build tools. +apt-get update && apt-get -y install make git-core build-essential linux-headers-$(uname -r) pkg-config + +# Install a recent go toolchain. +if ! [[ -d /usr/local/go ]]; then + wget https://dl.google.com/go/go1.13.5.linux-amd64.tar.gz + tar -xvf go1.13.5.linux-amd64.tar.gz + mv go /usr/local +fi + +# Link the Go binary from /usr/bin; replacing anything there. +(cd /usr/bin && rm -f go && sudo ln -fs /usr/local/go/bin/go go) diff --git a/tools/images/ubuntu1604/20_bazel.sh b/tools/images/ubuntu1604/20_bazel.sh new file mode 100755 index 000000000..b33e1656c --- /dev/null +++ b/tools/images/ubuntu1604/20_bazel.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +# Copyright 2019 The gVisor Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -xeo pipefail + +declare -r BAZEL_VERSION=2.0.0 + +# Install bazel dependencies. +apt-get update && apt-get install -y openjdk-8-jdk-headless unzip + +# Use the release installer. +curl -L -o bazel-${BAZEL_VERSION}-installer-linux-x86_64.sh https://github.com/bazelbuild/bazel/releases/download/${BAZEL_VERSION}/bazel-${BAZEL_VERSION}-installer-linux-x86_64.sh +chmod a+x bazel-${BAZEL_VERSION}-installer-linux-x86_64.sh +./bazel-${BAZEL_VERSION}-installer-linux-x86_64.sh +rm -f bazel-${BAZEL_VERSION}-installer-linux-x86_64.sh diff --git a/tools/images/ubuntu1604/25_docker.sh b/tools/images/ubuntu1604/25_docker.sh new file mode 100755 index 000000000..1d3defcd3 --- /dev/null +++ b/tools/images/ubuntu1604/25_docker.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +# Copyright 2019 The gVisor Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Add dependencies. +apt-get update && apt-get -y install \ + apt-transport-https \ + ca-certificates \ + curl \ + gnupg-agent \ + software-properties-common + +# Install the key. +curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - + +# Add the repository. +add-apt-repository \ + "deb [arch=amd64] https://download.docker.com/linux/ubuntu \ + $(lsb_release -cs) \ + stable" + +# Install docker. +apt-get update && apt-get install -y docker-ce docker-ce-cli containerd.io diff --git a/tools/images/ubuntu1604/30_containerd.sh b/tools/images/ubuntu1604/30_containerd.sh new file mode 100755 index 000000000..a7472bd1c --- /dev/null +++ b/tools/images/ubuntu1604/30_containerd.sh @@ -0,0 +1,76 @@ +#!/bin/bash + +# Copyright 2019 The gVisor Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -xeo pipefail + +# Helper for Go packages below. +install_helper() { + PACKAGE="${1}" + TAG="${2}" + GOPATH="${3}" + + # Clone the repository. + mkdir -p "${GOPATH}"/src/$(dirname "${PACKAGE}") && \ + git clone https://"${PACKAGE}" "${GOPATH}"/src/"${PACKAGE}" + + # Checkout and build the repository. + (cd "${GOPATH}"/src/"${PACKAGE}" && \ + git checkout "${TAG}" && \ + GOPATH="${GOPATH}" make && \ + GOPATH="${GOPATH}" make install) +} + +# Install dependencies for the crictl tests. +apt-get install -y btrfs-tools libseccomp-dev + +# Install containerd & cri-tools. +GOPATH=$(mktemp -d --tmpdir gopathXXXXX) +install_helper github.com/containerd/containerd v1.2.2 "${GOPATH}" +install_helper github.com/kubernetes-sigs/cri-tools v1.11.0 "${GOPATH}" + +# Install gvisor-containerd-shim. +declare -r base="https://storage.googleapis.com/cri-containerd-staging/gvisor-containerd-shim" +declare -r latest=$(mktemp --tmpdir gvisor-containerd-shim-latest.XXXXXX) +declare -r shim_path=$(mktemp --tmpdir gvisor-containerd-shim.XXXXXX) +wget --no-verbose "${base}"/latest -O ${latest} +wget --no-verbose "${base}"/gvisor-containerd-shim-$(cat ${latest}) -O ${shim_path} +chmod +x ${shim_path} +mv ${shim_path} /usr/local/bin + +# Configure containerd-shim. +declare -r shim_config_path=/etc/containerd +declare -r shim_config_tmp_path=$(mktemp --tmpdir gvisor-containerd-shim.XXXXXX.toml) +mkdir -p ${shim_config_path} +cat > ${shim_config_tmp_path} <<-EOF + runc_shim = "/usr/local/bin/containerd-shim" + +[runsc_config] + debug = "true" + debug-log = "/tmp/runsc-logs/" + strace = "true" + file-access = "shared" +EOF +mv ${shim_config_tmp_path} ${shim_config_path} + +# Configure CNI. +(cd "${GOPATH}" && GOPATH="${GOPATH}" \ + src/github.com/containerd/containerd/script/setup/install-cni) + +# Cleanup the above. +rm -rf "${GOPATH}" +rm -rf "${latest}" +rm -rf "${shim_path}" +rm -rf "${shim_config_tmp_path}" diff --git a/tools/images/ubuntu1604/40_kokoro.sh b/tools/images/ubuntu1604/40_kokoro.sh new file mode 100755 index 000000000..5f2dfc858 --- /dev/null +++ b/tools/images/ubuntu1604/40_kokoro.sh @@ -0,0 +1,57 @@ +#!/bin/bash + +# Copyright 2019 The gVisor Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -xeo pipefail + +# Declare kokoro's required public keys. +declare -r ssh_public_keys=( + "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDg7L/ZaEauETWrPklUTky3kvxqQfe2Ax/2CsSqhNIGNMnK/8d79CHlmY9+dE1FFQ/RzKNCaltgy7XcN/fCYiCZr5jm2ZtnLuGNOTzupMNhaYiPL419qmL+5rZXt4/dWTrsHbFRACxT8j51PcRMO5wgbL0Bg2XXimbx8kDFaurL2gqduQYqlu4lxWCaJqOL71WogcimeL63Nq/yeH5PJPWpqE4P9VUQSwAzBWFK/hLeds/AiP3MgVS65qHBnhq0JsHy8JQsqjZbG7Iidt/Ll0+gqzEbi62gDIcczG4KC0iOVzDDP/1BxDtt1lKeA23ll769Fcm3rJyoBMYxjvdw1TDx sabujp@trigger.mtv.corp.google.com" + "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBNgGK/hCdjmulHfRE3hp4rZs38NCR8yAh0eDsztxqGcuXnuSnL7jOlRrbcQpremJ84omD4eKrIpwJUs+YokMdv4= sabujp@trigger.svl.corp.google.com" +) + +# Install dependencies. +apt-get update && apt-get install -y rsync coreutils python-psutil qemu-kvm python-pip python3-pip zip + +# junitparser is used to merge junit xml files. +pip install junitparser + +# We need a kbuilder user. +if useradd -c "kbuilder user" -m -s /bin/bash kbuilder; then + # User was added successfully; we add the relevant SSH keys here. + mkdir -p ~kbuilder/.ssh + (IFS=$'\n'; echo "${ssh_public_keys[*]}") > ~kbuilder/.ssh/authorized_keys + chmod 0600 ~kbuilder/.ssh/authorized_keys + chown -R kbuilder ~kbuilder/.ssh +fi + +# Give passwordless sudo access. +cat > /etc/sudoers.d/kokoro < Date: Wed, 22 Jan 2020 11:50:53 -0800 Subject: Toolchain version bumps. - bazel_toolchain to 2.0.2 - rules_go to 0.21.0 - Go toolchain to 1.13.6 - Use new proto lib archive. PiperOrigin-RevId: 290999410 --- WORKSPACE | 33 ++++++++++++++++----------------- test/BUILD | 4 ++-- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/WORKSPACE b/WORKSPACE index e2afc073c..5d2fc36f9 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -4,10 +4,10 @@ load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository") # Load go bazel rules and gazelle. http_archive( name = "io_bazel_rules_go", - sha256 = "b9aa86ec08a292b97ec4591cf578e020b35f98e12173bbd4a921f84f583aebd9", + sha256 = "b27e55d2dcc9e6020e17614ae6e0374818a3e3ce6f2024036e688ada24110444", urls = [ - "https://storage.googleapis.com/bazel-mirror/github.com/bazelbuild/rules_go/releases/download/v0.20.2/rules_go-v0.20.2.tar.gz", - "https://github.com/bazelbuild/rules_go/releases/download/v0.20.2/rules_go-v0.20.2.tar.gz", + "https://storage.googleapis.com/bazel-mirror/github.com/bazelbuild/rules_go/releases/download/v0.21.0/rules_go-v0.21.0.tar.gz", + "https://github.com/bazelbuild/rules_go/releases/download/v0.21.0/rules_go-v0.21.0.tar.gz", ], ) @@ -25,7 +25,7 @@ load("@io_bazel_rules_go//go:deps.bzl", "go_rules_dependencies", "go_register_to go_rules_dependencies() go_register_toolchains( - go_version = "1.13.4", + go_version = "1.13.6", nogo = "@//:nogo", ) @@ -46,18 +46,17 @@ http_archive( # Load protobuf dependencies. http_archive( - name = "com_google_protobuf", - sha256 = "532d2575d8c0992065bb19ec5fba13aa3683499726f6055c11b474f91a00bb0c", - strip_prefix = "protobuf-7f520092d9050d96fb4b707ad11a51701af4ce49", + name = "rules_proto", + sha256 = "602e7161d9195e50246177e7c55b2f39950a9cf7366f74ed5f22fd45750cd208", + strip_prefix = "rules_proto-97d8af4dc474595af3900dd85cb3a29ad28cc313", urls = [ - "https://mirror.bazel.build/github.com/protocolbuffers/protobuf/archive/7f520092d9050d96fb4b707ad11a51701af4ce49.zip", - "https://github.com/protocolbuffers/protobuf/archive/7f520092d9050d96fb4b707ad11a51701af4ce49.zip", + "https://mirror.bazel.build/github.com/bazelbuild/rules_proto/archive/97d8af4dc474595af3900dd85cb3a29ad28cc313.tar.gz", + "https://github.com/bazelbuild/rules_proto/archive/97d8af4dc474595af3900dd85cb3a29ad28cc313.tar.gz", ], ) - -load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps") - -protobuf_deps() +load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies", "rules_proto_toolchains") +rules_proto_dependencies() +rules_proto_toolchains() # Load python dependencies. git_repository( @@ -83,11 +82,11 @@ pip_install() # See releases at https://releases.bazel.build/bazel-toolchains.html http_archive( name = "bazel_toolchains", - sha256 = "a019fbd579ce5aed0239de865b2d8281dbb809efd537bf42e0d366783e8dec65", - strip_prefix = "bazel-toolchains-0.29.2", + sha256 = "a653c9d318e42b14c0ccd7ac50c4a2a276c0db1e39743ab88b5aa2f0bc9cf607", + strip_prefix = "bazel-toolchains-2.0.2", urls = [ - "https://mirror.bazel.build/github.com/bazelbuild/bazel-toolchains/archive/0.29.2.tar.gz", - "https://github.com/bazelbuild/bazel-toolchains/archive/0.29.2.tar.gz", + "https://github.com/bazelbuild/bazel-toolchains/releases/download/2.0.2/bazel-toolchains-2.0.2.tar.gz", + "https://mirror.bazel.build/github.com/bazelbuild/bazel-toolchains/archive/2.0.2.tar.gz", ], ) diff --git a/test/BUILD b/test/BUILD index 01fa01f2e..bf834d994 100644 --- a/test/BUILD +++ b/test/BUILD @@ -20,7 +20,7 @@ platform( remote_execution_properties = """ properties: { name: "container-image" - value:"docker://gcr.io/cloud-marketplace/google/rbe-ubuntu16-04@sha256:69c9f1652941d64a46f6f7358a44c1718f25caa5cb1ced4a58ccc5281cd183b5" + value:"docker://gcr.io/cloud-marketplace/google/rbe-ubuntu16-04@sha256:93f7e127196b9b653d39830c50f8b05d49ef6fd8739a9b5b8ab16e1df5399e50" } properties: { name: "dockerAddCapabilities" @@ -39,6 +39,6 @@ toolchain( ], target_compatible_with = [ ], - toolchain = "@bazel_toolchains//configs/ubuntu16_04_clang/9.0.0/bazel_0.28.0/cc:cc-compiler-k8", + toolchain = "@bazel_toolchains//configs/ubuntu16_04_clang/10.0.0/bazel_2.0.0/cc:cc-compiler-k8", toolchain_type = "@bazel_tools//tools/cpp:toolchain_type", ) -- cgit v1.2.3 From 5ab1213a6c405071546c783d6d93b4e9af52842e Mon Sep 17 00:00:00 2001 From: Jamie Liu Date: Wed, 22 Jan 2020 12:27:16 -0800 Subject: Move VFS2 handling of FD readability/writability to vfs.FileDescription. PiperOrigin-RevId: 291006713 --- pkg/sentry/fsimpl/ext/inode.go | 8 +++- pkg/sentry/fsimpl/kernfs/dynamic_bytes_file.go | 11 +++-- pkg/sentry/fsimpl/kernfs/fd_impl_util.go | 11 ++++- pkg/sentry/fsimpl/kernfs/kernfs_test.go | 18 +++++-- pkg/sentry/fsimpl/tmpfs/filesystem.go | 15 ++---- pkg/sentry/fsimpl/tmpfs/named_pipe.go | 5 +- pkg/sentry/fsimpl/tmpfs/regular_file.go | 14 +----- pkg/sentry/kernel/pipe/vfs.go | 12 ++--- pkg/sentry/vfs/file_description.go | 66 ++++++++++++++++++++++++-- pkg/sentry/vfs/permissions.go | 5 +- 10 files changed, 111 insertions(+), 54 deletions(-) diff --git a/pkg/sentry/fsimpl/ext/inode.go b/pkg/sentry/fsimpl/ext/inode.go index 8608805bf..191b39970 100644 --- a/pkg/sentry/fsimpl/ext/inode.go +++ b/pkg/sentry/fsimpl/ext/inode.go @@ -157,7 +157,9 @@ func (in *inode) open(rp *vfs.ResolvingPath, vfsd *vfs.Dentry, flags uint32) (*v switch in.impl.(type) { case *regularFile: var fd regularFileFD - fd.vfsfd.Init(&fd, flags, mnt, vfsd, &vfs.FileDescriptionOptions{}) + if err := fd.vfsfd.Init(&fd, flags, mnt, vfsd, &vfs.FileDescriptionOptions{}); err != nil { + return nil, err + } return &fd.vfsfd, nil case *directory: // Can't open directories writably. This check is not necessary for a read @@ -166,7 +168,9 @@ func (in *inode) open(rp *vfs.ResolvingPath, vfsd *vfs.Dentry, flags uint32) (*v return nil, syserror.EISDIR } var fd directoryFD - fd.vfsfd.Init(&fd, flags, mnt, vfsd, &vfs.FileDescriptionOptions{}) + if err := fd.vfsfd.Init(&fd, flags, mnt, vfsd, &vfs.FileDescriptionOptions{}); err != nil { + return nil, err + } return &fd.vfsfd, nil case *symlink: if flags&linux.O_PATH == 0 { diff --git a/pkg/sentry/fsimpl/kernfs/dynamic_bytes_file.go b/pkg/sentry/fsimpl/kernfs/dynamic_bytes_file.go index 606ca692d..75624e0b1 100644 --- a/pkg/sentry/fsimpl/kernfs/dynamic_bytes_file.go +++ b/pkg/sentry/fsimpl/kernfs/dynamic_bytes_file.go @@ -55,7 +55,9 @@ func (f *DynamicBytesFile) Init(creds *auth.Credentials, ino uint64, data vfs.Dy // Open implements Inode.Open. func (f *DynamicBytesFile) Open(rp *vfs.ResolvingPath, vfsd *vfs.Dentry, flags uint32) (*vfs.FileDescription, error) { fd := &DynamicBytesFD{} - fd.Init(rp.Mount(), vfsd, f.data, flags) + if err := fd.Init(rp.Mount(), vfsd, f.data, flags); err != nil { + return nil, err + } return &fd.vfsfd, nil } @@ -80,10 +82,13 @@ type DynamicBytesFD struct { } // Init initializes a DynamicBytesFD. -func (fd *DynamicBytesFD) Init(m *vfs.Mount, d *vfs.Dentry, data vfs.DynamicBytesSource, flags uint32) { +func (fd *DynamicBytesFD) Init(m *vfs.Mount, d *vfs.Dentry, data vfs.DynamicBytesSource, flags uint32) error { + if err := fd.vfsfd.Init(fd, flags, m, d, &vfs.FileDescriptionOptions{}); err != nil { + return err + } fd.inode = d.Impl().(*Dentry).inode fd.SetDataSource(data) - fd.vfsfd.Init(fd, flags, m, d, &vfs.FileDescriptionOptions{}) + return nil } // Seek implements vfs.FileDescriptionImpl.Seek. diff --git a/pkg/sentry/fsimpl/kernfs/fd_impl_util.go b/pkg/sentry/fsimpl/kernfs/fd_impl_util.go index bcf069b5f..5fa1fa67b 100644 --- a/pkg/sentry/fsimpl/kernfs/fd_impl_util.go +++ b/pkg/sentry/fsimpl/kernfs/fd_impl_util.go @@ -43,9 +43,16 @@ type GenericDirectoryFD struct { } // Init initializes a GenericDirectoryFD. -func (fd *GenericDirectoryFD) Init(m *vfs.Mount, d *vfs.Dentry, children *OrderedChildren, flags uint32) { +func (fd *GenericDirectoryFD) Init(m *vfs.Mount, d *vfs.Dentry, children *OrderedChildren, flags uint32) error { + if vfs.AccessTypesForOpenFlags(flags)&vfs.MayWrite != 0 { + // Can't open directories for writing. + return syserror.EISDIR + } + if err := fd.vfsfd.Init(fd, flags, m, d, &vfs.FileDescriptionOptions{}); err != nil { + return err + } fd.children = children - fd.vfsfd.Init(fd, flags, m, d, &vfs.FileDescriptionOptions{}) + return nil } // VFSFileDescription returns a pointer to the vfs.FileDescription representing diff --git a/pkg/sentry/fsimpl/kernfs/kernfs_test.go b/pkg/sentry/fsimpl/kernfs/kernfs_test.go index a5fdfbde5..aa3fe76ee 100644 --- a/pkg/sentry/fsimpl/kernfs/kernfs_test.go +++ b/pkg/sentry/fsimpl/kernfs/kernfs_test.go @@ -115,7 +115,9 @@ func (fs *filesystem) newReadonlyDir(creds *auth.Credentials, mode linux.FileMod func (d *readonlyDir) Open(rp *vfs.ResolvingPath, vfsd *vfs.Dentry, flags uint32) (*vfs.FileDescription, error) { fd := &kernfs.GenericDirectoryFD{} - fd.Init(rp.Mount(), vfsd, &d.OrderedChildren, flags) + if err := fd.Init(rp.Mount(), vfsd, &d.OrderedChildren, flags); err != nil { + return nil, err + } return fd.VFSFileDescription(), nil } @@ -225,7 +227,9 @@ func TestReadStaticFile(t *testing.T) { defer sys.Destroy() pop := sys.PathOpAtRoot("file1") - fd, err := sys.VFS.OpenAt(sys.Ctx, sys.Creds, &pop, &vfs.OpenOptions{}) + fd, err := sys.VFS.OpenAt(sys.Ctx, sys.Creds, &pop, &vfs.OpenOptions{ + Flags: linux.O_RDONLY, + }) if err != nil { t.Fatalf("OpenAt for PathOperation %+v failed: %v", pop, err) } @@ -258,7 +262,9 @@ func TestCreateNewFileInStaticDir(t *testing.T) { // Close the file. The file should persist. fd.DecRef() - fd, err = sys.VFS.OpenAt(sys.Ctx, sys.Creds, &pop, &vfs.OpenOptions{}) + fd, err = sys.VFS.OpenAt(sys.Ctx, sys.Creds, &pop, &vfs.OpenOptions{ + Flags: linux.O_RDONLY, + }) if err != nil { t.Fatalf("OpenAt(pop:%+v) = %+v failed: %v", pop, fd, err) } @@ -272,7 +278,9 @@ func TestDirFDReadWrite(t *testing.T) { defer sys.Destroy() pop := sys.PathOpAtRoot("/") - fd, err := sys.VFS.OpenAt(sys.Ctx, sys.Creds, &pop, &vfs.OpenOptions{}) + fd, err := sys.VFS.OpenAt(sys.Ctx, sys.Creds, &pop, &vfs.OpenOptions{ + Flags: linux.O_RDONLY, + }) if err != nil { t.Fatalf("OpenAt for PathOperation %+v failed: %v", pop, err) } @@ -282,7 +290,7 @@ func TestDirFDReadWrite(t *testing.T) { if _, err := fd.Read(sys.Ctx, usermem.BytesIOSequence([]byte{}), vfs.ReadOptions{}); err != syserror.EISDIR { t.Fatalf("Read for directory FD failed with unexpected error: %v", err) } - if _, err := fd.Write(sys.Ctx, usermem.BytesIOSequence([]byte{}), vfs.WriteOptions{}); err != syserror.EISDIR { + if _, err := fd.Write(sys.Ctx, usermem.BytesIOSequence([]byte{}), vfs.WriteOptions{}); err != syserror.EBADF { t.Fatalf("Write for directory FD failed with unexpected error: %v", err) } } diff --git a/pkg/sentry/fsimpl/tmpfs/filesystem.go b/pkg/sentry/fsimpl/tmpfs/filesystem.go index 4cd7e9aea..a9f66a42a 100644 --- a/pkg/sentry/fsimpl/tmpfs/filesystem.go +++ b/pkg/sentry/fsimpl/tmpfs/filesystem.go @@ -337,19 +337,12 @@ func (d *dentry) open(ctx context.Context, rp *vfs.ResolvingPath, flags uint32, return nil, err } } - mnt := rp.Mount() switch impl := d.inode.impl.(type) { case *regularFile: var fd regularFileFD - fd.readable = vfs.MayReadFileWithOpenFlags(flags) - fd.writable = vfs.MayWriteFileWithOpenFlags(flags) - if fd.writable { - if err := mnt.CheckBeginWrite(); err != nil { - return nil, err - } - // mnt.EndWrite() is called by regularFileFD.Release(). + if err := fd.vfsfd.Init(&fd, flags, rp.Mount(), &d.vfsd, &vfs.FileDescriptionOptions{}); err != nil { + return nil, err } - fd.vfsfd.Init(&fd, flags, mnt, &d.vfsd, &vfs.FileDescriptionOptions{}) if flags&linux.O_TRUNC != 0 { impl.mu.Lock() impl.data.Truncate(0, impl.memFile) @@ -363,7 +356,9 @@ func (d *dentry) open(ctx context.Context, rp *vfs.ResolvingPath, flags uint32, return nil, syserror.EISDIR } var fd directoryFD - fd.vfsfd.Init(&fd, flags, mnt, &d.vfsd, &vfs.FileDescriptionOptions{}) + if err := fd.vfsfd.Init(&fd, flags, rp.Mount(), &d.vfsd, &vfs.FileDescriptionOptions{}); err != nil { + return nil, err + } return &fd.vfsfd, nil case *symlink: // Can't open symlinks without O_PATH (which is unimplemented). diff --git a/pkg/sentry/fsimpl/tmpfs/named_pipe.go b/pkg/sentry/fsimpl/tmpfs/named_pipe.go index 40bde54de..482aabd52 100644 --- a/pkg/sentry/fsimpl/tmpfs/named_pipe.go +++ b/pkg/sentry/fsimpl/tmpfs/named_pipe.go @@ -50,11 +50,10 @@ type namedPipeFD struct { func newNamedPipeFD(ctx context.Context, np *namedPipe, rp *vfs.ResolvingPath, vfsd *vfs.Dentry, flags uint32) (*vfs.FileDescription, error) { var err error var fd namedPipeFD - fd.VFSPipeFD, err = np.pipe.NewVFSPipeFD(ctx, rp, vfsd, &fd.vfsfd, flags) + fd.VFSPipeFD, err = np.pipe.NewVFSPipeFD(ctx, vfsd, &fd.vfsfd, flags) if err != nil { return nil, err } - mnt := rp.Mount() - fd.vfsfd.Init(&fd, flags, mnt, vfsd, &vfs.FileDescriptionOptions{}) + fd.vfsfd.Init(&fd, flags, rp.Mount(), vfsd, &vfs.FileDescriptionOptions{}) return &fd.vfsfd, nil } diff --git a/pkg/sentry/fsimpl/tmpfs/regular_file.go b/pkg/sentry/fsimpl/tmpfs/regular_file.go index 5fa70cc6d..7c633c1b0 100644 --- a/pkg/sentry/fsimpl/tmpfs/regular_file.go +++ b/pkg/sentry/fsimpl/tmpfs/regular_file.go @@ -101,10 +101,6 @@ func (rf *regularFile) truncate(size uint64) (bool, error) { type regularFileFD struct { fileDescription - // These are immutable. - readable bool - writable bool - // off is the file offset. off is accessed using atomic memory operations. // offMu serializes operations that may mutate off. off int64 @@ -113,16 +109,11 @@ type regularFileFD struct { // Release implements vfs.FileDescriptionImpl.Release. func (fd *regularFileFD) Release() { - if fd.writable { - fd.vfsfd.VirtualDentry().Mount().EndWrite() - } + // noop } // PRead implements vfs.FileDescriptionImpl.PRead. func (fd *regularFileFD) PRead(ctx context.Context, dst usermem.IOSequence, offset int64, opts vfs.ReadOptions) (int64, error) { - if !fd.readable { - return 0, syserror.EINVAL - } if offset < 0 { return 0, syserror.EINVAL } @@ -147,9 +138,6 @@ func (fd *regularFileFD) Read(ctx context.Context, dst usermem.IOSequence, opts // PWrite implements vfs.FileDescriptionImpl.PWrite. func (fd *regularFileFD) PWrite(ctx context.Context, src usermem.IOSequence, offset int64, opts vfs.WriteOptions) (int64, error) { - if !fd.writable { - return 0, syserror.EINVAL - } if offset < 0 { return 0, syserror.EINVAL } diff --git a/pkg/sentry/kernel/pipe/vfs.go b/pkg/sentry/kernel/pipe/vfs.go index bf7461cbb..6f83e3cee 100644 --- a/pkg/sentry/kernel/pipe/vfs.go +++ b/pkg/sentry/kernel/pipe/vfs.go @@ -66,7 +66,7 @@ func NewVFSPipe(sizeBytes, atomicIOBytes int64) *VFSPipe { // for read and write will succeed both in blocking and nonblocking mode. POSIX // leaves this behavior undefined. This can be used to open a FIFO for writing // while there are no readers available." - fifo(7) -func (vp *VFSPipe) NewVFSPipeFD(ctx context.Context, rp *vfs.ResolvingPath, vfsd *vfs.Dentry, vfsfd *vfs.FileDescription, flags uint32) (*VFSPipeFD, error) { +func (vp *VFSPipe) NewVFSPipeFD(ctx context.Context, vfsd *vfs.Dentry, vfsfd *vfs.FileDescription, flags uint32) (*VFSPipeFD, error) { vp.mu.Lock() defer vp.mu.Unlock() @@ -76,7 +76,7 @@ func (vp *VFSPipe) NewVFSPipeFD(ctx context.Context, rp *vfs.ResolvingPath, vfsd return nil, syserror.EINVAL } - vfd, err := vp.open(rp, vfsd, vfsfd, flags) + vfd, err := vp.open(vfsd, vfsfd, flags) if err != nil { return nil, err } @@ -118,19 +118,13 @@ func (vp *VFSPipe) NewVFSPipeFD(ctx context.Context, rp *vfs.ResolvingPath, vfsd } // Preconditions: vp.mu must be held. -func (vp *VFSPipe) open(rp *vfs.ResolvingPath, vfsd *vfs.Dentry, vfsfd *vfs.FileDescription, flags uint32) (*VFSPipeFD, error) { +func (vp *VFSPipe) open(vfsd *vfs.Dentry, vfsfd *vfs.FileDescription, flags uint32) (*VFSPipeFD, error) { var fd VFSPipeFD fd.flags = flags fd.readable = vfs.MayReadFileWithOpenFlags(flags) fd.writable = vfs.MayWriteFileWithOpenFlags(flags) fd.vfsfd = vfsfd fd.pipe = &vp.pipe - if fd.writable { - // The corresponding Mount.EndWrite() is in VFSPipe.Release(). - if err := rp.Mount().CheckBeginWrite(); err != nil { - return nil, err - } - } switch { case fd.readable && fd.writable: diff --git a/pkg/sentry/vfs/file_description.go b/pkg/sentry/vfs/file_description.go index 6afe280bc..51c95c2d9 100644 --- a/pkg/sentry/vfs/file_description.go +++ b/pkg/sentry/vfs/file_description.go @@ -49,8 +49,23 @@ type FileDescription struct { // A reference is held on vd. vd is immutable. vd VirtualDentry + // opts contains options passed to FileDescription.Init(). opts is + // immutable. opts FileDescriptionOptions + // readable is MayReadFileWithOpenFlags(statusFlags). readable is + // immutable. + // + // readable is analogous to Linux's FMODE_READ. + readable bool + + // writable is MayWriteFileWithOpenFlags(statusFlags). If writable is true, + // the FileDescription holds a write count on vd.mount. writable is + // immutable. + // + // writable is analogous to Linux's FMODE_WRITE. + writable bool + // impl is the FileDescriptionImpl associated with this Filesystem. impl is // immutable. This should be the last field in FileDescription. impl FileDescriptionImpl @@ -77,10 +92,17 @@ type FileDescriptionOptions struct { UseDentryMetadata bool } -// Init must be called before first use of fd. It takes references on mnt and -// d. statusFlags is the initial file description status flags, which is -// usually the full set of flags passed to open(2). -func (fd *FileDescription) Init(impl FileDescriptionImpl, statusFlags uint32, mnt *Mount, d *Dentry, opts *FileDescriptionOptions) { +// Init must be called before first use of fd. If it succeeds, it takes +// references on mnt and d. statusFlags is the initial file description status +// flags, which is usually the full set of flags passed to open(2). +func (fd *FileDescription) Init(impl FileDescriptionImpl, statusFlags uint32, mnt *Mount, d *Dentry, opts *FileDescriptionOptions) error { + writable := MayWriteFileWithOpenFlags(statusFlags) + if writable { + if err := mnt.CheckBeginWrite(); err != nil { + return err + } + } + fd.refs = 1 fd.statusFlags = statusFlags | linux.O_LARGEFILE fd.vd = VirtualDentry{ @@ -89,7 +111,10 @@ func (fd *FileDescription) Init(impl FileDescriptionImpl, statusFlags uint32, mn } fd.vd.IncRef() fd.opts = *opts + fd.readable = MayReadFileWithOpenFlags(statusFlags) + fd.writable = writable fd.impl = impl + return nil } // IncRef increments fd's reference count. @@ -117,6 +142,9 @@ func (fd *FileDescription) TryIncRef() bool { func (fd *FileDescription) DecRef() { if refs := atomic.AddInt64(&fd.refs, -1); refs == 0 { fd.impl.Release() + if fd.writable { + fd.vd.mount.EndWrite() + } fd.vd.DecRef() } else if refs < 0 { panic("FileDescription.DecRef() called without holding a reference") @@ -194,6 +222,16 @@ func (fd *FileDescription) SetStatusFlags(ctx context.Context, creds *auth.Crede return nil } +// IsReadable returns true if fd was opened for reading. +func (fd *FileDescription) IsReadable() bool { + return fd.readable +} + +// IsWritable returns true if fd was opened for writing. +func (fd *FileDescription) IsWritable() bool { + return fd.writable +} + // Impl returns the FileDescriptionImpl associated with fd. func (fd *FileDescription) Impl() FileDescriptionImpl { return fd.impl @@ -241,6 +279,8 @@ type FileDescriptionImpl interface { // Errors: // // - If opts.Flags specifies unsupported options, PRead returns EOPNOTSUPP. + // + // Preconditions: The FileDescription was opened for reading. PRead(ctx context.Context, dst usermem.IOSequence, offset int64, opts ReadOptions) (int64, error) // Read is similar to PRead, but does not specify an offset. @@ -254,6 +294,8 @@ type FileDescriptionImpl interface { // Errors: // // - If opts.Flags specifies unsupported options, Read returns EOPNOTSUPP. + // + // Preconditions: The FileDescription was opened for reading. Read(ctx context.Context, dst usermem.IOSequence, opts ReadOptions) (int64, error) // PWrite writes src to the file, starting at the given offset, and returns @@ -268,6 +310,8 @@ type FileDescriptionImpl interface { // // - If opts.Flags specifies unsupported options, PWrite returns // EOPNOTSUPP. + // + // Preconditions: The FileDescription was opened for writing. PWrite(ctx context.Context, src usermem.IOSequence, offset int64, opts WriteOptions) (int64, error) // Write is similar to PWrite, but does not specify an offset, which is @@ -281,6 +325,8 @@ type FileDescriptionImpl interface { // Errors: // // - If opts.Flags specifies unsupported options, Write returns EOPNOTSUPP. + // + // Preconditions: The FileDescription was opened for writing. Write(ctx context.Context, src usermem.IOSequence, opts WriteOptions) (int64, error) // IterDirents invokes cb on each entry in the directory represented by the @@ -411,11 +457,17 @@ func (fd *FileDescription) StatFS(ctx context.Context) (linux.Statfs, error) { // offset, and returns the number of bytes read. PRead is permitted to return // partial reads with a nil error. func (fd *FileDescription) PRead(ctx context.Context, dst usermem.IOSequence, offset int64, opts ReadOptions) (int64, error) { + if !fd.readable { + return 0, syserror.EBADF + } return fd.impl.PRead(ctx, dst, offset, opts) } // Read is similar to PRead, but does not specify an offset. func (fd *FileDescription) Read(ctx context.Context, dst usermem.IOSequence, opts ReadOptions) (int64, error) { + if !fd.readable { + return 0, syserror.EBADF + } return fd.impl.Read(ctx, dst, opts) } @@ -423,11 +475,17 @@ func (fd *FileDescription) Read(ctx context.Context, dst usermem.IOSequence, opt // offset, and returns the number of bytes written. PWrite is permitted to // return partial writes with a nil error. func (fd *FileDescription) PWrite(ctx context.Context, src usermem.IOSequence, offset int64, opts WriteOptions) (int64, error) { + if !fd.writable { + return 0, syserror.EBADF + } return fd.impl.PWrite(ctx, src, offset, opts) } // Write is similar to PWrite, but does not specify an offset. func (fd *FileDescription) Write(ctx context.Context, src usermem.IOSequence, opts WriteOptions) (int64, error) { + if !fd.writable { + return 0, syserror.EBADF + } return fd.impl.Write(ctx, src, opts) } diff --git a/pkg/sentry/vfs/permissions.go b/pkg/sentry/vfs/permissions.go index d279d05ca..f664581f4 100644 --- a/pkg/sentry/vfs/permissions.go +++ b/pkg/sentry/vfs/permissions.go @@ -94,14 +94,13 @@ func GenericCheckPermissions(creds *auth.Credentials, ats AccessTypes, isDir boo // the set of accesses permitted for the opened file: // // - O_TRUNC causes MayWrite to be set in the returned AccessTypes (since it -// mutates the file), but does not permit the opened to write to the file +// mutates the file), but does not permit writing to the open file description // thereafter. // // - "Linux reserves the special, nonstandard access mode 3 (binary 11) in // flags to mean: check for read and write permission on the file and return a // file descriptor that can't be used for reading or writing." - open(2). Thus -// AccessTypesForOpenFlags returns MayRead|MayWrite in this case, but -// filesystems are responsible for ensuring that access is denied. +// AccessTypesForOpenFlags returns MayRead|MayWrite in this case. // // Use May{Read,Write}FileWithOpenFlags() for these checks instead. func AccessTypesForOpenFlags(flags uint32) AccessTypes { -- cgit v1.2.3 From 1d97adaa6d73dd897bb4e89d4533936a95003951 Mon Sep 17 00:00:00 2001 From: Ghanan Gowripalan Date: Wed, 22 Jan 2020 14:50:32 -0800 Subject: Use embedded mutex pattern for stack.NIC - Wrap NIC's fields that should only be accessed while holding the mutex in an anonymous struct with the embedded mutex. - Make sure NIC's spoofing and promiscuous mode flags are only read while holding the NIC's mutex. - Use the correct endpoint when sending DAD messages. - Do not hold the NIC's lock when sending DAD messages. This change does not introduce any behaviour changes. Tests: Existing tests continue to pass. PiperOrigin-RevId: 291036251 --- pkg/tcpip/stack/ndp.go | 181 +++++++++++++++------------------ pkg/tcpip/stack/ndp_test.go | 45 ++++----- pkg/tcpip/stack/nic.go | 236 +++++++++++++++++++++++++------------------- 3 files changed, 234 insertions(+), 228 deletions(-) diff --git a/pkg/tcpip/stack/ndp.go b/pkg/tcpip/stack/ndp.go index 7d4b41dfa..d983ac390 100644 --- a/pkg/tcpip/stack/ndp.go +++ b/pkg/tcpip/stack/ndp.go @@ -15,7 +15,6 @@ package stack import ( - "fmt" "log" "math/rand" "time" @@ -429,8 +428,13 @@ func (ndp *ndpState) startDuplicateAddressDetection(addr tcpip.Address, ref *ref return tcpip.ErrAddressFamilyNotSupported } - // Should not attempt to perform DAD on an address that is currently in - // the DAD process. + if ref.getKind() != permanentTentative { + // The endpoint should be marked as tentative since we are starting DAD. + log.Fatalf("ndpdad: addr %s is not tentative on NIC(%d)", addr, ndp.nic.ID()) + } + + // Should not attempt to perform DAD on an address that is currently in the + // DAD process. if _, ok := ndp.dad[addr]; ok { // Should never happen because we should only ever call this function for // newly created addresses. If we attemped to "add" an address that already @@ -438,77 +442,79 @@ func (ndp *ndpState) startDuplicateAddressDetection(addr tcpip.Address, ref *ref // address, or its reference count would have been increased without doing // the work that would have been done for an address that was brand new. // See NIC.addAddressLocked. - panic(fmt.Sprintf("ndpdad: already performing DAD for addr %s on NIC(%d)", addr, ndp.nic.ID())) + log.Fatalf("ndpdad: already performing DAD for addr %s on NIC(%d)", addr, ndp.nic.ID()) } remaining := ndp.configs.DupAddrDetectTransmits - - { - done, err := ndp.doDuplicateAddressDetection(addr, remaining, ref) - if err != nil { - return err - } - if done { - return nil - } + if remaining == 0 { + ref.setKind(permanent) + return nil } - remaining-- - var done bool var timer *time.Timer - timer = time.AfterFunc(ndp.configs.RetransmitTimer, func() { - var d bool - var err *tcpip.Error - - // doDadIteration does a single iteration of the DAD loop. - // - // Returns true if the integrator needs to be informed of DAD - // completing. - doDadIteration := func() bool { - ndp.nic.mu.Lock() - defer ndp.nic.mu.Unlock() - - if done { - // If we reach this point, it means that the DAD - // timer fired after another goroutine already - // obtained the NIC lock and stopped DAD before - // this function obtained the NIC lock. Simply - // return here and do nothing further. - return false - } + // We initially start a timer to fire immediately because some of the DAD work + // cannot be done while holding the NIC's lock. This is effectively the same + // as starting a goroutine but we use a timer that fires immediately so we can + // reset it for the next DAD iteration. + timer = time.AfterFunc(0, func() { + ndp.nic.mu.RLock() + if done { + // If we reach this point, it means that the DAD timer fired after + // another goroutine already obtained the NIC lock and stopped DAD + // before this function obtained the NIC lock. Simply return here and do + // nothing further. + ndp.nic.mu.RUnlock() + return + } - ref, ok := ndp.nic.endpoints[NetworkEndpointID{addr}] - if !ok { - // This should never happen. - // We should have an endpoint for addr since we - // are still performing DAD on it. If the - // endpoint does not exist, but we are doing DAD - // on it, then we started DAD at some point, but - // forgot to stop it when the endpoint was - // deleted. - panic(fmt.Sprintf("ndpdad: unrecognized addr %s for NIC(%d)", addr, ndp.nic.ID())) - } + if ref.getKind() != permanentTentative { + // The endpoint should still be marked as tentative since we are still + // performing DAD on it. + log.Fatalf("ndpdad: addr %s is no longer tentative on NIC(%d)", addr, ndp.nic.ID()) + } - d, err = ndp.doDuplicateAddressDetection(addr, remaining, ref) - if err != nil || d { - delete(ndp.dad, addr) + dadDone := remaining == 0 + ndp.nic.mu.RUnlock() - if err != nil { - log.Printf("ndpdad: Error occured during DAD iteration for addr (%s) on NIC(%d); err = %s", addr, ndp.nic.ID(), err) - } + var err *tcpip.Error + if !dadDone { + err = ndp.sendDADPacket(addr) + } - // Let the integrator know DAD has completed. - return true - } + ndp.nic.mu.Lock() + if done { + // If we reach this point, it means that DAD was stopped after we released + // the NIC's read lock and before we obtained the write lock. + ndp.nic.mu.Unlock() + return + } + if dadDone { + // DAD has resolved. + ref.setKind(permanent) + } else if err == nil { + // DAD is not done and we had no errors when sending the last NDP NS, + // schedule the next DAD timer. remaining-- timer.Reset(ndp.nic.stack.ndpConfigs.RetransmitTimer) - return false + + ndp.nic.mu.Unlock() + return + } + + // At this point we know that either DAD is done or we hit an error sending + // the last NDP NS. Either way, clean up addr's DAD state and let the + // integrator know DAD has completed. + delete(ndp.dad, addr) + ndp.nic.mu.Unlock() + + if err != nil { + log.Printf("ndpdad: error occured during DAD iteration for addr (%s) on NIC(%d); err = %s", addr, ndp.nic.ID(), err) } - if doDadIteration() && ndp.nic.stack.ndpDisp != nil { - ndp.nic.stack.ndpDisp.OnDuplicateAddressDetectionStatus(ndp.nic.ID(), addr, d, err) + if ndpDisp := ndp.nic.stack.ndpDisp; ndpDisp != nil { + ndpDisp.OnDuplicateAddressDetectionStatus(ndp.nic.ID(), addr, dadDone, err) } }) @@ -520,45 +526,16 @@ func (ndp *ndpState) startDuplicateAddressDetection(addr tcpip.Address, ref *ref return nil } -// doDuplicateAddressDetection is called on every iteration of the timer, and -// when DAD starts. -// -// It handles resolving the address (if there are no more NS to send), or -// sending the next NS if there are more NS to send. -// -// This function must only be called by IPv6 addresses that are currently -// tentative. -// -// The NIC that ndp belongs to (n) MUST be locked. +// sendDADPacket sends a NS message to see if any nodes on ndp's NIC's link owns +// addr. // -// Returns true if DAD has resolved; false if DAD is still ongoing. -func (ndp *ndpState) doDuplicateAddressDetection(addr tcpip.Address, remaining uint8, ref *referencedNetworkEndpoint) (bool, *tcpip.Error) { - if ref.getKind() != permanentTentative { - // The endpoint should still be marked as tentative - // since we are still performing DAD on it. - panic(fmt.Sprintf("ndpdad: addr %s is not tentative on NIC(%d)", addr, ndp.nic.ID())) - } - - if remaining == 0 { - // DAD has resolved. - ref.setKind(permanent) - return true, nil - } - - // Send a new NS. +// addr must be a tentative IPv6 address on ndp's NIC. +func (ndp *ndpState) sendDADPacket(addr tcpip.Address) *tcpip.Error { snmc := header.SolicitedNodeAddr(addr) - snmcRef, ok := ndp.nic.endpoints[NetworkEndpointID{snmc}] - if !ok { - // This should never happen as if we have the - // address, we should have the solicited-node - // address. - panic(fmt.Sprintf("ndpdad: NIC(%d) is not in the solicited-node multicast group (%s) but it has addr %s", ndp.nic.ID(), snmc, addr)) - } - snmcRef.incRef() - // Use the unspecified address as the source address when performing - // DAD. - r := makeRoute(header.IPv6ProtocolNumber, header.IPv6Any, snmc, ndp.nic.linkEP.LinkAddress(), snmcRef, false, false) + // Use the unspecified address as the source address when performing DAD. + ref := ndp.nic.getRefOrCreateTemp(header.IPv6ProtocolNumber, header.IPv6Any, NeverPrimaryEndpoint, forceSpoofing) + r := makeRoute(header.IPv6ProtocolNumber, header.IPv6Any, snmc, ndp.nic.linkEP.LinkAddress(), ref, false, false) defer r.Release() hdr := buffer.NewPrependable(int(r.MaxHeaderLength()) + header.ICMPv6NeighborSolicitMinimumSize) @@ -569,15 +546,19 @@ func (ndp *ndpState) doDuplicateAddressDetection(addr tcpip.Address, remaining u pkt.SetChecksum(header.ICMPv6Checksum(pkt, r.LocalAddress, r.RemoteAddress, buffer.VectorisedView{})) sent := r.Stats().ICMP.V6PacketsSent - if err := r.WritePacket(nil, NetworkHeaderParams{Protocol: header.ICMPv6ProtocolNumber, TTL: header.NDPHopLimit, TOS: DefaultTOS}, tcpip.PacketBuffer{ - Header: hdr, - }); err != nil { + if err := r.WritePacket(nil, + NetworkHeaderParams{ + Protocol: header.ICMPv6ProtocolNumber, + TTL: header.NDPHopLimit, + TOS: DefaultTOS, + }, tcpip.PacketBuffer{Header: hdr}, + ); err != nil { sent.Dropped.Increment() - return false, err + return err } sent.NeighborSolicit.Increment() - return false, nil + return nil } // stopDuplicateAddressDetection ends a running Duplicate Address Detection @@ -1212,7 +1193,7 @@ func (ndp *ndpState) startSolicitingRouters() { ndp.rtrSolicitTimer = time.AfterFunc(delay, func() { // Send an RS message with the unspecified source address. - ref := ndp.nic.getRefOrCreateTemp(header.IPv6ProtocolNumber, header.IPv6Any, NeverPrimaryEndpoint, true) + ref := ndp.nic.getRefOrCreateTemp(header.IPv6ProtocolNumber, header.IPv6Any, NeverPrimaryEndpoint, forceSpoofing) r := makeRoute(header.IPv6ProtocolNumber, header.IPv6Any, header.IPv6AllRoutersMulticastAddress, ndp.nic.linkEP.LinkAddress(), ref, false, false) defer r.Release() diff --git a/pkg/tcpip/stack/ndp_test.go b/pkg/tcpip/stack/ndp_test.go index 1a52e0e68..376681b30 100644 --- a/pkg/tcpip/stack/ndp_test.go +++ b/pkg/tcpip/stack/ndp_test.go @@ -301,6 +301,8 @@ func (n *ndpDispatcher) OnDHCPv6Configuration(nicID tcpip.NICID, configuration s // Included in the subtests is a test to make sure that an invalid // RetransmitTimer (<1ms) values get fixed to the default RetransmitTimer of 1s. func TestDADResolve(t *testing.T) { + const nicID = 1 + tests := []struct { name string dupAddrDetectTransmits uint8 @@ -331,44 +333,36 @@ func TestDADResolve(t *testing.T) { opts.NDPConfigs.RetransmitTimer = test.retransTimer opts.NDPConfigs.DupAddrDetectTransmits = test.dupAddrDetectTransmits - e := channel.New(10, 1280, linkAddr1) + e := channel.New(int(test.dupAddrDetectTransmits), 1280, linkAddr1) s := stack.New(opts) - if err := s.CreateNIC(1, e); err != nil { - t.Fatalf("CreateNIC(_) = %s", err) + if err := s.CreateNIC(nicID, e); err != nil { + t.Fatalf("CreateNIC(%d, _) = %s", nicID, err) } - if err := s.AddAddress(1, header.IPv6ProtocolNumber, addr1); err != nil { - t.Fatalf("AddAddress(_, %d, %s) = %s", header.IPv6ProtocolNumber, addr1, err) - } - - stat := s.Stats().ICMP.V6PacketsSent.NeighborSolicit - - // Should have sent an NDP NS immediately. - if got := stat.Value(); got != 1 { - t.Fatalf("got NeighborSolicit = %d, want = 1", got) - + if err := s.AddAddress(nicID, header.IPv6ProtocolNumber, addr1); err != nil { + t.Fatalf("AddAddress(%d, %d, %s) = %s", nicID, header.IPv6ProtocolNumber, addr1, err) } // Address should not be considered bound to the NIC yet // (DAD ongoing). - addr, err := s.GetMainNICAddress(1, header.IPv6ProtocolNumber) + addr, err := s.GetMainNICAddress(nicID, header.IPv6ProtocolNumber) if err != nil { - t.Fatalf("got stack.GetMainNICAddress(_, _) = (_, %v), want = (_, nil)", err) + t.Fatalf("got stack.GetMainNICAddress(%d, %d) = (_, %v), want = (_, nil)", nicID, header.IPv6ProtocolNumber, err) } if want := (tcpip.AddressWithPrefix{}); addr != want { - t.Fatalf("got stack.GetMainNICAddress(_, _) = (%s, nil), want = (%s, nil)", addr, want) + t.Fatalf("got stack.GetMainNICAddress(%d, %d) = (%s, nil), want = (%s, nil)", nicID, header.IPv6ProtocolNumber, addr, want) } // Wait for the remaining time - some delta (500ms), to // make sure the address is still not resolved. const delta = 500 * time.Millisecond time.Sleep(test.expectedRetransmitTimer*time.Duration(test.dupAddrDetectTransmits) - delta) - addr, err = s.GetMainNICAddress(1, header.IPv6ProtocolNumber) + addr, err = s.GetMainNICAddress(nicID, header.IPv6ProtocolNumber) if err != nil { - t.Fatalf("got stack.GetMainNICAddress(_, _) = (_, %v), want = (_, nil)", err) + t.Fatalf("got stack.GetMainNICAddress(%d, %d) = (_, %v), want = (_, nil)", nicID, header.IPv6ProtocolNumber, err) } if want := (tcpip.AddressWithPrefix{}); addr != want { - t.Fatalf("got stack.GetMainNICAddress(_, _) = (%s, nil), want = (%s, nil)", addr, want) + t.Fatalf("got stack.GetMainNICAddress(%d, %d) = (%s, nil), want = (%s, nil)", nicID, header.IPv6ProtocolNumber, addr, want) } // Wait for DAD to resolve. @@ -385,8 +379,8 @@ func TestDADResolve(t *testing.T) { if e.err != nil { t.Fatal("got DAD error: ", e.err) } - if e.nicID != 1 { - t.Fatalf("got DAD event w/ nicID = %d, want = 1", e.nicID) + if e.nicID != nicID { + t.Fatalf("got DAD event w/ nicID = %d, want = %d", e.nicID, nicID) } if e.addr != addr1 { t.Fatalf("got DAD event w/ addr = %s, want = %s", addr, addr1) @@ -395,16 +389,16 @@ func TestDADResolve(t *testing.T) { t.Fatal("got DAD event w/ resolved = false, want = true") } } - addr, err = s.GetMainNICAddress(1, header.IPv6ProtocolNumber) + addr, err = s.GetMainNICAddress(nicID, header.IPv6ProtocolNumber) if err != nil { - t.Fatalf("stack.GetMainNICAddress(_, _) err = %s", err) + t.Fatalf("got stack.GetMainNICAddress(%d, %d) = (_, %v), want = (_, nil)", nicID, header.IPv6ProtocolNumber, err) } if addr.Address != addr1 { - t.Fatalf("got stack.GetMainNICAddress(_, _) = %s, want = %s", addr, addr1) + t.Fatalf("got stack.GetMainNICAddress(%d, %d) = %s, want = %s", nicID, header.IPv6ProtocolNumber, addr, addr1) } // Should not have sent any more NS messages. - if got := stat.Value(); got != uint64(test.dupAddrDetectTransmits) { + if got := s.Stats().ICMP.V6PacketsSent.NeighborSolicit.Value(); got != uint64(test.dupAddrDetectTransmits) { t.Fatalf("got NeighborSolicit = %d, want = %d", got, test.dupAddrDetectTransmits) } @@ -425,7 +419,6 @@ func TestDADResolve(t *testing.T) { } }) } - } // TestDADFail tests to make sure that the DAD process fails if another node is diff --git a/pkg/tcpip/stack/nic.go b/pkg/tcpip/stack/nic.go index de88c0bfa..79556a36f 100644 --- a/pkg/tcpip/stack/nic.go +++ b/pkg/tcpip/stack/nic.go @@ -35,24 +35,21 @@ type NIC struct { linkEP LinkEndpoint context NICContext - mu sync.RWMutex - spoofing bool - promiscuous bool - primary map[tcpip.NetworkProtocolNumber][]*referencedNetworkEndpoint - endpoints map[NetworkEndpointID]*referencedNetworkEndpoint - addressRanges []tcpip.Subnet - mcastJoins map[NetworkEndpointID]int32 - // packetEPs is protected by mu, but the contained PacketEndpoint - // values are not. - packetEPs map[tcpip.NetworkProtocolNumber][]PacketEndpoint - stats NICStats - // ndp is the NDP related state for NIC. - // - // Note, read and write operations on ndp require that the NIC is - // appropriately locked. - ndp ndpState + mu struct { + sync.RWMutex + spoofing bool + promiscuous bool + primary map[tcpip.NetworkProtocolNumber][]*referencedNetworkEndpoint + endpoints map[NetworkEndpointID]*referencedNetworkEndpoint + addressRanges []tcpip.Subnet + mcastJoins map[NetworkEndpointID]int32 + // packetEPs is protected by mu, but the contained PacketEndpoint + // values are not. + packetEPs map[tcpip.NetworkProtocolNumber][]PacketEndpoint + ndp ndpState + } } // NICStats includes transmitted and received stats. @@ -97,15 +94,11 @@ func newNIC(stack *Stack, id tcpip.NICID, name string, ep LinkEndpoint, ctx NICC // of IPv6 is supported on this endpoint's LinkEndpoint. nic := &NIC{ - stack: stack, - id: id, - name: name, - linkEP: ep, - context: ctx, - primary: make(map[tcpip.NetworkProtocolNumber][]*referencedNetworkEndpoint), - endpoints: make(map[NetworkEndpointID]*referencedNetworkEndpoint), - mcastJoins: make(map[NetworkEndpointID]int32), - packetEPs: make(map[tcpip.NetworkProtocolNumber][]PacketEndpoint), + stack: stack, + id: id, + name: name, + linkEP: ep, + context: ctx, stats: NICStats{ Tx: DirectionStats{ Packets: &tcpip.StatCounter{}, @@ -116,22 +109,26 @@ func newNIC(stack *Stack, id tcpip.NICID, name string, ep LinkEndpoint, ctx NICC Bytes: &tcpip.StatCounter{}, }, }, - ndp: ndpState{ - configs: stack.ndpConfigs, - dad: make(map[tcpip.Address]dadState), - defaultRouters: make(map[tcpip.Address]defaultRouterState), - onLinkPrefixes: make(map[tcpip.Subnet]onLinkPrefixState), - autoGenAddresses: make(map[tcpip.Address]autoGenAddressState), - }, } - nic.ndp.nic = nic + nic.mu.primary = make(map[tcpip.NetworkProtocolNumber][]*referencedNetworkEndpoint) + nic.mu.endpoints = make(map[NetworkEndpointID]*referencedNetworkEndpoint) + nic.mu.mcastJoins = make(map[NetworkEndpointID]int32) + nic.mu.packetEPs = make(map[tcpip.NetworkProtocolNumber][]PacketEndpoint) + nic.mu.ndp = ndpState{ + nic: nic, + configs: stack.ndpConfigs, + dad: make(map[tcpip.Address]dadState), + defaultRouters: make(map[tcpip.Address]defaultRouterState), + onLinkPrefixes: make(map[tcpip.Subnet]onLinkPrefixState), + autoGenAddresses: make(map[tcpip.Address]autoGenAddressState), + } // Register supported packet endpoint protocols. for _, netProto := range header.Ethertypes { - nic.packetEPs[netProto] = []PacketEndpoint{} + nic.mu.packetEPs[netProto] = []PacketEndpoint{} } for _, netProto := range stack.networkProtocols { - nic.packetEPs[netProto.Number()] = []PacketEndpoint{} + nic.mu.packetEPs[netProto.Number()] = []PacketEndpoint{} } return nic @@ -215,7 +212,7 @@ func (n *NIC) enable() *tcpip.Error { // and default routers). Therefore, soliciting RAs from other routers on // a link is unnecessary for routers. if !n.stack.forwarding { - n.ndp.startSolicitingRouters() + n.mu.ndp.startSolicitingRouters() } return nil @@ -230,8 +227,8 @@ func (n *NIC) becomeIPv6Router() { n.mu.Lock() defer n.mu.Unlock() - n.ndp.cleanupHostOnlyState() - n.ndp.stopSolicitingRouters() + n.mu.ndp.cleanupHostOnlyState() + n.mu.ndp.stopSolicitingRouters() } // becomeIPv6Host transitions n into an IPv6 host. @@ -242,7 +239,7 @@ func (n *NIC) becomeIPv6Host() { n.mu.Lock() defer n.mu.Unlock() - n.ndp.startSolicitingRouters() + n.mu.ndp.startSolicitingRouters() } // attachLinkEndpoint attaches the NIC to the endpoint, which will enable it @@ -254,13 +251,13 @@ func (n *NIC) attachLinkEndpoint() { // setPromiscuousMode enables or disables promiscuous mode. func (n *NIC) setPromiscuousMode(enable bool) { n.mu.Lock() - n.promiscuous = enable + n.mu.promiscuous = enable n.mu.Unlock() } func (n *NIC) isPromiscuousMode() bool { n.mu.RLock() - rv := n.promiscuous + rv := n.mu.promiscuous n.mu.RUnlock() return rv } @@ -272,7 +269,7 @@ func (n *NIC) isLoopback() bool { // setSpoofing enables or disables address spoofing. func (n *NIC) setSpoofing(enable bool) { n.mu.Lock() - n.spoofing = enable + n.mu.spoofing = enable n.mu.Unlock() } @@ -291,8 +288,8 @@ func (n *NIC) primaryEndpoint(protocol tcpip.NetworkProtocolNumber, remoteAddr t defer n.mu.RUnlock() var deprecatedEndpoint *referencedNetworkEndpoint - for _, r := range n.primary[protocol] { - if !r.isValidForOutgoing() { + for _, r := range n.mu.primary[protocol] { + if !r.isValidForOutgoingRLocked() { continue } @@ -342,7 +339,7 @@ func (n *NIC) primaryIPv6Endpoint(remoteAddr tcpip.Address) *referencedNetworkEn n.mu.RLock() defer n.mu.RUnlock() - primaryAddrs := n.primary[header.IPv6ProtocolNumber] + primaryAddrs := n.mu.primary[header.IPv6ProtocolNumber] if len(primaryAddrs) == 0 { return nil @@ -425,7 +422,7 @@ func (n *NIC) primaryIPv6Endpoint(remoteAddr tcpip.Address) *referencedNetworkEn // hasPermanentAddrLocked returns true if n has a permanent (including currently // tentative) address, addr. func (n *NIC) hasPermanentAddrLocked(addr tcpip.Address) bool { - ref, ok := n.endpoints[NetworkEndpointID{addr}] + ref, ok := n.mu.endpoints[NetworkEndpointID{addr}] if !ok { return false @@ -436,24 +433,54 @@ func (n *NIC) hasPermanentAddrLocked(addr tcpip.Address) bool { return kind == permanent || kind == permanentTentative } +type getRefBehaviour int + +const ( + // spoofing indicates that the NIC's spoofing flag should be observed when + // getting a NIC's referenced network endpoint. + spoofing getRefBehaviour = iota + + // promiscuous indicates that the NIC's promiscuous flag should be observed + // when getting a NIC's referenced network endpoint. + promiscuous + + // forceSpoofing indicates that the NIC should be assumed to be spoofing, + // regardless of what the NIC's spoofing flag is when getting a NIC's + // referenced network endpoint. + forceSpoofing +) + func (n *NIC) getRef(protocol tcpip.NetworkProtocolNumber, dst tcpip.Address) *referencedNetworkEndpoint { - return n.getRefOrCreateTemp(protocol, dst, CanBePrimaryEndpoint, n.promiscuous) + return n.getRefOrCreateTemp(protocol, dst, CanBePrimaryEndpoint, promiscuous) } // findEndpoint finds the endpoint, if any, with the given address. func (n *NIC) findEndpoint(protocol tcpip.NetworkProtocolNumber, address tcpip.Address, peb PrimaryEndpointBehavior) *referencedNetworkEndpoint { - return n.getRefOrCreateTemp(protocol, address, peb, n.spoofing) + return n.getRefOrCreateTemp(protocol, address, peb, spoofing) } // getRefEpOrCreateTemp returns the referenced network endpoint for the given -// protocol and address. If none exists a temporary one may be created if -// we are in promiscuous mode or spoofing. -func (n *NIC) getRefOrCreateTemp(protocol tcpip.NetworkProtocolNumber, address tcpip.Address, peb PrimaryEndpointBehavior, spoofingOrPromiscuous bool) *referencedNetworkEndpoint { +// protocol and address. +// +// If none exists a temporary one may be created if we are in promiscuous mode +// or spoofing. Promiscuous mode will only be checked if promiscuous is true. +// Similarly, spoofing will only be checked if spoofing is true. +func (n *NIC) getRefOrCreateTemp(protocol tcpip.NetworkProtocolNumber, address tcpip.Address, peb PrimaryEndpointBehavior, tempRef getRefBehaviour) *referencedNetworkEndpoint { id := NetworkEndpointID{address} n.mu.RLock() - if ref, ok := n.endpoints[id]; ok { + var spoofingOrPromiscuous bool + switch tempRef { + case spoofing: + spoofingOrPromiscuous = n.mu.spoofing + case promiscuous: + spoofingOrPromiscuous = n.mu.promiscuous + case forceSpoofing: + spoofingOrPromiscuous = true + } + + if ref, ok := n.mu.endpoints[id]; ok { // An endpoint with this id exists, check if it can be used and return it. switch ref.getKind() { case permanentExpired: @@ -474,7 +501,7 @@ func (n *NIC) getRefOrCreateTemp(protocol tcpip.NetworkProtocolNumber, address t // the caller or if the address is found in the NIC's subnets. createTempEP := spoofingOrPromiscuous if !createTempEP { - for _, sn := range n.addressRanges { + for _, sn := range n.mu.addressRanges { // Skip the subnet address. if address == sn.ID() { continue @@ -502,7 +529,7 @@ func (n *NIC) getRefOrCreateTemp(protocol tcpip.NetworkProtocolNumber, address t // endpoint, create a new "temporary" endpoint. It will only exist while // there's a route through it. n.mu.Lock() - if ref, ok := n.endpoints[id]; ok { + if ref, ok := n.mu.endpoints[id]; ok { // No need to check the type as we are ok with expired endpoints at this // point. if ref.tryIncRef() { @@ -543,7 +570,7 @@ func (n *NIC) addAddressLocked(protocolAddress tcpip.ProtocolAddress, peb Primar // Sanity check. id := NetworkEndpointID{LocalAddress: protocolAddress.AddressWithPrefix.Address} - if ref, ok := n.endpoints[id]; ok { + if ref, ok := n.mu.endpoints[id]; ok { // Endpoint already exists. if kind != permanent { return nil, tcpip.ErrDuplicateAddress @@ -562,7 +589,7 @@ func (n *NIC) addAddressLocked(protocolAddress tcpip.ProtocolAddress, peb Primar ref.deprecated = deprecated ref.configType = configType - refs := n.primary[ref.protocol] + refs := n.mu.primary[ref.protocol] for i, r := range refs { if r == ref { switch peb { @@ -572,9 +599,9 @@ func (n *NIC) addAddressLocked(protocolAddress tcpip.ProtocolAddress, peb Primar if i == 0 { return ref, nil } - n.primary[r.protocol] = append(refs[:i], refs[i+1:]...) + n.mu.primary[r.protocol] = append(refs[:i], refs[i+1:]...) case NeverPrimaryEndpoint: - n.primary[r.protocol] = append(refs[:i], refs[i+1:]...) + n.mu.primary[r.protocol] = append(refs[:i], refs[i+1:]...) return ref, nil } } @@ -637,13 +664,13 @@ func (n *NIC) addAddressLocked(protocolAddress tcpip.ProtocolAddress, peb Primar } } - n.endpoints[id] = ref + n.mu.endpoints[id] = ref n.insertPrimaryEndpointLocked(ref, peb) // If we are adding a tentative IPv6 address, start DAD. if isIPv6Unicast && kind == permanentTentative { - if err := n.ndp.startDuplicateAddressDetection(protocolAddress.AddressWithPrefix.Address, ref); err != nil { + if err := n.mu.ndp.startDuplicateAddressDetection(protocolAddress.AddressWithPrefix.Address, ref); err != nil { return nil, err } } @@ -668,8 +695,8 @@ func (n *NIC) AllAddresses() []tcpip.ProtocolAddress { n.mu.RLock() defer n.mu.RUnlock() - addrs := make([]tcpip.ProtocolAddress, 0, len(n.endpoints)) - for nid, ref := range n.endpoints { + addrs := make([]tcpip.ProtocolAddress, 0, len(n.mu.endpoints)) + for nid, ref := range n.mu.endpoints { // Don't include tentative, expired or temporary endpoints to // avoid confusion and prevent the caller from using those. switch ref.getKind() { @@ -695,7 +722,7 @@ func (n *NIC) PrimaryAddresses() []tcpip.ProtocolAddress { defer n.mu.RUnlock() var addrs []tcpip.ProtocolAddress - for proto, list := range n.primary { + for proto, list := range n.mu.primary { for _, ref := range list { // Don't include tentative, expired or tempory endpoints // to avoid confusion and prevent the caller from using @@ -726,7 +753,7 @@ func (n *NIC) primaryAddress(proto tcpip.NetworkProtocolNumber) tcpip.AddressWit n.mu.RLock() defer n.mu.RUnlock() - list, ok := n.primary[proto] + list, ok := n.mu.primary[proto] if !ok { return tcpip.AddressWithPrefix{} } @@ -769,7 +796,7 @@ func (n *NIC) primaryAddress(proto tcpip.NetworkProtocolNumber) tcpip.AddressWit // address. func (n *NIC) AddAddressRange(protocol tcpip.NetworkProtocolNumber, subnet tcpip.Subnet) { n.mu.Lock() - n.addressRanges = append(n.addressRanges, subnet) + n.mu.addressRanges = append(n.mu.addressRanges, subnet) n.mu.Unlock() } @@ -778,13 +805,13 @@ func (n *NIC) RemoveAddressRange(subnet tcpip.Subnet) { n.mu.Lock() // Use the same underlying array. - tmp := n.addressRanges[:0] - for _, sub := range n.addressRanges { + tmp := n.mu.addressRanges[:0] + for _, sub := range n.mu.addressRanges { if sub != subnet { tmp = append(tmp, sub) } } - n.addressRanges = tmp + n.mu.addressRanges = tmp n.mu.Unlock() } @@ -793,8 +820,8 @@ func (n *NIC) RemoveAddressRange(subnet tcpip.Subnet) { func (n *NIC) AddressRanges() []tcpip.Subnet { n.mu.RLock() defer n.mu.RUnlock() - sns := make([]tcpip.Subnet, 0, len(n.addressRanges)+len(n.endpoints)) - for nid := range n.endpoints { + sns := make([]tcpip.Subnet, 0, len(n.mu.addressRanges)+len(n.mu.endpoints)) + for nid := range n.mu.endpoints { sn, err := tcpip.NewSubnet(nid.LocalAddress, tcpip.AddressMask(strings.Repeat("\xff", len(nid.LocalAddress)))) if err != nil { // This should never happen as the mask has been carefully crafted to @@ -803,7 +830,7 @@ func (n *NIC) AddressRanges() []tcpip.Subnet { } sns = append(sns, sn) } - return append(sns, n.addressRanges...) + return append(sns, n.mu.addressRanges...) } // insertPrimaryEndpointLocked adds r to n's primary endpoint list as required @@ -813,9 +840,9 @@ func (n *NIC) AddressRanges() []tcpip.Subnet { func (n *NIC) insertPrimaryEndpointLocked(r *referencedNetworkEndpoint, peb PrimaryEndpointBehavior) { switch peb { case CanBePrimaryEndpoint: - n.primary[r.protocol] = append(n.primary[r.protocol], r) + n.mu.primary[r.protocol] = append(n.mu.primary[r.protocol], r) case FirstPrimaryEndpoint: - n.primary[r.protocol] = append([]*referencedNetworkEndpoint{r}, n.primary[r.protocol]...) + n.mu.primary[r.protocol] = append([]*referencedNetworkEndpoint{r}, n.mu.primary[r.protocol]...) } } @@ -827,7 +854,7 @@ func (n *NIC) removeEndpointLocked(r *referencedNetworkEndpoint) { // and was waiting (on the lock) to be removed and 2) the same address was // re-added in the meantime by removing this endpoint from the list and // adding a new one. - if n.endpoints[id] != r { + if n.mu.endpoints[id] != r { return } @@ -835,11 +862,11 @@ func (n *NIC) removeEndpointLocked(r *referencedNetworkEndpoint) { panic("Reference count dropped to zero before being removed") } - delete(n.endpoints, id) - refs := n.primary[r.protocol] + delete(n.mu.endpoints, id) + refs := n.mu.primary[r.protocol] for i, ref := range refs { if ref == r { - n.primary[r.protocol] = append(refs[:i], refs[i+1:]...) + n.mu.primary[r.protocol] = append(refs[:i], refs[i+1:]...) break } } @@ -854,7 +881,7 @@ func (n *NIC) removeEndpoint(r *referencedNetworkEndpoint) { } func (n *NIC) removePermanentAddressLocked(addr tcpip.Address) *tcpip.Error { - r, ok := n.endpoints[NetworkEndpointID{addr}] + r, ok := n.mu.endpoints[NetworkEndpointID{addr}] if !ok { return tcpip.ErrBadLocalAddress } @@ -870,13 +897,13 @@ func (n *NIC) removePermanentAddressLocked(addr tcpip.Address) *tcpip.Error { // If we are removing a tentative IPv6 unicast address, stop // DAD. if kind == permanentTentative { - n.ndp.stopDuplicateAddressDetection(addr) + n.mu.ndp.stopDuplicateAddressDetection(addr) } // If we are removing an address generated via SLAAC, cleanup // its SLAAC resources and notify the integrator. if r.configType == slaac { - n.ndp.cleanupAutoGenAddrResourcesAndNotify(addr) + n.mu.ndp.cleanupAutoGenAddrResourcesAndNotify(addr) } } @@ -926,7 +953,7 @@ func (n *NIC) joinGroupLocked(protocol tcpip.NetworkProtocolNumber, addr tcpip.A // outlined in RFC 3810 section 5. id := NetworkEndpointID{addr} - joins := n.mcastJoins[id] + joins := n.mu.mcastJoins[id] if joins == 0 { netProto, ok := n.stack.networkProtocols[protocol] if !ok { @@ -942,7 +969,7 @@ func (n *NIC) joinGroupLocked(protocol tcpip.NetworkProtocolNumber, addr tcpip.A return err } } - n.mcastJoins[id] = joins + 1 + n.mu.mcastJoins[id] = joins + 1 return nil } @@ -960,7 +987,7 @@ func (n *NIC) leaveGroup(addr tcpip.Address) *tcpip.Error { // before leaveGroupLocked is called. func (n *NIC) leaveGroupLocked(addr tcpip.Address) *tcpip.Error { id := NetworkEndpointID{addr} - joins := n.mcastJoins[id] + joins := n.mu.mcastJoins[id] switch joins { case 0: // There are no joins with this address on this NIC. @@ -971,7 +998,7 @@ func (n *NIC) leaveGroupLocked(addr tcpip.Address) *tcpip.Error { return err } } - n.mcastJoins[id] = joins - 1 + n.mu.mcastJoins[id] = joins - 1 return nil } @@ -1006,12 +1033,12 @@ func (n *NIC) DeliverNetworkPacket(linkEP LinkEndpoint, remote, local tcpip.Link // Are any packet sockets listening for this network protocol? n.mu.RLock() - packetEPs := n.packetEPs[protocol] + packetEPs := n.mu.packetEPs[protocol] // Check whether there are packet sockets listening for every protocol. // If we received a packet with protocol EthernetProtocolAll, then the // previous for loop will have handled it. if protocol != header.EthernetProtocolAll { - packetEPs = append(packetEPs, n.packetEPs[header.EthernetProtocolAll]...) + packetEPs = append(packetEPs, n.mu.packetEPs[header.EthernetProtocolAll]...) } n.mu.RUnlock() for _, ep := range packetEPs { @@ -1060,8 +1087,8 @@ func (n *NIC) DeliverNetworkPacket(linkEP LinkEndpoint, remote, local tcpip.Link // Found a NIC. n := r.ref.nic n.mu.RLock() - ref, ok := n.endpoints[NetworkEndpointID{dst}] - ok = ok && ref.isValidForOutgoing() && ref.tryIncRef() + ref, ok := n.mu.endpoints[NetworkEndpointID{dst}] + ok = ok && ref.isValidForOutgoingRLocked() && ref.tryIncRef() n.mu.RUnlock() if ok { r.RemoteAddress = src @@ -1181,7 +1208,7 @@ func (n *NIC) Stack() *Stack { // false. It will only return true if the address is associated with the NIC // AND it is tentative. func (n *NIC) isAddrTentative(addr tcpip.Address) bool { - ref, ok := n.endpoints[NetworkEndpointID{addr}] + ref, ok := n.mu.endpoints[NetworkEndpointID{addr}] if !ok { return false } @@ -1197,7 +1224,7 @@ func (n *NIC) dupTentativeAddrDetected(addr tcpip.Address) *tcpip.Error { n.mu.Lock() defer n.mu.Unlock() - ref, ok := n.endpoints[NetworkEndpointID{addr}] + ref, ok := n.mu.endpoints[NetworkEndpointID{addr}] if !ok { return tcpip.ErrBadAddress } @@ -1217,7 +1244,7 @@ func (n *NIC) setNDPConfigs(c NDPConfigurations) { c.validate() n.mu.Lock() - n.ndp.configs = c + n.mu.ndp.configs = c n.mu.Unlock() } @@ -1226,7 +1253,7 @@ func (n *NIC) handleNDPRA(ip tcpip.Address, ra header.NDPRouterAdvert) { n.mu.Lock() defer n.mu.Unlock() - n.ndp.handleRA(ip, ra) + n.mu.ndp.handleRA(ip, ra) } type networkEndpointKind int32 @@ -1268,11 +1295,11 @@ func (n *NIC) registerPacketEndpoint(netProto tcpip.NetworkProtocolNumber, ep Pa n.mu.Lock() defer n.mu.Unlock() - eps, ok := n.packetEPs[netProto] + eps, ok := n.mu.packetEPs[netProto] if !ok { return tcpip.ErrNotSupported } - n.packetEPs[netProto] = append(eps, ep) + n.mu.packetEPs[netProto] = append(eps, ep) return nil } @@ -1281,14 +1308,14 @@ func (n *NIC) unregisterPacketEndpoint(netProto tcpip.NetworkProtocolNumber, ep n.mu.Lock() defer n.mu.Unlock() - eps, ok := n.packetEPs[netProto] + eps, ok := n.mu.packetEPs[netProto] if !ok { return } for i, epOther := range eps { if epOther == ep { - n.packetEPs[netProto] = append(eps[:i], eps[i+1:]...) + n.mu.packetEPs[netProto] = append(eps[:i], eps[i+1:]...) return } } @@ -1346,14 +1373,19 @@ func (r *referencedNetworkEndpoint) setKind(kind networkEndpointKind) { // packet. It requires the endpoint to not be marked expired (i.e., its address // has been removed), or the NIC to be in spoofing mode. func (r *referencedNetworkEndpoint) isValidForOutgoing() bool { - return r.getKind() != permanentExpired || r.nic.spoofing + r.nic.mu.RLock() + defer r.nic.mu.RUnlock() + + return r.isValidForOutgoingRLocked() } -// isValidForIncoming returns true if the endpoint can accept an incoming -// packet. It requires the endpoint to not be marked expired (i.e., its address -// has been removed), or the NIC to be in promiscuous mode. -func (r *referencedNetworkEndpoint) isValidForIncoming() bool { - return r.getKind() != permanentExpired || r.nic.promiscuous +// isValidForOutgoingRLocked returns true if the endpoint can be used to send +// out a packet. It requires the endpoint to not be marked expired (i.e., its +// address has been removed), or the NIC to be in spoofing mode. +// +// r's NIC must be read locked. +func (r *referencedNetworkEndpoint) isValidForOutgoingRLocked() bool { + return r.getKind() != permanentExpired || r.nic.mu.spoofing } // decRef decrements the ref count and cleans up the endpoint once it reaches -- cgit v1.2.3 From 896bd654b6622d20cbaf8e82b4554a5375addf81 Mon Sep 17 00:00:00 2001 From: Rahat Mahmood Date: Wed, 22 Jan 2020 15:14:43 -0800 Subject: De-duplicate common test functionality for VFS2 filesystems. PiperOrigin-RevId: 291041576 --- pkg/sentry/fsimpl/kernfs/kernfs_test.go | 12 +- pkg/sentry/fsimpl/proc/tasks_test.go | 411 +++++++++++--------------------- pkg/sentry/fsimpl/sys/sys_test.go | 4 +- pkg/sentry/fsimpl/testutil/testutil.go | 149 ++++++++++-- 4 files changed, 278 insertions(+), 298 deletions(-) diff --git a/pkg/sentry/fsimpl/kernfs/kernfs_test.go b/pkg/sentry/fsimpl/kernfs/kernfs_test.go index aa3fe76ee..fade59491 100644 --- a/pkg/sentry/fsimpl/kernfs/kernfs_test.go +++ b/pkg/sentry/fsimpl/kernfs/kernfs_test.go @@ -212,7 +212,7 @@ func TestMkdirGetDentry(t *testing.T) { defer sys.Destroy() pop := sys.PathOpAtRoot("dir1/a new directory") - if err := sys.VFS.MkdirAt(sys.Ctx, sys.Creds, &pop, &vfs.MkdirOptions{Mode: 0755}); err != nil { + if err := sys.VFS.MkdirAt(sys.Ctx, sys.Creds, pop, &vfs.MkdirOptions{Mode: 0755}); err != nil { t.Fatalf("MkdirAt for PathOperation %+v failed: %v", pop, err) } sys.GetDentryOrDie(pop).DecRef() @@ -227,7 +227,7 @@ func TestReadStaticFile(t *testing.T) { defer sys.Destroy() pop := sys.PathOpAtRoot("file1") - fd, err := sys.VFS.OpenAt(sys.Ctx, sys.Creds, &pop, &vfs.OpenOptions{ + fd, err := sys.VFS.OpenAt(sys.Ctx, sys.Creds, pop, &vfs.OpenOptions{ Flags: linux.O_RDONLY, }) if err != nil { @@ -254,7 +254,7 @@ func TestCreateNewFileInStaticDir(t *testing.T) { pop := sys.PathOpAtRoot("dir1/newfile") opts := &vfs.OpenOptions{Flags: linux.O_CREAT | linux.O_EXCL, Mode: defaultMode} - fd, err := sys.VFS.OpenAt(sys.Ctx, sys.Creds, &pop, opts) + fd, err := sys.VFS.OpenAt(sys.Ctx, sys.Creds, pop, opts) if err != nil { t.Fatalf("OpenAt(pop:%+v, opts:%+v) failed: %v", pop, opts, err) } @@ -262,7 +262,7 @@ func TestCreateNewFileInStaticDir(t *testing.T) { // Close the file. The file should persist. fd.DecRef() - fd, err = sys.VFS.OpenAt(sys.Ctx, sys.Creds, &pop, &vfs.OpenOptions{ + fd, err = sys.VFS.OpenAt(sys.Ctx, sys.Creds, pop, &vfs.OpenOptions{ Flags: linux.O_RDONLY, }) if err != nil { @@ -278,7 +278,7 @@ func TestDirFDReadWrite(t *testing.T) { defer sys.Destroy() pop := sys.PathOpAtRoot("/") - fd, err := sys.VFS.OpenAt(sys.Ctx, sys.Creds, &pop, &vfs.OpenOptions{ + fd, err := sys.VFS.OpenAt(sys.Ctx, sys.Creds, pop, &vfs.OpenOptions{ Flags: linux.O_RDONLY, }) if err != nil { @@ -309,7 +309,7 @@ func TestDirFDIterDirents(t *testing.T) { defer sys.Destroy() pop := sys.PathOpAtRoot("/") - sys.AssertDirectoryContains(&pop, map[string]testutil.DirentType{ + sys.AssertAllDirentTypes(sys.ListDirents(pop), map[string]testutil.DirentType{ "dir1": linux.DT_DIR, "dir2": linux.DT_DIR, "file1": linux.DT_REG, diff --git a/pkg/sentry/fsimpl/proc/tasks_test.go b/pkg/sentry/fsimpl/proc/tasks_test.go index 41977d816..2c1635f33 100644 --- a/pkg/sentry/fsimpl/proc/tasks_test.go +++ b/pkg/sentry/fsimpl/proc/tasks_test.go @@ -44,100 +44,47 @@ var ( proc3 = vfs.Dirent{Type: linux.DT_DIR, NextOff: 258 + 3 + 1} ) -type testIterDirentsCallback struct { - dirents []vfs.Dirent -} - -func (t *testIterDirentsCallback) Handle(d vfs.Dirent) bool { - t.dirents = append(t.dirents, d) - return true -} - -func checkDots(dirs []vfs.Dirent) ([]vfs.Dirent, error) { - if got := len(dirs); got < 2 { - return dirs, fmt.Errorf("wrong number of dirents, want at least: 2, got: %d: %v", got, dirs) - } - for i, want := range []string{".", ".."} { - if got := dirs[i].Name; got != want { - return dirs, fmt.Errorf("wrong name, want: %s, got: %s", want, got) - } - if got := dirs[i].Type; got != linux.DT_DIR { - return dirs, fmt.Errorf("wrong type, want: %d, got: %d", linux.DT_DIR, got) - } - } - return dirs[2:], nil -} - -func checkTasksStaticFiles(gots []vfs.Dirent) ([]vfs.Dirent, error) { - wants := map[string]vfs.Dirent{ - "cpuinfo": {Type: linux.DT_REG}, - "loadavg": {Type: linux.DT_REG}, - "meminfo": {Type: linux.DT_REG}, - "mounts": {Type: linux.DT_LNK}, - "net": {Type: linux.DT_DIR}, - "self": selfLink, - "stat": {Type: linux.DT_REG}, - "sys": {Type: linux.DT_DIR}, - "thread-self": threadSelfLink, - "uptime": {Type: linux.DT_REG}, - "version": {Type: linux.DT_REG}, - } - return checkFiles(gots, wants) -} - -func checkTaskStaticFiles(gots []vfs.Dirent) ([]vfs.Dirent, error) { - wants := map[string]vfs.Dirent{ - "auxv": {Type: linux.DT_REG}, - "cgroup": {Type: linux.DT_REG}, - "cmdline": {Type: linux.DT_REG}, - "comm": {Type: linux.DT_REG}, - "environ": {Type: linux.DT_REG}, - "gid_map": {Type: linux.DT_REG}, - "io": {Type: linux.DT_REG}, - "maps": {Type: linux.DT_REG}, - "ns": {Type: linux.DT_DIR}, - "smaps": {Type: linux.DT_REG}, - "stat": {Type: linux.DT_REG}, - "statm": {Type: linux.DT_REG}, - "status": {Type: linux.DT_REG}, - "task": {Type: linux.DT_DIR}, - "uid_map": {Type: linux.DT_REG}, - } - return checkFiles(gots, wants) -} - -func checkFiles(gots []vfs.Dirent, wants map[string]vfs.Dirent) ([]vfs.Dirent, error) { - // Go over all files, when there is a match, the file is removed from both - // 'gots' and 'wants'. wants is expected to reach 0, as all files must - // be present. Remaining files in 'gots', is returned to caller to decide - // whether this is valid or not. - for i := 0; i < len(gots); i++ { - got := gots[i] - want, ok := wants[got.Name] - if !ok { - continue - } - if want.Type != got.Type { - return gots, fmt.Errorf("wrong file type, want: %v, got: %v: %+v", want.Type, got.Type, got) - } - if want.NextOff != 0 && want.NextOff != got.NextOff { - return gots, fmt.Errorf("wrong dirent offset, want: %v, got: %v: %+v", want.NextOff, got.NextOff, got) - } - - delete(wants, got.Name) - gots = append(gots[0:i], gots[i+1:]...) - i-- - } - if len(wants) != 0 { - return gots, fmt.Errorf("not all files were found, missing: %+v", wants) +var ( + tasksStaticFiles = map[string]testutil.DirentType{ + "cpuinfo": linux.DT_REG, + "loadavg": linux.DT_REG, + "meminfo": linux.DT_REG, + "mounts": linux.DT_LNK, + "net": linux.DT_DIR, + "self": linux.DT_LNK, + "stat": linux.DT_REG, + "sys": linux.DT_DIR, + "thread-self": linux.DT_LNK, + "uptime": linux.DT_REG, + "version": linux.DT_REG, + } + tasksStaticFilesNextOffs = map[string]int64{ + "self": selfLink.NextOff, + "thread-self": threadSelfLink.NextOff, + } + taskStaticFiles = map[string]testutil.DirentType{ + "auxv": linux.DT_REG, + "cgroup": linux.DT_REG, + "cmdline": linux.DT_REG, + "comm": linux.DT_REG, + "environ": linux.DT_REG, + "gid_map": linux.DT_REG, + "io": linux.DT_REG, + "maps": linux.DT_REG, + "ns": linux.DT_DIR, + "smaps": linux.DT_REG, + "stat": linux.DT_REG, + "statm": linux.DT_REG, + "status": linux.DT_REG, + "task": linux.DT_DIR, + "uid_map": linux.DT_REG, } - return gots, nil -} +) -func setup() (context.Context, *vfs.VirtualFilesystem, vfs.VirtualDentry, error) { +func setup(t *testing.T) *testutil.System { k, err := testutil.Boot() if err != nil { - return nil, nil, vfs.VirtualDentry{}, fmt.Errorf("creating kernel: %v", err) + t.Fatalf("Error creating kernel: %v", err) } ctx := k.SupervisorContext() @@ -157,93 +104,60 @@ func setup() (context.Context, *vfs.VirtualFilesystem, vfs.VirtualDentry, error) } mntns, err := vfsObj.NewMountNamespace(ctx, creds, "", "procfs", &fsOpts) if err != nil { - return nil, nil, vfs.VirtualDentry{}, fmt.Errorf("NewMountNamespace(): %v", err) + t.Fatalf("NewMountNamespace(): %v", err) } - return ctx, vfsObj, mntns.Root(), nil + return testutil.NewSystem(ctx, t, vfsObj, mntns) } func TestTasksEmpty(t *testing.T) { - ctx, vfsObj, root, err := setup() - if err != nil { - t.Fatalf("Setup failed: %v", err) - } - defer root.DecRef() - - fd, err := vfsObj.OpenAt( - ctx, - auth.CredentialsFromContext(ctx), - &vfs.PathOperation{Root: root, Start: root, Path: fspath.Parse("/")}, - &vfs.OpenOptions{}, - ) - if err != nil { - t.Fatalf("vfsfs.OpenAt failed: %v", err) - } + s := setup(t) + defer s.Destroy() - cb := testIterDirentsCallback{} - if err := fd.Impl().IterDirents(ctx, &cb); err != nil { - t.Fatalf("IterDirents(): %v", err) - } - cb.dirents, err = checkDots(cb.dirents) - if err != nil { - t.Error(err.Error()) - } - cb.dirents, err = checkTasksStaticFiles(cb.dirents) - if err != nil { - t.Error(err.Error()) - } - if len(cb.dirents) != 0 { - t.Errorf("found more files than expected: %+v", cb.dirents) - } + collector := s.ListDirents(s.PathOpAtRoot("/")) + s.AssertAllDirentTypes(collector, tasksStaticFiles) + s.AssertDirentOffsets(collector, tasksStaticFilesNextOffs) } func TestTasks(t *testing.T) { - ctx, vfsObj, root, err := setup() - if err != nil { - t.Fatalf("Setup failed: %v", err) + s := setup(t) + defer s.Destroy() + + expectedDirents := make(map[string]testutil.DirentType) + for n, d := range tasksStaticFiles { + expectedDirents[n] = d } - defer root.DecRef() - k := kernel.KernelFromContext(ctx) + k := kernel.KernelFromContext(s.Ctx) var tasks []*kernel.Task for i := 0; i < 5; i++ { tc := k.NewThreadGroup(nil, k.RootPIDNamespace(), kernel.NewSignalHandlers(), linux.SIGCHLD, k.GlobalInit().Limits()) - task, err := testutil.CreateTask(ctx, fmt.Sprintf("name-%d", i), tc) + task, err := testutil.CreateTask(s.Ctx, fmt.Sprintf("name-%d", i), tc) if err != nil { t.Fatalf("CreateTask(): %v", err) } tasks = append(tasks, task) + expectedDirents[fmt.Sprintf("%d", i+1)] = linux.DT_DIR } - fd, err := vfsObj.OpenAt( - ctx, - auth.CredentialsFromContext(ctx), - &vfs.PathOperation{Root: root, Start: root, Path: fspath.Parse("/")}, - &vfs.OpenOptions{}, - ) - if err != nil { - t.Fatalf("vfsfs.OpenAt(/) failed: %v", err) - } + collector := s.ListDirents(s.PathOpAtRoot("/")) + s.AssertAllDirentTypes(collector, expectedDirents) + s.AssertDirentOffsets(collector, tasksStaticFilesNextOffs) - cb := testIterDirentsCallback{} - if err := fd.Impl().IterDirents(ctx, &cb); err != nil { - t.Fatalf("IterDirents(): %v", err) - } - cb.dirents, err = checkDots(cb.dirents) - if err != nil { - t.Error(err.Error()) - } - cb.dirents, err = checkTasksStaticFiles(cb.dirents) - if err != nil { - t.Error(err.Error()) - } lastPid := 0 - for _, d := range cb.dirents { + dirents := collector.OrderedDirents() + doneSkippingNonTaskDirs := false + for _, d := range dirents { pid, err := strconv.Atoi(d.Name) if err != nil { + if !doneSkippingNonTaskDirs { + // We haven't gotten to the task dirs yet. + continue + } t.Fatalf("Invalid process directory %q", d.Name) } + doneSkippingNonTaskDirs = true if lastPid > pid { - t.Errorf("pids not in order: %v", cb.dirents) + t.Errorf("pids not in order: %v", dirents) } found := false for _, t := range tasks { @@ -260,13 +174,16 @@ func TestTasks(t *testing.T) { t.Errorf("Wrong dirent offset want: %d got: %d: %+v", want, d.NextOff, d) } } + if !doneSkippingNonTaskDirs { + t.Fatalf("Never found any process directories.") + } // Test lookup. for _, path := range []string{"/1", "/2"} { - fd, err := vfsObj.OpenAt( - ctx, - auth.CredentialsFromContext(ctx), - &vfs.PathOperation{Root: root, Start: root, Path: fspath.Parse(path)}, + fd, err := s.VFS.OpenAt( + s.Ctx, + s.Creds, + s.PathOpAtRoot(path), &vfs.OpenOptions{}, ) if err != nil { @@ -274,15 +191,15 @@ func TestTasks(t *testing.T) { } buf := make([]byte, 1) bufIOSeq := usermem.BytesIOSequence(buf) - if _, err := fd.Read(ctx, bufIOSeq, vfs.ReadOptions{}); err != syserror.EISDIR { + if _, err := fd.Read(s.Ctx, bufIOSeq, vfs.ReadOptions{}); err != syserror.EISDIR { t.Errorf("wrong error reading directory: %v", err) } } - if _, err := vfsObj.OpenAt( - ctx, - auth.CredentialsFromContext(ctx), - &vfs.PathOperation{Root: root, Start: root, Path: fspath.Parse("/9999")}, + if _, err := s.VFS.OpenAt( + s.Ctx, + s.Creds, + s.PathOpAtRoot("/9999"), &vfs.OpenOptions{}, ); err != syserror.ENOENT { t.Fatalf("wrong error from vfsfs.OpenAt(/9999): %v", err) @@ -290,16 +207,13 @@ func TestTasks(t *testing.T) { } func TestTasksOffset(t *testing.T) { - ctx, vfsObj, root, err := setup() - if err != nil { - t.Fatalf("Setup failed: %v", err) - } - defer root.DecRef() + s := setup(t) + defer s.Destroy() - k := kernel.KernelFromContext(ctx) + k := kernel.KernelFromContext(s.Ctx) for i := 0; i < 3; i++ { tc := k.NewThreadGroup(nil, k.RootPIDNamespace(), kernel.NewSignalHandlers(), linux.SIGCHLD, k.GlobalInit().Limits()) - if _, err := testutil.CreateTask(ctx, fmt.Sprintf("name-%d", i), tc); err != nil { + if _, err := testutil.CreateTask(s.Ctx, fmt.Sprintf("name-%d", i), tc); err != nil { t.Fatalf("CreateTask(): %v", err) } } @@ -382,134 +296,100 @@ func TestTasksOffset(t *testing.T) { }, } { t.Run(tc.name, func(t *testing.T) { - fd, err := vfsObj.OpenAt( - ctx, - auth.CredentialsFromContext(ctx), - &vfs.PathOperation{Root: root, Start: root, Path: fspath.Parse("/")}, + s := s.WithSubtest(t) + fd, err := s.VFS.OpenAt( + s.Ctx, + s.Creds, + s.PathOpAtRoot("/"), &vfs.OpenOptions{}, ) if err != nil { t.Fatalf("vfsfs.OpenAt(/) failed: %v", err) } - if _, err := fd.Impl().Seek(ctx, tc.offset, linux.SEEK_SET); err != nil { + if _, err := fd.Seek(s.Ctx, tc.offset, linux.SEEK_SET); err != nil { t.Fatalf("Seek(%d, SEEK_SET): %v", tc.offset, err) } - cb := testIterDirentsCallback{} - if err := fd.Impl().IterDirents(ctx, &cb); err != nil { - t.Fatalf("IterDirents(): %v", err) + var collector testutil.DirentCollector + if err := fd.IterDirents(s.Ctx, &collector); err != nil { + t.Fatalf("IterDirent(): %v", err) } - if cb.dirents, err = checkFiles(cb.dirents, tc.wants); err != nil { - t.Error(err.Error()) - } - if len(cb.dirents) != 0 { - t.Errorf("found more files than expected: %+v", cb.dirents) + + expectedTypes := make(map[string]testutil.DirentType) + expectedOffsets := make(map[string]int64) + for name, want := range tc.wants { + expectedTypes[name] = want.Type + if want.NextOff != 0 { + expectedOffsets[name] = want.NextOff + } } + + collector.SkipDotsChecks(true) // We seek()ed past the dots. + s.AssertAllDirentTypes(&collector, expectedTypes) + s.AssertDirentOffsets(&collector, expectedOffsets) }) } } func TestTask(t *testing.T) { - ctx, vfsObj, root, err := setup() - if err != nil { - t.Fatalf("Setup failed: %v", err) - } - defer root.DecRef() + s := setup(t) + defer s.Destroy() - k := kernel.KernelFromContext(ctx) + k := kernel.KernelFromContext(s.Ctx) tc := k.NewThreadGroup(nil, k.RootPIDNamespace(), kernel.NewSignalHandlers(), linux.SIGCHLD, k.GlobalInit().Limits()) - _, err = testutil.CreateTask(ctx, "name", tc) + _, err := testutil.CreateTask(s.Ctx, "name", tc) if err != nil { t.Fatalf("CreateTask(): %v", err) } - fd, err := vfsObj.OpenAt( - ctx, - auth.CredentialsFromContext(ctx), - &vfs.PathOperation{Root: root, Start: root, Path: fspath.Parse("/1")}, - &vfs.OpenOptions{}, - ) - if err != nil { - t.Fatalf("vfsfs.OpenAt(/1) failed: %v", err) - } - - cb := testIterDirentsCallback{} - if err := fd.Impl().IterDirents(ctx, &cb); err != nil { - t.Fatalf("IterDirents(): %v", err) - } - cb.dirents, err = checkDots(cb.dirents) - if err != nil { - t.Error(err.Error()) - } - cb.dirents, err = checkTaskStaticFiles(cb.dirents) - if err != nil { - t.Error(err.Error()) - } - if len(cb.dirents) != 0 { - t.Errorf("found more files than expected: %+v", cb.dirents) - } + collector := s.ListDirents(s.PathOpAtRoot("/1")) + s.AssertAllDirentTypes(collector, taskStaticFiles) } func TestProcSelf(t *testing.T) { - ctx, vfsObj, root, err := setup() - if err != nil { - t.Fatalf("Setup failed: %v", err) - } - defer root.DecRef() + s := setup(t) + defer s.Destroy() - k := kernel.KernelFromContext(ctx) + k := kernel.KernelFromContext(s.Ctx) tc := k.NewThreadGroup(nil, k.RootPIDNamespace(), kernel.NewSignalHandlers(), linux.SIGCHLD, k.GlobalInit().Limits()) - task, err := testutil.CreateTask(ctx, "name", tc) + task, err := testutil.CreateTask(s.Ctx, "name", tc) if err != nil { t.Fatalf("CreateTask(): %v", err) } - fd, err := vfsObj.OpenAt( - task, - auth.CredentialsFromContext(ctx), - &vfs.PathOperation{Root: root, Start: root, Path: fspath.Parse("/self/"), FollowFinalSymlink: true}, - &vfs.OpenOptions{}, - ) - if err != nil { - t.Fatalf("vfsfs.OpenAt(/self/) failed: %v", err) - } - - cb := testIterDirentsCallback{} - if err := fd.Impl().IterDirents(ctx, &cb); err != nil { - t.Fatalf("IterDirents(): %v", err) - } - cb.dirents, err = checkDots(cb.dirents) - if err != nil { - t.Error(err.Error()) - } - cb.dirents, err = checkTaskStaticFiles(cb.dirents) - if err != nil { - t.Error(err.Error()) - } - if len(cb.dirents) != 0 { - t.Errorf("found more files than expected: %+v", cb.dirents) - } + collector := s.WithTemporaryContext(task).ListDirents(&vfs.PathOperation{ + Root: s.Root, + Start: s.Root, + Path: fspath.Parse("/self/"), + FollowFinalSymlink: true, + }) + s.AssertAllDirentTypes(collector, taskStaticFiles) } -func iterateDir(ctx context.Context, t *testing.T, vfsObj *vfs.VirtualFilesystem, root vfs.VirtualDentry, fd *vfs.FileDescription) { +func iterateDir(ctx context.Context, t *testing.T, s *testutil.System, fd *vfs.FileDescription) { t.Logf("Iterating: /proc%s", fd.MappedName(ctx)) - cb := testIterDirentsCallback{} - if err := fd.Impl().IterDirents(ctx, &cb); err != nil { + var collector testutil.DirentCollector + if err := fd.IterDirents(ctx, &collector); err != nil { t.Fatalf("IterDirents(): %v", err) } - var err error - cb.dirents, err = checkDots(cb.dirents) - if err != nil { + if err := collector.Contains(".", linux.DT_DIR); err != nil { t.Error(err.Error()) } - for _, d := range cb.dirents { + if err := collector.Contains("..", linux.DT_DIR); err != nil { + t.Error(err.Error()) + } + + for _, d := range collector.Dirents() { + if d.Name == "." || d.Name == ".." { + continue + } childPath := path.Join(fd.MappedName(ctx), d.Name) if d.Type == linux.DT_LNK { - link, err := vfsObj.ReadlinkAt( + link, err := s.VFS.ReadlinkAt( ctx, auth.CredentialsFromContext(ctx), - &vfs.PathOperation{Root: root, Start: root, Path: fspath.Parse(childPath)}, + &vfs.PathOperation{Root: s.Root, Start: s.Root, Path: fspath.Parse(childPath)}, ) if err != nil { t.Errorf("vfsfs.ReadlinkAt(%v) failed: %v", childPath, err) @@ -520,10 +400,10 @@ func iterateDir(ctx context.Context, t *testing.T, vfsObj *vfs.VirtualFilesystem } t.Logf("Opening: /proc%s", childPath) - child, err := vfsObj.OpenAt( + child, err := s.VFS.OpenAt( ctx, auth.CredentialsFromContext(ctx), - &vfs.PathOperation{Root: root, Start: root, Path: fspath.Parse(childPath)}, + &vfs.PathOperation{Root: s.Root, Start: s.Root, Path: fspath.Parse(childPath)}, &vfs.OpenOptions{}, ) if err != nil { @@ -539,24 +419,21 @@ func iterateDir(ctx context.Context, t *testing.T, vfsObj *vfs.VirtualFilesystem } if d.Type == linux.DT_DIR { // Found another dir, let's do it again! - iterateDir(ctx, t, vfsObj, root, child) + iterateDir(ctx, t, s, child) } } } // TestTree iterates all directories and stats every file. func TestTree(t *testing.T) { - uberCtx, vfsObj, root, err := setup() - if err != nil { - t.Fatalf("Setup failed: %v", err) - } - defer root.DecRef() + s := setup(t) + defer s.Destroy() - k := kernel.KernelFromContext(uberCtx) + k := kernel.KernelFromContext(s.Ctx) var tasks []*kernel.Task for i := 0; i < 5; i++ { tc := k.NewThreadGroup(nil, k.RootPIDNamespace(), kernel.NewSignalHandlers(), linux.SIGCHLD, k.GlobalInit().Limits()) - task, err := testutil.CreateTask(uberCtx, fmt.Sprintf("name-%d", i), tc) + task, err := testutil.CreateTask(s.Ctx, fmt.Sprintf("name-%d", i), tc) if err != nil { t.Fatalf("CreateTask(): %v", err) } @@ -564,14 +441,14 @@ func TestTree(t *testing.T) { } ctx := tasks[0] - fd, err := vfsObj.OpenAt( + fd, err := s.VFS.OpenAt( ctx, - auth.CredentialsFromContext(uberCtx), - &vfs.PathOperation{Root: root, Start: root, Path: fspath.Parse("/")}, + auth.CredentialsFromContext(s.Ctx), + &vfs.PathOperation{Root: s.Root, Start: s.Root, Path: fspath.Parse("/")}, &vfs.OpenOptions{}, ) if err != nil { t.Fatalf("vfsfs.OpenAt(/) failed: %v", err) } - iterateDir(ctx, t, vfsObj, root, fd) + iterateDir(ctx, t, s, fd) } diff --git a/pkg/sentry/fsimpl/sys/sys_test.go b/pkg/sentry/fsimpl/sys/sys_test.go index 60a1634a9..8b1cf0bd0 100644 --- a/pkg/sentry/fsimpl/sys/sys_test.go +++ b/pkg/sentry/fsimpl/sys/sys_test.go @@ -56,7 +56,7 @@ func TestReadCPUFile(t *testing.T) { for _, fname := range []string{"online", "possible", "present"} { pop := s.PathOpAtRoot(fmt.Sprintf("devices/system/cpu/%s", fname)) - fd, err := s.VFS.OpenAt(s.Ctx, s.Creds, &pop, &vfs.OpenOptions{}) + fd, err := s.VFS.OpenAt(s.Ctx, s.Creds, pop, &vfs.OpenOptions{}) if err != nil { t.Fatalf("OpenAt(pop:%+v) = %+v failed: %v", pop, fd, err) } @@ -75,7 +75,7 @@ func TestSysRootContainsExpectedEntries(t *testing.T) { s := newTestSystem(t) defer s.Destroy() pop := s.PathOpAtRoot("/") - s.AssertDirectoryContains(&pop, map[string]testutil.DirentType{ + s.AssertAllDirentTypes(s.ListDirents(pop), map[string]testutil.DirentType{ "block": linux.DT_DIR, "bus": linux.DT_DIR, "class": linux.DT_DIR, diff --git a/pkg/sentry/fsimpl/testutil/testutil.go b/pkg/sentry/fsimpl/testutil/testutil.go index eada31d94..2a723a89f 100644 --- a/pkg/sentry/fsimpl/testutil/testutil.go +++ b/pkg/sentry/fsimpl/testutil/testutil.go @@ -40,8 +40,8 @@ type System struct { Ctx context.Context Creds *auth.Credentials VFS *vfs.VirtualFilesystem + Root vfs.VirtualDentry mns *vfs.MountNamespace - root vfs.VirtualDentry } // NewSystem constructs a System. @@ -55,14 +55,49 @@ func NewSystem(ctx context.Context, t *testing.T, v *vfs.VirtualFilesystem, mns Creds: auth.CredentialsFromContext(ctx), VFS: v, mns: mns, - root: mns.Root(), + Root: mns.Root(), } return s } +// WithSubtest creates a temporary test system with a new test harness, +// referencing all other resources from the original system. This is useful when +// a system is reused for multiple subtests, and the T needs to change for each +// case. Note that this is safe when test cases run in parallel, as all +// resources referenced by the system are immutable, or handle interior +// mutations in a thread-safe manner. +// +// The returned system must not outlive the original and should not be destroyed +// via System.Destroy. +func (s *System) WithSubtest(t *testing.T) *System { + return &System{ + t: t, + Ctx: s.Ctx, + Creds: s.Creds, + VFS: s.VFS, + mns: s.mns, + Root: s.Root, + } +} + +// WithTemporaryContext constructs a temporary test system with a new context +// ctx. The temporary system borrows all resources and references from the +// original system. The returned temporary system must not outlive the original +// system, and should not be destroyed via System.Destroy. +func (s *System) WithTemporaryContext(ctx context.Context) *System { + return &System{ + t: s.t, + Ctx: ctx, + Creds: s.Creds, + VFS: s.VFS, + mns: s.mns, + Root: s.Root, + } +} + // Destroy release resources associated with a test system. func (s *System) Destroy() { - s.root.DecRef() + s.Root.DecRef() s.mns.DecRef(s.VFS) // Reference on mns passed to NewSystem. } @@ -87,18 +122,18 @@ func (s *System) ReadToEnd(fd *vfs.FileDescription) (string, error) { // PathOpAtRoot constructs a PathOperation with the given path from // the root of the filesystem. -func (s *System) PathOpAtRoot(path string) vfs.PathOperation { - return vfs.PathOperation{ - Root: s.root, - Start: s.root, +func (s *System) PathOpAtRoot(path string) *vfs.PathOperation { + return &vfs.PathOperation{ + Root: s.Root, + Start: s.Root, Path: fspath.Parse(path), } } // GetDentryOrDie attempts to resolve a dentry referred to by the // provided path operation. If unsuccessful, the test fails. -func (s *System) GetDentryOrDie(pop vfs.PathOperation) vfs.VirtualDentry { - vd, err := s.VFS.GetDentryAt(s.Ctx, s.Creds, &pop, &vfs.GetDentryOptions{}) +func (s *System) GetDentryOrDie(pop *vfs.PathOperation) vfs.VirtualDentry { + vd, err := s.VFS.GetDentryAt(s.Ctx, s.Creds, pop, &vfs.GetDentryOptions{}) if err != nil { s.t.Fatalf("GetDentryAt(pop:%+v) failed: %v", pop, err) } @@ -108,14 +143,8 @@ func (s *System) GetDentryOrDie(pop vfs.PathOperation) vfs.VirtualDentry { // DirentType is an alias for values for linux_dirent64.d_type. type DirentType = uint8 -// AssertDirectoryContains verifies that a directory at pop contains the entries -// specified. AssertDirectoryContains implicitly checks for "." and "..", these -// need not be included in entries. -func (s *System) AssertDirectoryContains(pop *vfs.PathOperation, entries map[string]DirentType) { - // Also implicitly check for "." and "..". - entries["."] = linux.DT_DIR - entries[".."] = linux.DT_DIR - +// ListDirents lists the Dirents for a directory at pop. +func (s *System) ListDirents(pop *vfs.PathOperation) *DirentCollector { fd, err := s.VFS.OpenAt(s.Ctx, s.Creds, pop, &vfs.OpenOptions{Flags: linux.O_RDONLY}) if err != nil { s.t.Fatalf("OpenAt for PathOperation %+v failed: %v", pop, err) @@ -126,12 +155,52 @@ func (s *System) AssertDirectoryContains(pop *vfs.PathOperation, entries map[str if err := fd.IterDirents(s.Ctx, collector); err != nil { s.t.Fatalf("IterDirent failed: %v", err) } + return collector +} + +// AssertAllDirentTypes verifies that the set of dirents in collector contains +// exactly the specified set of expected entries. AssertAllDirentTypes respects +// collector.skipDots, and implicitly checks for "." and ".." accordingly. +func (s *System) AssertAllDirentTypes(collector *DirentCollector, expected map[string]DirentType) { + // Also implicitly check for "." and "..", if enabled. + if !collector.skipDots { + expected["."] = linux.DT_DIR + expected[".."] = linux.DT_DIR + } - collectedEntries := make(map[string]DirentType) + dentryTypes := make(map[string]DirentType) + collector.mu.Lock() for _, dirent := range collector.dirents { - collectedEntries[dirent.Name] = dirent.Type + dentryTypes[dirent.Name] = dirent.Type } - if diff := cmp.Diff(entries, collectedEntries); diff != "" { + collector.mu.Unlock() + if diff := cmp.Diff(expected, dentryTypes); diff != "" { + s.t.Fatalf("IterDirent had unexpected results:\n--- want\n+++ got\n%v", diff) + } +} + +// AssertDirentOffsets verifies that collector contains at least the entries +// specified in expected, with the given NextOff field. Entries specified in +// expected but missing from collector result in failure. Extra entries in +// collector are ignored. AssertDirentOffsets respects collector.skipDots, and +// implicitly checks for "." and ".." accordingly. +func (s *System) AssertDirentOffsets(collector *DirentCollector, expected map[string]int64) { + // Also implicitly check for "." and "..", if enabled. + if !collector.skipDots { + expected["."] = 1 + expected[".."] = 2 + } + + dentryNextOffs := make(map[string]int64) + collector.mu.Lock() + for _, dirent := range collector.dirents { + // Ignore extra entries in dentries that are not in expected. + if _, ok := expected[dirent.Name]; ok { + dentryNextOffs[dirent.Name] = dirent.NextOff + } + } + collector.mu.Unlock() + if diff := cmp.Diff(expected, dentryNextOffs); diff != "" { s.t.Fatalf("IterDirent had unexpected results:\n--- want\n+++ got\n%v", diff) } } @@ -141,16 +210,29 @@ func (s *System) AssertDirectoryContains(pop *vfs.PathOperation, entries map[str // all dirents emitted by the callback. type DirentCollector struct { mu sync.Mutex - dirents map[string]vfs.Dirent + order []*vfs.Dirent + dirents map[string]*vfs.Dirent + // When the collector is used in various Assert* functions, should "." and + // ".." be implicitly checked? + skipDots bool +} + +// SkipDotsChecks enables or disables the implicit checks on "." and ".." when +// the collector is used in various Assert* functions. Note that "." and ".." +// are still collected if passed to d.Handle, so the caller should only disable +// the checks when they aren't expected. +func (d *DirentCollector) SkipDotsChecks(value bool) { + d.skipDots = value } // Handle implements vfs.IterDirentsCallback.Handle. func (d *DirentCollector) Handle(dirent vfs.Dirent) bool { d.mu.Lock() if d.dirents == nil { - d.dirents = make(map[string]vfs.Dirent) + d.dirents = make(map[string]*vfs.Dirent) } - d.dirents[dirent.Name] = dirent + d.order = append(d.order, &dirent) + d.dirents[dirent.Name] = &dirent d.mu.Unlock() return true } @@ -176,3 +258,24 @@ func (d *DirentCollector) Contains(name string, typ uint8) error { } return nil } + +// Dirents returns all dirents discovered by this collector. +func (d *DirentCollector) Dirents() map[string]*vfs.Dirent { + d.mu.Lock() + dirents := make(map[string]*vfs.Dirent) + for n, d := range d.dirents { + dirents[n] = d + } + d.mu.Unlock() + return dirents +} + +// OrderedDirents returns an ordered list of dirents as discovered by this +// collector. +func (d *DirentCollector) OrderedDirents() []*vfs.Dirent { + d.mu.Lock() + dirents := make([]*vfs.Dirent, len(d.order)) + copy(dirents, d.order) + d.mu.Unlock() + return dirents +} -- cgit v1.2.3 From 04e3d56db1d8dee9f4fae51718dbef33559c4101 Mon Sep 17 00:00:00 2001 From: Adin Scannell Date: Thu, 23 Jan 2020 10:43:59 -0800 Subject: Fix master build case. Otherwise, this will be built when building a specific release tag (typically in the past), causing the master binary to be overwritten with something older. We can generally assume that tags will be applied after the commit has been integrated, and therefore that any builds pointing to tags will use only the tags. Another way to fix this would be to introduce something akin to the KOKORO_BUILD_NIGHTLY environment variable, but it doesn't seem strictly necessary. PiperOrigin-RevId: 291198171 --- scripts/build.sh | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/scripts/build.sh b/scripts/build.sh index 8b2094cb0..4c042af6c 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -67,11 +67,7 @@ if [[ "${KOKORO_BUILD_NIGHTLY:-false}" == "true" ]]; then install_raw "${KOKORO_ARTIFACTS_DIR}/nightly/${stamp}" install_repo "${KOKORO_ARTIFACTS_DIR}/dists/nightly" else - # We keep only the latest master raw release. - install_raw "${KOKORO_ARTIFACTS_DIR}/master/latest" - install_repo "${KOKORO_ARTIFACTS_DIR}/dists/master" - - # Is it a tagged release? Build that too. + # Is it a tagged release? Build that. tags="$(git tag --points-at HEAD)" if ! [[ -z "${tags}" ]]; then # Note that a given commit can match any number of tags. We have to iterate @@ -80,8 +76,13 @@ else name=$(echo "${tag}" | cut -d'-' -f2) base=$(echo "${name}" | cut -d'.' -f1) install_raw "${KOKORO_ARTIFACTS_DIR}/release/${name}" + install_raw "${KOKORO_ARTIFACTS_DIR}/release/latest" install_repo "${KOKORO_ARTIFACTS_DIR}/dists/release" install_repo "${KOKORO_ARTIFACTS_DIR}/dists/${base}" done + else + # Otherwise, assume it is a raw master commit. + install_raw "${KOKORO_ARTIFACTS_DIR}/master/latest" + install_repo "${KOKORO_ARTIFACTS_DIR}/dists/master" fi fi -- cgit v1.2.3 From 98e83c444fa58669d45ecf162cf4bf48dce790d1 Mon Sep 17 00:00:00 2001 From: Brad Burlage Date: Thu, 23 Jan 2020 10:58:18 -0800 Subject: Try running kythe build on RBE. Also add our RBE project/instance to the --config=remote defaults. PiperOrigin-RevId: 291201426 --- .bazelrc | 20 +++++++------------- kokoro/kythe/generate_xrefs.sh | 3 ++- scripts/common_bazel.sh | 9 +-------- 3 files changed, 10 insertions(+), 22 deletions(-) diff --git a/.bazelrc b/.bazelrc index 7f87e94b1..9c35c5e7b 100644 --- a/.bazelrc +++ b/.bazelrc @@ -20,6 +20,13 @@ build --stamp --workspace_status_command tools/workspace_status.sh # Enable remote execution so actions are performed on the remote systems. build:remote --remote_executor=grpcs://remotebuildexecution.googleapis.com +build:remote --project_id=gvisor-rbe +build:remote --remote_instance_name=projects/gvisor-rbe/instances/default_instance +# Enable authentication. This will pick up application default credentials by +# default. You can use --google_credentials=some_file.json to use a service +# account credential instead. +build:remote --google_default_credentials=true +build:remote --auth_scope="https://www.googleapis.com/auth/cloud-source-tools" # Add a custom platform and toolchain that builds in a privileged docker # container, which is required by our syscall tests. @@ -27,25 +34,12 @@ build:remote --host_platform=//test:rbe_ubuntu1604 build:remote --extra_toolchains=//test:cc-toolchain-clang-x86_64-default build:remote --extra_execution_platforms=//test:rbe_ubuntu1604 build:remote --platforms=//test:rbe_ubuntu1604 - -# Use default image for crosstool toolchain. build:remote --crosstool_top=@rbe_default//cc:toolchain - -# Default parallelism and timeout for remote jobs. build:remote --jobs=50 build:remote --remote_timeout=3600 - # RBE requires a strong hash function, such as SHA256. startup --host_jvm_args=-Dbazel.DigestFunction=SHA256 -# Enable authentication. This will pick up application default credentials by -# default. You can use --google_credentials=some_file.json to use a service -# account credential instead. -build:remote --google_default_credentials=true - -# Auth scope needed for authentication with RBE. -build:remote --auth_scope="https://www.googleapis.com/auth/cloud-source-tools" - # Set flags for uploading to BES in order to view results in the Bazel Build # Results UI. build:results --bes_backend="buildeventservice.googleapis.com" diff --git a/kokoro/kythe/generate_xrefs.sh b/kokoro/kythe/generate_xrefs.sh index 799467a34..d2ca95c68 100644 --- a/kokoro/kythe/generate_xrefs.sh +++ b/kokoro/kythe/generate_xrefs.sh @@ -25,7 +25,7 @@ bazel version python3 -V -readonly KYTHE_VERSION='v0.0.37' +readonly KYTHE_VERSION='v0.0.39' readonly WORKDIR="$(mktemp -d)" readonly KYTHE_DIR="${WORKDIR}/kythe-${KYTHE_VERSION}" if [[ -n "$KOKORO_GIT_COMMIT" ]]; then @@ -47,6 +47,7 @@ bazel \ --override_repository kythe_release="${KYTHE_DIR}" \ --define=kythe_corpus=gvisor.dev \ --cxxopt=-std=c++17 \ + --config=remote \ //... "${KYTHE_DIR}/tools/kzip" merge \ diff --git a/scripts/common_bazel.sh b/scripts/common_bazel.sh index bbc1a038e..a473a88a4 100755 --- a/scripts/common_bazel.sh +++ b/scripts/common_bazel.sh @@ -32,18 +32,11 @@ declare -r BAZEL_FLAGS=( "--keep_going" "--verbose_failures=true" ) -if [[ -v KOKORO_BAZEL_AUTH_CREDENTIAL ]] || [[ -v RBE_PROJECT_ID ]]; then - declare -r RBE_PROJECT_ID="${RBE_PROJECT_ID:-gvisor-rbe}" - declare -r BAZEL_RBE_FLAGS=( - "--config=remote" - "--project_id=${RBE_PROJECT_ID}" - "--remote_instance_name=projects/${RBE_PROJECT_ID}/instances/default_instance" - ) -fi if [[ -v KOKORO_BAZEL_AUTH_CREDENTIAL ]]; then declare -r BAZEL_RBE_AUTH_FLAGS=( "--auth_credentials=${KOKORO_BAZEL_AUTH_CREDENTIAL}" ) + declare -r BAZEL_RBE_FLAGS=("--config=remote") fi # Wrap bazel. -- cgit v1.2.3 From 7a79715504e92be9fc9aebc12fbd65aa46049054 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Thu, 23 Jan 2020 11:47:30 -0800 Subject: Check for EINTR from KVM_CREATE_VM The kernel may return EINTR from: kvm_create_vm kvm_init_mmu_notifier mmu_notifier_register do_mmu_notifier_register mm_take_all_locks Go 1.14's preemptive scheduling signals make hitting this much more likely. PiperOrigin-RevId: 291212669 --- pkg/sentry/platform/kvm/kvm.go | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/pkg/sentry/platform/kvm/kvm.go b/pkg/sentry/platform/kvm/kvm.go index a7850faed..d337c5c7c 100644 --- a/pkg/sentry/platform/kvm/kvm.go +++ b/pkg/sentry/platform/kvm/kvm.go @@ -62,9 +62,19 @@ func New(deviceFile *os.File) (*KVM, error) { } // Create a new VM fd. - vm, _, errno := syscall.RawSyscall(syscall.SYS_IOCTL, fd, _KVM_CREATE_VM, 0) - if errno != 0 { - return nil, fmt.Errorf("creating VM: %v", errno) + var ( + vm uintptr + errno syscall.Errno + ) + for { + vm, _, errno = syscall.Syscall(syscall.SYS_IOCTL, fd, _KVM_CREATE_VM, 0) + if errno == syscall.EINTR { + continue + } + if errno != 0 { + return nil, fmt.Errorf("creating VM: %v", errno) + } + break } // We are done with the device file. deviceFile.Close() -- cgit v1.2.3 From 14d2ed1ad7785a54b35ef7ee949d3cf89a87e66d Mon Sep 17 00:00:00 2001 From: Brad Burlage Date: Thu, 23 Jan 2020 14:12:40 -0800 Subject: Fix kythe build. * Pass --auth_credentials now that we're using RBE * Fix kzips not being uploaded to the root of the GCS bucket PiperOrigin-RevId: 291241757 --- kokoro/kythe/generate_xrefs.cfg | 3 ++- kokoro/kythe/generate_xrefs.sh | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/kokoro/kythe/generate_xrefs.cfg b/kokoro/kythe/generate_xrefs.cfg index 03e65c54e..ccf657983 100644 --- a/kokoro/kythe/generate_xrefs.cfg +++ b/kokoro/kythe/generate_xrefs.cfg @@ -23,6 +23,7 @@ bazel_setting { action { define_artifacts { - regex: "*.kzip" + regex: "**/*.kzip" + fail_if_no_artifacts: true } } diff --git a/kokoro/kythe/generate_xrefs.sh b/kokoro/kythe/generate_xrefs.sh index d2ca95c68..4c104afdb 100644 --- a/kokoro/kythe/generate_xrefs.sh +++ b/kokoro/kythe/generate_xrefs.sh @@ -48,6 +48,7 @@ bazel \ --define=kythe_corpus=gvisor.dev \ --cxxopt=-std=c++17 \ --config=remote \ + --auth_credentials="${KOKORO_BAZEL_AUTH_CREDENTIAL}" \ //... "${KYTHE_DIR}/tools/kzip" merge \ -- cgit v1.2.3 From 3db317390b5cc491d680fc4a5fc7b8372890b4da Mon Sep 17 00:00:00 2001 From: Nicolas Lacasse Date: Thu, 23 Jan 2020 16:17:50 -0800 Subject: Remove epoll entry from map when dropping it. This pattern (delete from map when dropping) is also used in epoll.RemoveEntry, and seems like generally a good idea. PiperOrigin-RevId: 291268208 --- pkg/sentry/kernel/epoll/epoll.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/sentry/kernel/epoll/epoll.go b/pkg/sentry/kernel/epoll/epoll.go index 430311cc0..e84742993 100644 --- a/pkg/sentry/kernel/epoll/epoll.go +++ b/pkg/sentry/kernel/epoll/epoll.go @@ -174,6 +174,7 @@ func (e *EventPoll) Release() { entry.id.File.EventUnregister(&entry.waiter) entry.file.Drop() } + e.files = nil } // Read implements fs.FileOperations.Read. -- cgit v1.2.3