summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorBrian Geffon <bgeffon@google.com>2018-06-19 14:11:58 -0700
committerShentubot <shentubot@google.com>2018-06-19 14:12:52 -0700
commitbda2a1ed3503699b8cb814bb3cc7ad0b9694155b (patch)
tree8f155da52a2ff48a0cbb3b137593938f3100c175
parent9db7cfad93abff181c59d61892d32b9b05f4234f (diff)
Rpcinet is racy around shutdown flags.
Correct a data race in rpcinet where a shutdown and recvmsg can race around shutown flags. PiperOrigin-RevId: 201238366 Change-Id: I5eb06df4a2b4eba331eeb5de19076213081d581f
-rw-r--r--pkg/sentry/socket/rpcinet/socket.go24
1 files changed, 17 insertions, 7 deletions
diff --git a/pkg/sentry/socket/rpcinet/socket.go b/pkg/sentry/socket/rpcinet/socket.go
index f641f25df..207123d6f 100644
--- a/pkg/sentry/socket/rpcinet/socket.go
+++ b/pkg/sentry/socket/rpcinet/socket.go
@@ -15,6 +15,7 @@
package rpcinet
import (
+ "sync/atomic"
"syscall"
"gvisor.googlesource.com/gvisor/pkg/abi/linux"
@@ -57,7 +58,7 @@ type socketOperations struct {
// shState is the state of the connection with respect to shutdown. Because
// we're mixing non-blocking semantics on the other side we have to adapt for
// some strange differences between blocking and non-blocking sockets.
- shState tcpip.ShutdownFlags
+ shState int32
}
// Verify that we actually implement socket.Socket.
@@ -105,26 +106,35 @@ func translateIOSyscallError(err error) error {
// setShutdownFlags will set the shutdown flag so we can handle blocking reads
// after a read shutdown.
func (s *socketOperations) setShutdownFlags(how int) {
+ var f tcpip.ShutdownFlags
switch how {
case linux.SHUT_RD:
- s.shState |= tcpip.ShutdownRead
+ f = tcpip.ShutdownRead
case linux.SHUT_WR:
- s.shState |= tcpip.ShutdownWrite
+ f = tcpip.ShutdownWrite
case linux.SHUT_RDWR:
- s.shState |= tcpip.ShutdownWrite | tcpip.ShutdownRead
+ f = tcpip.ShutdownWrite | tcpip.ShutdownRead
+ }
+
+ // Atomically update the flags.
+ for {
+ old := atomic.LoadInt32(&s.shState)
+ if atomic.CompareAndSwapInt32(&s.shState, old, old|int32(f)) {
+ break
+ }
}
}
func (s *socketOperations) resetShutdownFlags() {
- s.shState = 0
+ atomic.StoreInt32(&s.shState, 0)
}
func (s *socketOperations) isShutRdSet() bool {
- return s.shState&tcpip.ShutdownRead != 0
+ return atomic.LoadInt32(&s.shState)&int32(tcpip.ShutdownRead) != 0
}
func (s *socketOperations) isShutWrSet() bool {
- return s.shState&tcpip.ShutdownWrite != 0
+ return atomic.LoadInt32(&s.shState)&int32(tcpip.ShutdownWrite) != 0
}
// Release implements fs.FileOperations.Release.