mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
gvisor/sock/unix: pass creds when a message is sent between unconnected sockets
and don't report a sender address if it doesn't have one PiperOrigin-RevId: 251371284
This commit is contained in:
@@ -139,3 +139,8 @@ func (e *endpoint) UnidirectionalConnect() (transport.ConnectedEndpoint, *syserr
|
||||
func (e *endpoint) Release() {
|
||||
e.inode.DecRef()
|
||||
}
|
||||
|
||||
// Passcred implements transport.BoundEndpoint.Passcred.
|
||||
func (e *endpoint) Passcred() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -406,12 +406,20 @@ func makeCreds(t *kernel.Task, socketOrEndpoint interface{}) SCMCredentials {
|
||||
return nil
|
||||
}
|
||||
if cr, ok := socketOrEndpoint.(transport.Credentialer); ok && (cr.Passcred() || cr.ConnectedPasscred()) {
|
||||
tcred := t.Credentials()
|
||||
return &scmCredentials{t, tcred.EffectiveKUID, tcred.EffectiveKGID}
|
||||
return MakeCreds(t)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// MakeCreds creates default SCMCredentials.
|
||||
func MakeCreds(t *kernel.Task) SCMCredentials {
|
||||
if t == nil {
|
||||
return nil
|
||||
}
|
||||
tcred := t.Credentials()
|
||||
return &scmCredentials{t, tcred.EffectiveKUID, tcred.EffectiveKGID}
|
||||
}
|
||||
|
||||
// New creates default control messages if needed.
|
||||
func New(t *kernel.Task, socketOrEndpoint interface{}, rights SCMRights) transport.ControlMessages {
|
||||
return transport.ControlMessages{
|
||||
|
||||
@@ -237,6 +237,10 @@ type BoundEndpoint interface {
|
||||
// endpoint.
|
||||
UnidirectionalConnect() (ConnectedEndpoint, *syserr.Error)
|
||||
|
||||
// Passcred returns whether or not the SO_PASSCRED socket option is
|
||||
// enabled on this end.
|
||||
Passcred() bool
|
||||
|
||||
// Release releases any resources held by the BoundEndpoint. It must be
|
||||
// called before dropping all references to a BoundEndpoint returned by a
|
||||
// function.
|
||||
|
||||
@@ -385,6 +385,10 @@ func (s *SocketOperations) SendMsg(t *kernel.Task, src usermem.IOSequence, to []
|
||||
}
|
||||
defer ep.Release()
|
||||
w.To = ep
|
||||
|
||||
if ep.Passcred() && w.Control.Credentials == nil {
|
||||
w.Control.Credentials = control.MakeCreds(t)
|
||||
}
|
||||
}
|
||||
|
||||
n, err := src.CopyInTo(t, &w)
|
||||
@@ -516,7 +520,7 @@ func (s *SocketOperations) RecvMsg(t *kernel.Task, dst usermem.IOSequence, flags
|
||||
if n, err := dst.CopyOutFrom(t, &r); err != syserror.ErrWouldBlock || dontWait {
|
||||
var from interface{}
|
||||
var fromLen uint32
|
||||
if r.From != nil {
|
||||
if r.From != nil && len([]byte(r.From.Addr)) != 0 {
|
||||
from, fromLen = epsocket.ConvertAddress(linux.AF_UNIX, *r.From)
|
||||
}
|
||||
|
||||
|
||||
@@ -448,19 +448,7 @@ TEST_P(AllSocketPairTest, UnboundSenderAddr) {
|
||||
RetryEINTR(recvfrom)(accepted_fd.get(), &i, sizeof(i), 0,
|
||||
reinterpret_cast<sockaddr*>(&addr), &addr_len),
|
||||
SyscallSucceedsWithValue(sizeof(i)));
|
||||
if (!IsRunningOnGvisor()) {
|
||||
// Linux returns a zero length for addresses from recvfrom(2) and
|
||||
// recvmsg(2). This differs from the behavior of getpeername(2) and
|
||||
// getsockname(2). For simplicity, we use the getpeername(2) and
|
||||
// getsockname(2) behavior for recvfrom(2) and recvmsg(2).
|
||||
EXPECT_EQ(addr_len, 0);
|
||||
return;
|
||||
}
|
||||
EXPECT_EQ(addr_len, 2);
|
||||
EXPECT_EQ(
|
||||
memcmp(&addr, sockets->second_addr(),
|
||||
std::min((size_t)addr_len, (size_t)sockets->second_addr_len())),
|
||||
0);
|
||||
EXPECT_EQ(addr_len, 0);
|
||||
}
|
||||
|
||||
TEST_P(AllSocketPairTest, BoundSenderAddr) {
|
||||
|
||||
@@ -13,7 +13,9 @@
|
||||
// limitations under the License.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "test/syscalls/linux/socket_test_util.h"
|
||||
@@ -142,6 +144,28 @@ TEST_P(UnboundDgramUnixSocketPairTest, SendtoWithoutConnect) {
|
||||
SyscallSucceedsWithValue(sizeof(data)));
|
||||
}
|
||||
|
||||
TEST_P(UnboundDgramUnixSocketPairTest, SendtoWithoutConnectPassCreds) {
|
||||
auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
|
||||
|
||||
ASSERT_THAT(bind(sockets->first_fd(), sockets->first_addr(),
|
||||
sockets->first_addr_size()),
|
||||
SyscallSucceeds());
|
||||
|
||||
SetSoPassCred(sockets->first_fd());
|
||||
char data = 'a';
|
||||
ASSERT_THAT(
|
||||
RetryEINTR(sendto)(sockets->second_fd(), &data, sizeof(data), 0,
|
||||
sockets->first_addr(), sockets->first_addr_size()),
|
||||
SyscallSucceedsWithValue(sizeof(data)));
|
||||
ucred creds;
|
||||
creds.pid = -1;
|
||||
char buf[sizeof(data) + 1];
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
RecvCreds(sockets->first_fd(), &creds, buf, sizeof(buf), sizeof(data)));
|
||||
EXPECT_EQ(0, memcmp(&data, buf, sizeof(data)));
|
||||
EXPECT_THAT(getpid(), SyscallSucceedsWithValue(creds.pid));
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
AllUnixDomainSockets, UnboundDgramUnixSocketPairTest,
|
||||
::testing::ValuesIn(VecCat<SocketPairKind>(
|
||||
|
||||
Reference in New Issue
Block a user