Skip to content

Commit 9c7560c

Browse files
committed
socket: unix socket abstract namespace registry
1 parent 0e47e19 commit 9c7560c

5 files changed

Lines changed: 143 additions & 73 deletions

File tree

kernel/interfaces/system/vfs/socket/base.cppm

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -380,8 +380,7 @@ export namespace vfs::socket
380380
-> lib::expect<std::shared_ptr<socket_t>>;
381381
auto create_pair(addr_fam af, sock_type type, int protocol)
382382
-> lib::expect<std::pair<std::shared_ptr<socket_t>, std::shared_ptr<socket_t>>>;
383-
auto create_anon(std::shared_ptr<socket_t> sock, int flags)
384-
-> lib::expect<std::pair<int, std::shared_ptr<vfs::filedesc>>>;
383+
auto create_anon(std::shared_ptr<socket_t> sock, int flags) -> lib::expect<int>;
385384

386385
std::shared_ptr<vfs::ops> get_ops();
387386
} // export namespace vfs::socket

kernel/source/system/syscall/vfs/pipe.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,12 @@ namespace syscall::vfs
3636

3737
std::array<int, 2> fds;
3838

39-
const auto rdentry = std::make_shared<dentry>();
39+
auto rdentry = std::make_shared<dentry>();
4040
rdentry->name = "<[PIPE READ]>";
4141
rdentry->inode = shared_inode;
4242

4343
const auto rfdesc = filedesc::create({
44-
.dentry = rdentry,
44+
.dentry = std::move(rdentry),
4545
.mnt = nullptr
4646
}, flags | o_rdonly);
4747

@@ -58,12 +58,12 @@ namespace syscall::vfs
5858
return -lib::map_error(ret.error());
5959
}
6060

61-
const auto wdentry = std::make_shared<dentry>();
61+
auto wdentry = std::make_shared<dentry>();
6262
wdentry->name = "<[PIPE WRITE]>";
6363
wdentry->inode = std::move(shared_inode);
6464

6565
const auto wfdesc = filedesc::create({
66-
.dentry = wdentry,
66+
.dentry = std::move(wdentry),
6767
.mnt = nullptr
6868
}, flags | o_wronly);
6969

kernel/source/system/syscall/vfs/socket.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ namespace syscall::vfs
111111
if (!res)
112112
return -lib::map_error(res.error());
113113

114-
return res->first;
114+
return *res;
115115
}
116116

117117
int connect(int sockfd, const sockaddr __user *addr, socklen_t addrlen)
@@ -491,11 +491,11 @@ namespace syscall::vfs
491491
auto res2 = socket::create_anon(std::move(pres->second), flags);
492492
if (!res2)
493493
{
494-
proc->fdt->close(res1->first);
494+
proc->fdt->close(*res1);
495495
return -lib::map_error(res2.error());
496496
}
497497

498-
int ksv[2] { res1->first, res2->first };
498+
int ksv[2] { *res1, *res2 };
499499
if (!lib::copy_to_user(sv, ksv, sizeof(int) * 2))
500500
return -EFAULT;
501501
return 0;
@@ -590,6 +590,6 @@ namespace syscall::vfs
590590
return -EFAULT;
591591
}
592592

593-
return res->first;
593+
return *res;
594594
}
595595
} // namespace syscall::vfs

kernel/source/system/vfs/socket/socket.cpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -149,8 +149,7 @@ namespace vfs::socket
149149
return fam->create_pair(type, protocol);
150150
}
151151

152-
auto create_anon(std::shared_ptr<socket_t> sock, int flags)
153-
-> lib::expect<std::pair<int, std::shared_ptr<vfs::filedesc>>>
152+
auto create_anon(std::shared_ptr<socket_t> sock, int flags) -> lib::expect<int>
154153
{
155154
const auto proc = sched::current_process();
156155
auto &fdt = proc->fdt;
@@ -171,22 +170,22 @@ namespace vfs::socket
171170
kstat::time::status |
172171
kstat::time::birth
173172
);
174-
175173
}
176174

177-
const auto dentry = std::make_shared<vfs::dentry>();
175+
auto dentry = std::make_shared<vfs::dentry>();
178176
dentry->name = "<[SOCKET]>";
179177
dentry->inode = inode;
180178

