Skip to content

Commit e97d8eb

Browse files
howjmayianlancetaylor
authored andcommitted
net: pass MSG_CMSG_CLOEXEC flag in ReadMsgUnix
As mentioned in #42765, calling "recvmsg" syscall on Linux should come with "MSG_CMSG_CLOEXEC" flag. For other systems which not supports "MSG_CMSG_CLOEXEC". ReadMsgUnix() would check the header. If the header type is "syscall.SCM_RIGHTS", then ReadMsgUnix() would parse the SocketControlMessage and call each fd with "syscall.CloseOnExec" Fixes #42765 Change-Id: I74347db72b465685d7684bf0f32415d285845ebb GitHub-Last-Rev: ca59e2c GitHub-Pull-Request: #42768 Reviewed-on: https://go-review.googlesource.com/c/go/+/272226 Trust: Emmanuel Odeke <[email protected]> Run-TryBot: Emmanuel Odeke <[email protected]> TryBot-Result: Go Bot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]> Reviewed-by: Tobias Klauser <[email protected]>
1 parent bbb510c commit e97d8eb

File tree

12 files changed

+186
-13
lines changed

12 files changed

+186
-13
lines changed

src/internal/poll/fd_unix.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ func (fd *FD) ReadFrom(p []byte) (int, syscall.Sockaddr, error) {
231231
}
232232

