mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
vfs1: don't allow to open socket files
open() has to return ENXIO in this case. O_PATH isn't supported by vfs1. PiperOrigin-RevId: 348820478
This commit is contained in:
@@ -475,6 +475,9 @@ func (i *inodeOperations) Check(ctx context.Context, inode *fs.Inode, p fs.PermM
|
||||
func (i *inodeOperations) GetFile(ctx context.Context, d *fs.Dirent, flags fs.FileFlags) (*fs.File, error) {
|
||||
switch d.Inode.StableAttr.Type {
|
||||
case fs.Socket:
|
||||
if i.session().overrides != nil {
|
||||
return nil, syserror.ENXIO
|
||||
}
|
||||
return i.getFileSocket(ctx, d, flags)
|
||||
case fs.Pipe:
|
||||
return i.getFilePipe(ctx, d, flags)
|
||||
|
||||
@@ -276,6 +276,10 @@ func (i *inodeOperations) BoundEndpoint(inode *fs.Inode, path string) transport.
|
||||
|
||||
// GetFile implements fs.InodeOperations.GetFile.
|
||||
func (i *inodeOperations) GetFile(ctx context.Context, d *fs.Dirent, flags fs.FileFlags) (*fs.File, error) {
|
||||
if fs.IsSocket(d.Inode.StableAttr) {
|
||||
return nil, syserror.ENXIO
|
||||
}
|
||||
|
||||
return newFile(ctx, d, flags, i), nil
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/sentry/fs"
|
||||
"gvisor.dev/gvisor/pkg/sentry/fs/fsutil"
|
||||
"gvisor.dev/gvisor/pkg/sentry/socket/unix/transport"
|
||||
"gvisor.dev/gvisor/pkg/syserror"
|
||||
"gvisor.dev/gvisor/pkg/waiter"
|
||||
)
|
||||
|
||||
@@ -63,7 +64,7 @@ func (s *Socket) BoundEndpoint(*fs.Inode, string) transport.BoundEndpoint {
|
||||
|
||||
// GetFile implements fs.FileOperations.GetFile.
|
||||
func (s *Socket) GetFile(ctx context.Context, dirent *fs.Dirent, flags fs.FileFlags) (*fs.File, error) {
|
||||
return fs.NewFile(ctx, dirent, flags, &socketFileOperations{}), nil
|
||||
return nil, syserror.ENXIO
|
||||
}
|
||||
|
||||
// +stateify savable
|
||||
|
||||
@@ -148,6 +148,10 @@ func (*fileInodeOperations) Rename(ctx context.Context, inode *fs.Inode, oldPare
|
||||
|
||||
// GetFile implements fs.InodeOperations.GetFile.
|
||||
func (f *fileInodeOperations) GetFile(ctx context.Context, d *fs.Dirent, flags fs.FileFlags) (*fs.File, error) {
|
||||
if fs.IsSocket(d.Inode.StableAttr) {
|
||||
return nil, syserror.ENXIO
|
||||
}
|
||||
|
||||
if flags.Write {
|
||||
fsmetric.TmpfsOpensW.Increment()
|
||||
} else if flags.Read {
|
||||
|
||||
@@ -175,6 +175,12 @@ func openAt(t *kernel.Task, dirFD int32, addr usermem.Addr, flags uint) (fd uint
|
||||
}
|
||||
}
|
||||
|
||||
file, err := d.Inode.GetFile(t, d, fileFlags)
|
||||
if err != nil {
|
||||
return syserror.ConvertIntr(err, syserror.ERESTARTSYS)
|
||||
}
|
||||
defer file.DecRef(t)
|
||||
|
||||
// Truncate is called when O_TRUNC is specified for any kind of
|
||||
// existing Dirent. Behavior is delegated to the entry's Truncate
|
||||
// implementation.
|
||||
@@ -184,12 +190,6 @@ func openAt(t *kernel.Task, dirFD int32, addr usermem.Addr, flags uint) (fd uint
|
||||
}
|
||||
}
|
||||
|
||||
file, err := d.Inode.GetFile(t, d, fileFlags)
|
||||
if err != nil {
|
||||
return syserror.ConvertIntr(err, syserror.ERESTARTSYS)
|
||||
}
|
||||
defer file.DecRef(t)
|
||||
|
||||
// Success.
|
||||
newFD, err := t.NewFDFrom(0, file, kernel.FDFlags{
|
||||
CloseOnExec: flags&linux.O_CLOEXEC != 0,
|
||||
|
||||
@@ -3324,6 +3324,7 @@ cc_binary(
|
||||
":socket_test_util",
|
||||
":unix_domain_socket_test_util",
|
||||
gtest,
|
||||
"//test/util:file_descriptor",
|
||||
"//test/util:test_main",
|
||||
"//test/util:test_util",
|
||||
],
|
||||
|
||||
@@ -12,12 +12,14 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "test/syscalls/linux/socket_test_util.h"
|
||||
#include "test/syscalls/linux/unix_domain_socket_test_util.h"
|
||||
#include "test/util/file_descriptor.h"
|
||||
#include "test/util/test_util.h"
|
||||
|
||||
namespace gvisor {
|
||||
@@ -70,6 +72,20 @@ TEST_P(UnboundFilesystemUnixSocketPairTest, GetSockNameLength) {
|
||||
strlen(want_addr.sun_path) + 1 + sizeof(want_addr.sun_family));
|
||||
}
|
||||
|
||||
TEST_P(UnboundFilesystemUnixSocketPairTest, OpenSocketWithTruncate) {
|
||||
auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
|
||||
|
||||
ASSERT_THAT(bind(sockets->first_fd(), sockets->first_addr(),
|
||||
sockets->first_addr_size()),
|
||||
SyscallSucceeds());
|
||||
|
||||
const struct sockaddr_un *addr =
|
||||
reinterpret_cast<const struct sockaddr_un *>(sockets->first_addr());
|
||||
EXPECT_THAT(chmod(addr->sun_path, 0777), SyscallSucceeds());
|
||||
EXPECT_THAT(open(addr->sun_path, O_RDONLY | O_TRUNC),
|
||||
SyscallFailsWithErrno(ENXIO));
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
AllUnixDomainSockets, UnboundFilesystemUnixSocketPairTest,
|
||||
::testing::ValuesIn(ApplyVec<SocketPairKind>(
|
||||
|
||||
Reference in New Issue
Block a user