1 // Copyright 2022 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifdef UNSAFE_BUFFERS_BUILD
6 // TODO(crbug.com/40284755): Remove this and spanify to fix the errors.
7 #pragma allow_unsafe_buffers
8 #endif
9
10 #include "net/base/sockaddr_util_posix.h"
11
12 #include <string.h>
13
14 #include <sys/socket.h>
15 #include <sys/un.h>
16
17 #include "net/base/sockaddr_storage.h"
18 #include "testing/gmock/include/gmock/gmock-matchers.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20
21 namespace net {
22
23 namespace {
24
MaxPathLength(SockaddrStorage * storage)25 size_t MaxPathLength(SockaddrStorage* storage) {
26 // |storage.addr_len| is initialized to the largest possible platform-
27 // dependent value. Subtracting the size of the initial fields in
28 // sockaddr_un gives us the longest permissible path value including space
29 // for an extra NUL character at the front or back.
30 return storage->addr_len - offsetof(struct sockaddr_un, sun_path) - 1;
31 }
32
33 } // namespace
34
TEST(FillUnixAddressTest,SimpleAddress)35 TEST(FillUnixAddressTest, SimpleAddress) {
36 SockaddrStorage storage;
37 std::string path = "/tmp/socket/path";
38
39 EXPECT_TRUE(
40 FillUnixAddress(path, /*use_abstract_namespace=*/false, &storage));
41
42 // |storage.addr_len| indicates the full size of the data in sockaddr_un.
43 // The size is increased by one byte to include the string NUL terminator.
44 EXPECT_EQ(path.size() + 1U + offsetof(struct sockaddr_un, sun_path),
45 (unsigned int)storage.addr_len);
46
47 struct sockaddr_un* socket_addr =
48 reinterpret_cast<struct sockaddr_un*>(storage.addr);
49 EXPECT_EQ(socket_addr->sun_family, AF_UNIX);
50
51 // Implicit conversion to std::string for comparison is fine since the path
52 // is always NUL terminated.
53 EXPECT_EQ(socket_addr->sun_path, path);
54 }
55
TEST(FillUnixAddressTest,PathEmpty)56 TEST(FillUnixAddressTest, PathEmpty) {
57 SockaddrStorage storage;
58 std::string path = "";
59 EXPECT_FALSE(
60 FillUnixAddress(path, /*use_abstract_namespace=*/false, &storage));
61 }
62
TEST(FillUnixAddressTest,AddressMaxLength)63 TEST(FillUnixAddressTest, AddressMaxLength) {
64 SockaddrStorage storage;
65 size_t path_max = MaxPathLength(&storage);
66 std::string path(path_max, '0');
67
68 EXPECT_TRUE(
69 FillUnixAddress(path, /*use_abstract_namespace=*/false, &storage));
70
71 struct sockaddr_un* socket_addr =
72 reinterpret_cast<struct sockaddr_un*>(storage.addr);
73 EXPECT_EQ(socket_addr->sun_family, AF_UNIX);
74 EXPECT_EQ(socket_addr->sun_path, path);
75 }
76
TEST(FillUnixAddressTest,AddressTooLong)77 TEST(FillUnixAddressTest, AddressTooLong) {
78 SockaddrStorage storage;
79 size_t path_max = MaxPathLength(&storage);
80 std::string path(path_max + 1, '0');
81
82 EXPECT_FALSE(
83 FillUnixAddress(path, /*use_abstract_namespace=*/false, &storage));
84 }
85
TEST(FillUnixAddressTest,AbstractLinuxAddress)86 TEST(FillUnixAddressTest, AbstractLinuxAddress) {
87 SockaddrStorage storage;
88 size_t path_max = MaxPathLength(&storage);
89 std::string path(path_max, '0');
90
91 #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
92 EXPECT_TRUE(FillUnixAddress(path, /*use_abstract_namespace=*/true, &storage));
93
94 EXPECT_EQ(path.size() + 1U + offsetof(struct sockaddr_un, sun_path),
95 (unsigned int)storage.addr_len);
96
97 struct sockaddr_un* socket_addr =
98 reinterpret_cast<struct sockaddr_un*>(storage.addr);
99 EXPECT_EQ(socket_addr->sun_family, AF_UNIX);
100
101 // The path buffer is preceded by a NUL character for abstract Linux
102 // addresses.
103 EXPECT_EQ(socket_addr->sun_path[0], '\0');
104
105 // The path string may not be NUL terminated, so do a buffer copy when
106 // converting to std::string.
107 std::string unix_path(reinterpret_cast<char*>(socket_addr->sun_path + 1),
108 path.size());
109 EXPECT_EQ(unix_path, path);
110 #else
111 // Other platforms don't support the abstract Linux namespace.
112 EXPECT_FALSE(
113 FillUnixAddress(path, /*use_abstract_namespace=*/true, &storage));
114 #endif
115 }
116
117 } // namespace net
118