181-
const auto fdesc = filedesc::create({ .dentry = dentry, .mnt = nullptr }, flags);
179+
auto fdesc = filedesc::create({ .dentry = std::move(dentry), .mnt = nullptr }, flags);
182180
fdesc->file->private_data = std::move(sock);
181+
fdesc->file->opened = true;
183182

184183
const auto max_fd = proc->rlimits->get(sched::rlimit_nofile).cur;
185-
const auto fdres = fdt->alloc(fdesc, 0, false, max_fd);
184+
const auto fdres = fdt->alloc(std::move(fdesc), 0, false, max_fd);
186185
if (!fdres.has_value())
187186
return std::unexpected { fdres.error() };
188187

189-
return std::make_pair(*fdres, fdesc);
188+
return *fdres;
190189
}
191190

192191
std::shared_ptr<vfs::ops> get_ops()

kernel/source/system/vfs/socket/unix.cpp

Lines changed: 128 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -48,15 +48,15 @@ namespace vfs::socket
4848
std::size_t off, std::size_t len, bool &fault
4949
);
5050

51-
// TODO: scm rights, abstract namespace, connected dgram, msg_more, cmsg_cloexec, trunc
51+
// TODO: scm rights, connected dgram, msg_more, cmsg_cloexec, trunc
5252

53-
// struct unix_sock;
54-
// lib::locker<
55-
// lib::map::flat_hash<
56-
// std::string,
57-
// std::weak_ptr<unix_sock>
58-
// >, sched::mutex
59-
// > abstract;
53+
struct unix_sock;
54+
lib::locker<
55+
lib::map::flat_hash<
56+
std::string,
57+
std::weak_ptr<unix_sock>
58+
>, sched::mutex
59+
> abstract;
6060

6161
enum state { unconnected, connecting, connected, listening, disconnecting };
6262
struct unix_sock : socket_t, std::enable_shared_from_this<unix_sock>
@@ -146,23 +146,28 @@ namespace vfs::socket
146146
if (addr.size() < sizeof(addr_fam) || addr.size() > sizeof(sockaddr_un))
147147
return std::unexpected { lib::err::invalid_argument };
148148

149-
sockaddr_un sa;
150-
addr.copy_to(std::as_writable_bytes(std::span { &sa, 1 }));
149+
sockaddr_un sa { };
150+
addr.copy_to(std::as_writable_bytes(std::span { &sa, 1 }).subspan(0, addr.size()));
151151

152152
if (sa.sun_family != af_unix)
153153
return std::unexpected { lib::err::address_family_unsupported };
154154

155155
std::string_view path;
156+
bool is_abstract = false;
157+
156158
if (addr.size() > sizeof(addr_fam))
157159
{
160+
const auto max_len = addr.size() - sizeof(addr_fam);
158161
if (sa.sun_path[0] == 0)
159162
{
160-
// TODO
161-
return std::unexpected { lib::err::not_supported };
163+
is_abstract = true;
164+
path = std::string_view { sa.sun_path, max_len };
165+
}
166+
else
167+
{
168+
const auto len = std::strnlen(sa.sun_path, max_len);
169+
path = std::string_view { sa.sun_path, len };
162170
}
163-
164-
const auto len = std::strnlen(sa.sun_path, addr.size() - sizeof(addr_fam));
165-
path = std::string_view { sa.sun_path, len };
166171
}
167172
else path = "";
168173

@@ -173,6 +178,18 @@ namespace vfs::socket
173178
if (slocked->state != unconnected)
174179
return std::unexpected { lib::err::invalid_argument };
175180