233233
// ReadMsg wraps the recvmsg network call.
234-
func (fd *FD) ReadMsg(p []byte, oob []byte) (int, int, int, syscall.Sockaddr, error) {
234+
func (fd *FD) ReadMsg(p []byte, oob []byte, flags int) (int, int, int, syscall.Sockaddr, error) {
235235
if err := fd.readLock(); err != nil {
236236
return 0, 0, 0, nil, err
237237
}
@@ -240,7 +240,7 @@ func (fd *FD) ReadMsg(p []byte, oob []byte) (int, int, int, syscall.Sockaddr, er
240240
return 0, 0, 0, nil, err
241241
}
242242
for {
243-
n, oobn, flags, sa, err := syscall.Recvmsg(fd.Sysfd, p, oob, 0)
243+
n, oobn, sysflags, sa, err := syscall.Recvmsg(fd.Sysfd, p, oob, flags)
244244
if err != nil {
245245
if err == syscall.EINTR {
246246
continue
@@ -253,7 +253,7 @@ func (fd *FD) ReadMsg(p []byte, oob []byte) (int, int, int, syscall.Sockaddr, er
253253
}
254254
}
255255
err = fd.eofError(n, err)
256-
return n, oobn, flags, sa, err
256+
return n, oobn, sysflags, sa, err
257257
}
258258
}
259259

src/internal/poll/fd_windows.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1013,7 +1013,7 @@ func sockaddrToRaw(sa syscall.Sockaddr) (unsafe.Pointer, int32, error) {
10131013
}
10141014

10151015
// ReadMsg wraps the WSARecvMsg network call.
1016-
func (fd *FD) ReadMsg(p []byte, oob []byte) (int, int, int, syscall.Sockaddr, error) {
1016+
func (fd *FD) ReadMsg(p []byte, oob []byte, flags int) (int, int, int, syscall.Sockaddr, error) {
10171017
if err := fd.readLock(); err != nil {
10181018
return 0, 0, 0, nil, err
10191019
}
@@ -1028,6 +1028,7 @@ func (fd *FD) ReadMsg(p []byte, oob []byte) (int, int, int, syscall.Sockaddr, er
10281028
o.rsa = new(syscall.RawSockaddrAny)
10291029
o.msg.Name = (syscall.Pointer)(unsafe.Pointer(o.rsa))
10301030
o.msg.Namelen = int32(unsafe.Sizeof(*o.rsa))
1031+
o.msg.Flags = uint32(flags)
10311032
n, err := execIO(o, func(o *operation) error {
10321033
return windows.WSARecvMsg(o.fd.Sysfd, &o.msg, &o.qty, &o.o, nil)
10331034
})

src/net/fd_posix.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,10 @@ func (fd *netFD) readFrom(p []byte) (n int, sa syscall.Sockaddr, err error) {
6464
return n, sa, wrapSyscallError(readFromSyscallName, err)
6565
}
6666

67-
func (fd *netFD) readMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) {
68-
n, oobn, flags, sa, err = fd.pfd.ReadMsg(p, oob)
67+
func (fd *netFD) readMsg(p []byte, oob []byte, flags int) (n, oobn, retflags int, sa syscall.Sockaddr, err error) {
68+
n, oobn, retflags, sa, err = fd.pfd.ReadMsg(p, oob, flags)
6969
runtime.KeepAlive(fd)
70-
return n, oobn, flags, sa, wrapSyscallError(readMsgSyscallName, err)
70+
return n, oobn, retflags, sa, wrapSyscallError(readMsgSyscallName, err)
7171
}
7272

7373
func (fd *netFD) Write(p []byte) (nn int, err error) {

src/net/iprawsock_posix.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ func stripIPv4Header(n int, b []byte) int {
7575

7676
func (c *IPConn) readMsg(b, oob []byte) (n, oobn, flags int, addr *IPAddr, err error) {
7777
var sa syscall.Sockaddr
78-
n, oobn, flags, sa, err = c.fd.readMsg(b, oob)
78+
n, oobn, flags, sa, err = c.fd.readMsg(b, oob, 0)
7979
switch sa := sa.(type) {
8080
case *syscall.SockaddrInet4:
8181
addr = &IPAddr{IP: sa.Addr[0:]}

src/net/net_fake.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ func (fd *netFD) readFrom(p []byte) (n int, sa syscall.Sockaddr, err error) {
268268
return 0, nil, syscall.ENOSYS
269269
}
270270

271-
func (fd *netFD) readMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) {
271+
func (fd *netFD) readMsg(p []byte, oob []byte, flags int) (n, oobn, retflags int, sa syscall.Sockaddr, err error) {
272272
return 0, 0, 0, nil, syscall.ENOSYS
273273
}
274274

src/net/udpsock_posix.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ func (c *UDPConn) readFrom(b []byte, addr *UDPAddr) (int, *UDPAddr, error) {
5656

5757
func (c *UDPConn) readMsg(b, oob []byte) (n, oobn, flags int, addr *UDPAddr, err error) {
5858
var sa syscall.Sockaddr
59-
n, oobn, flags, sa, err = c.fd.readMsg(b, oob)
59+
n, oobn, flags, sa, err = c.fd.readMsg(b, oob, 0)
6060
switch sa := sa.(type) {
6161
case *syscall.SockaddrInet4:
6262
addr = &UDPAddr{IP: sa.Addr[0:], Port: sa.Port}

src/net/unixsock_posix.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,11 @@ func (c *UnixConn) readFrom(b []byte) (int, *UnixAddr, error) {
113113

114114
func (c *UnixConn) readMsg(b, oob []byte) (n, oobn, flags int, addr *UnixAddr, err error) {
115115
var sa syscall.Sockaddr
116-
n, oobn, flags, sa, err = c.fd.readMsg(b, oob)
116+
n, oobn, flags, sa, err = c.fd.readMsg(b, oob, readMsgFlags)
117+
if oobn > 0 {
118+
setReadMsgCloseOnExec(oob[:oobn])
119+
}
120+
117121
switch sa := sa.(type) {
118122
case *syscall.SockaddrUnix:
119123
if sa.Name != "" {

src/net/unixsock_readmsg_linux.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright 2021 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
//go:build linux
6+
// +build linux
7+
8+
package net
9+
10+
import (
11+
"syscall"
12+
)
13+
14+
const readMsgFlags = syscall.MSG_CMSG_CLOEXEC
15+
16+
func setReadMsgCloseOnExec(oob []byte) {
17+
}

src/net/unixsock_readmsg_other.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright 2021 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
//go:build (js && wasm) || windows
6+
// +build js,wasm windows
7+
8+
package net
9+
10+
const readMsgFlags = 0
11+
12+
func setReadMsgCloseOnExec(oob []byte) {
13+
}

src/net/unixsock_readmsg_posix.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright 2021 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
//go:build aix || darwin || dragonfly || freebsd || netbsd || openbsd || solaris
6+
// +build aix darwin dragonfly freebsd netbsd openbsd solaris
7+
8+
package net
9+
10+
import (
11+
"syscall"
12+
)
13+
14+
const readMsgFlags = 0
15+
16+
func setReadMsgCloseOnExec(oob []byte) {
17+
scms, err := syscall.ParseSocketControlMessage(oob)
18+
if err != nil {
19+
return
20+
}
21+
22+
for _, scm := range scms {
23+
if scm.Header.Level == syscall.SOL_SOCKET && scm.Header.Type == syscall.SCM_RIGHTS {
24+
fds, err := syscall.ParseUnixRights(&scm)
25+
if err != nil {
26+
continue
27+
}
28+
for _, fd := range fds {
29+
syscall.CloseOnExec(fd)
30+
}
31+
}
32+
}
33+
}

0 commit comments

Comments
 (0)