181+
if (is_abstract)
182+
{
183+
auto registry = abstract.lock();
184+
if (registry->contains(path))
185+
return std::unexpected { lib::err::address_in_use };
186+
187+
registry->insert({ std::string { path }, shared_from_this() });
188+
slocked->bound_path = path;
189+
190+
return { };
191+
}
192+
176193
const auto proc = sched::current_process();
177194
const auto ret = vfs::create(
178195
proc->vfs->cwd, path, (0777 & ~proc->vfs->umask) | stat::s_ifsock, 0
@@ -197,32 +214,56 @@ namespace vfs::socket
197214
return std::unexpected { lib::err::invalid_argument };
198215

199216
sockaddr_un sa { };
200-
addr.copy_to(std::as_writable_bytes(std::span { &sa, 1 }));
217+
addr.copy_to(std::as_writable_bytes(std::span { &sa, 1 }).subspan(0, addr.size()));
201218

202219
if (sa.sun_family != af_unix)
203220
return std::unexpected { lib::err::address_family_unsupported };
204221

205222
std::string_view path;
223+
bool is_abstract = false;
224+
206225
if (addr.size() > sizeof(addr_fam))
207226
{
227+
const auto max_len = addr.size() - sizeof(addr_fam);
208228
if (sa.sun_path[0] == 0)
209-
return std::unexpected { lib::err::not_found };
210-
211-
const auto len = std::strnlen(sa.sun_path, addr.size() - sizeof(addr_fam));
212-
path = std::string_view { sa.sun_path, len };
229+
{
230+
is_abstract = true;
231+
path = std::string_view { sa.sun_path, max_len };
232+
}
233+
else
234+
{
235+
const auto len = std::strnlen(sa.sun_path, max_len);
236+
path = std::string_view { sa.sun_path, len };
237+
}
213238
}
214239
else return std::unexpected { lib::err::not_found };
215240

216241
const auto proc = sched::current_process();
217-
const auto res = vfs::resolve(proc->vfs->cwd, path);
218-
if (!res)
219-
return std::unexpected { res.error() };
242+
std::shared_ptr<unix_sock> target;
220243

221-
auto &inode = res->target.dentry->inode;
222-
if (inode->stat.type() != stat::s_ifsock)
223-
return std::unexpected { lib::err::connection_refused };
244+
if (is_abstract)
245+
{
246+
auto registry = abstract.lock();
247+
auto it = registry->find(path);
248+
if (it == registry->end())
249+
return std::unexpected { lib::err::connection_refused };
224250

225-
auto target = private_t::get(inode)->sock.lock();
251+
target = it->second.lock();
252+
if (!target)
253+
return std::unexpected { lib::err::connection_refused };
254+
}
255+
else
256+
{
257+
const auto res = vfs::resolve(proc->vfs->cwd, path);
258+
if (!res)
259+
return std::unexpected { res.error() };
260+
261+
auto &inode = res->target.dentry->inode;
262+
if (inode->stat.type() != stat::s_ifsock)
263+
return std::unexpected { lib::err::connection_refused };
264+
265+
target = private_t::get(inode)->sock.lock();
266+
}
226267
if (!target)
227268
return std::unexpected { lib::err::connection_refused };
228269

@@ -339,12 +380,14 @@ namespace vfs::socket
339380
auto pslocked = connecting->state.lock();
340381
if (!pslocked->bound_path.empty())
341382
{
342-
std::strncpy(
343-
sa.sun_path,
344-
pslocked->bound_path.c_str(),
345-
sizeof(sa.sun_path) - 1
383+
const bool is_abstract = pslocked->bound_path[0] == 0;
384+
const auto copy_size = std::min(
385+
pslocked->bound_path.size(), sizeof(sa.sun_path)
346386
);
347-
actual = sizeof(addr_fam) + pslocked->bound_path.size() + 1;
387+
388+
std::memcpy(sa.sun_path, pslocked->bound_path.data(), copy_size);
389+
actual = static_cast<socklen_t>(sizeof(addr_fam) +
390+
pslocked->bound_path.size() + !is_abstract);
348391
}
349392
}
350393

@@ -495,26 +538,44 @@ namespace vfs::socket
495538
if (!hdr.name.empty())
496539
{
497540
sockaddr_un sa { };
498-
hdr.name.copy_to(std::as_writable_bytes(std::span { &sa, 1 }));
541+
hdr.name.copy_to(std::as_writable_bytes(std::span { &sa, 1 })
542+
.subspan(0, hdr.name.size()));
543+
499544
if (sa.sun_family != af_unix)
500545
return std::unexpected { lib::err::address_family_unsupported };
501546

502-
const auto len = std::strnlen(
503-
sa.sun_path,
504-
hdr.name.size() - sizeof(addr_fam)
505-
);
506-
const std::string_view path { sa.sun_path, len };
547+
const auto max_len = hdr.name.size() - sizeof(addr_fam);
548+
if (max_len == 0)
549+
return std::unexpected { lib::err::invalid_argument };
507550

508-
const auto proc = sched::current_process();
509-
const auto res = vfs::resolve(proc->vfs->cwd, path);
510-
if (!res)
511-
return std::unexpected { res.error() };
551+
if (sa.sun_path[0] == '\0')
552+
{
553+
const std::string_view path { sa.sun_path, max_len };
512554

513-
auto &inode = res->target.dentry->inode;
514-
if (inode->stat.type() != stat::s_ifsock)
515-
return std::unexpected { lib::err::connection_refused };
555+
auto registry = abstract.lock();
556+
auto it = registry->find(path);
557+
if (it == registry->end())
558+
return std::unexpected { lib::err::connection_refused };
559+
560+
dest = it->second.lock();
561+
}
562+
else
563+
{
564+
const auto len = std::strnlen(sa.sun_path, max_len);
565+
const std::string_view path { sa.sun_path, len };
566+
567+
const auto proc = sched::current_process();
568+
const auto res = vfs::resolve(proc->vfs->cwd, path);
569+
if (!res)
570+
return std::unexpected { res.error() };
571+
572+
auto &inode = res->target.dentry->inode;
573+
if (inode->stat.type() != stat::s_ifsock)
574+
return std::unexpected { lib::err::connection_refused };
575+
576+
dest = private_t::get(inode)->sock.lock();
577+
}
516578

517-
dest = private_t::get(inode)->sock.lock();
518579
if (!dest)
519580
return std::unexpected { lib::err::connection_refused };
520581
}
@@ -743,13 +804,15 @@ namespace vfs::socket
743804
{
744805
sockaddr_un sa { };
745806
sa.sun_family = af_unix;
746-
std::strncpy(
747-
sa.sun_path,
748-
msg->sender_path.c_str(),
749-
sizeof(sa.sun_path) - 1
807+
808+
const bool is_abstract = msg->sender_path[0] == 0;
809+
const auto copy_size = std::min(
810+
msg->sender_path.size(), sizeof(sa.sun_path)
750811
);
812+
std::memcpy(sa.sun_path, msg->sender_path.data(), copy_size);
751813

752-
const auto sa_len = sizeof(addr_fam) + msg->sender_path.size() + 1;
814+
const auto sa_len = sizeof(addr_fam) +
815+
msg->sender_path.size() + !is_abstract;
753816
const auto copy_len = std::min(hdr.name.size(), sa_len);
754817

755818
hdr.name.subspan(0, copy_len).copy_from(
@@ -900,12 +963,15 @@ namespace vfs::socket
900963
auto slocked = state.lock();
901964
if (!slocked->bound_path.empty())
902965
{
903-
std::strncpy(
904-
sa.sun_path,
905-
slocked->bound_path.c_str(),
906-
sizeof(sa.sun_path) - 1
966+
const bool is_abstract = slocked->bound_path[0] == 0;
967+
const auto copy_size = std::min(
968+
slocked->bound_path.size(),
969+
sizeof(sa.sun_path)
907970
);
908-
actual = sizeof(addr_fam) + slocked->bound_path.size() + 1;
971+
std::memcpy(sa.sun_path, slocked->bound_path.data(), copy_size);
972+
973+
actual = static_cast<socklen_t>(sizeof(addr_fam) +
974+
slocked->bound_path.size() + !is_abstract);
909975
}
910976
}
911977

@@ -1106,6 +1172,12 @@ namespace vfs::socket
11061172
{
11071173
{
11081174
auto slocked = state.lock();
1175+
if (!slocked->bound_path.empty() && slocked->bound_path[0] == 0)
1176+
{
1177+
auto registry = abstract.lock();
1178+
registry->erase(slocked->bound_path);
1179+
}
1180+
11091181
slocked->state = disconnecting;
11101182
slocked->bound_inode.reset();
11111183

0 commit comments

Comments
 (0)