Skip to content

Commit 4fcb84f

Browse files
Safer handling of unix socket address names
1 parent eddd5cd commit 4fcb84f

2 files changed

Lines changed: 23 additions & 44 deletions

File tree

toolbelt/sockets.cc

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@
55
#include "sockets.h"
66

77
#include <arpa/inet.h>
8+
#include <cstring>
89
#include <netdb.h>
910
#include <netinet/in.h>
1011
#include <stdint.h>
1112
#include <stdlib.h>
1213
#include <sys/ioctl.h>
1314
#include <sys/socket.h>
15+
#include <sys/un.h>
1416
#include <unistd.h>
1517

1618
#include <algorithm>
@@ -329,14 +331,24 @@ static struct sockaddr_un BuildUnixSocketName(const std::string &pathname) {
329331
// On Linux we can create it in the abstract namespace which doesn't
330332
// consume a pathname.
331333
addr.sun_path[0] = '\0';
332-
memcpy(addr.sun_path + 1, pathname.c_str(), pathname.size());
334+
memcpy(addr.sun_path + 1, pathname.c_str(), std::min(pathname.size(), sizeof(addr.sun_path) - 2));
333335
#else
334336
// Portable uses the file system so it must be a valid path name.
335-
memcpy(addr.sun_path, pathname.c_str(), pathname.size());
337+
memcpy(addr.sun_path, pathname.c_str(), std::min(pathname.size(), sizeof(addr.sun_path) - 1));
336338
#endif
337339
return addr;
338340
}
339341

342+
static std::string ExtractUnixSocketNameString(const struct sockaddr_un &addr, socklen_t addrlen) {
343+
#if defined(__linux__)
344+
auto addr_str_len = strnlen(addr.sun_path + 1, addrlen - offsetof(sockaddr_un, sun_path) - 1);
345+
return std::string(addr.sun_path + 1, addr.sun_path + addr_str_len + 1);
346+
#else
347+
auto addr_str_len = strnlen(addr.sun_path, addrlen - offsetof(sockaddr_un, sun_path));
348+
return std::string(addr.sun_path, addr.sun_path + addr_str_len);
349+
#endif
350+
}
351+
340352
absl::Status UnixSocket::Bind(const std::string &pathname, bool listen) {
341353
struct sockaddr_un addr = BuildUnixSocketName(pathname);
342354

@@ -381,12 +393,7 @@ absl::StatusOr<UnixSocket> UnixSocket::Accept(co::Coroutine *c) const {
381393
"Failed to obtain bound address for accepted socket: %s",
382394
strerror(errno)));
383395
}
384-
#ifdef __linux__
385-
new_socket.bound_address_ = bound.sun_path + 1;
386-
#else
387-
new_socket.bound_address_ = bound.sun_path;
388-
389-
#endif
396+
new_socket.bound_address_ = ExtractUnixSocketNameString(bound, len);
390397
return new_socket;
391398
}
392399

@@ -531,11 +538,7 @@ absl::StatusOr<std::string> UnixSocket::GetPeerName() const {
531538
return absl::InternalError(absl::StrFormat(
532539
"Failed to obtain peer address for socket: %s", strerror(errno)));
533540
}
534-
#if defined(__linux__)
535-
return std::string(peer.sun_path + 1);
536-
#else
537-
return std::string(peer.sun_path);
538-
#endif
541+
return ExtractUnixSocketNameString(peer, len);
539542
}
540543

541544
absl::StatusOr<std::string> UnixSocket::LocalAddress() const {
@@ -550,11 +553,7 @@ absl::StatusOr<std::string> UnixSocket::LocalAddress() const {
550553
return absl::InternalError(absl::StrFormat(
551554
"Failed to obtain local address for socket: %s", strerror(errno)));
552555
}
553-
#if defined(__linux__)
554-
return std::string(local.sun_path + 1);
555-
#else
556-
return std::string(local.sun_path);
557-
#endif
556+
return ExtractUnixSocketNameString(local, len);
558557
}
559558

560559
// Network socket.

toolbelt/sockets.h

Lines changed: 6 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ template <typename H> inline H AbslHashValue(H h, const SocketAddress &a) {
291291
// This is a general socket initialized with a file descriptor. Subclasses
292292
// implement the different socket types.
293293
class Socket {
294-
public:
294+
protected:
295295
Socket() = default;
296296
explicit Socket(int fd, bool connected = false)
297297
: fd_(fd), connected_(connected) {}
@@ -307,6 +307,7 @@ class Socket {
307307
return *this;
308308
}
309309
~Socket() {}
310+
public:
310311

311312
void Close() {
312313
fd_.Close();
@@ -363,12 +364,6 @@ class UnixSocket : public Socket {
363364
public:
364365
UnixSocket();
365366
explicit UnixSocket(int fd, bool connected = false) : Socket(fd, connected) {}
366-
UnixSocket(UnixSocket &&s) : Socket(std::move(s)) {}
367-
UnixSocket(const UnixSocket &s) = default;
368-
UnixSocket &operator=(const UnixSocket &s) = default;
369-
UnixSocket &operator=(UnixSocket &&s) = default;
370-
371-
~UnixSocket() = default;
372367

373368
absl::Status Bind(const std::string &pathname, bool listen);
374369
absl::Status Connect(const std::string &pathname);
@@ -391,16 +386,11 @@ class UnixSocket : public Socket {
391386
// A socket for communication across the network. This is the base
392387
// class for UDP and TCP sockets.
393388
class NetworkSocket : public Socket {
394-
public:
389+
protected:
395390
NetworkSocket() = default;
396391
explicit NetworkSocket(int fd, bool connected = false)
397392
: Socket(fd, connected) {}
398-
NetworkSocket(const NetworkSocket &s)
399-
: Socket(s), bound_address_(s.bound_address_) {}
400-
NetworkSocket(NetworkSocket &&s)
401-
: Socket(std::move(s)), bound_address_(std::move(s.bound_address_)) {}
402-
~NetworkSocket() = default;
403-
NetworkSocket &operator=(const NetworkSocket &s) = default;
393+
public:
404394

405395
absl::Status Connect(const InetAddress &addr);
406396

@@ -419,10 +409,6 @@ class UDPSocket : public NetworkSocket {
419409
UDPSocket();
420410
explicit UDPSocket(int fd, bool connected = false)
421411
: NetworkSocket(fd, connected) {}
422-
UDPSocket(const UDPSocket &) = default;
423-
UDPSocket(UDPSocket &&s) : NetworkSocket(std::move(s)) {}
424-
~UDPSocket() = default;
425-
UDPSocket &operator=(const UDPSocket &s) = default;
426412

427413
absl::Status Bind(const InetAddress &addr);
428414

@@ -448,10 +434,6 @@ class TCPSocket : public NetworkSocket {
448434
TCPSocket();
449435
explicit TCPSocket(int fd, bool connected = false)
450436
: NetworkSocket(fd, connected) {}
451-
TCPSocket(const TCPSocket &) = default;
452-
TCPSocket(TCPSocket &&s) : NetworkSocket(std::move(s)) {}
453-
~TCPSocket() = default;
454-
TCPSocket &operator=(const TCPSocket &s) = default;
455437

456438
absl::Status Bind(const InetAddress &addr, bool listen);
457439

@@ -467,10 +449,7 @@ class VirtualStreamSocket : public Socket {
467449
VirtualStreamSocket();
468450
explicit VirtualStreamSocket(int fd, bool connected = false)
469451
: Socket(fd, connected) {}
470-
VirtualStreamSocket(const VirtualStreamSocket &) = default;
471-
VirtualStreamSocket(VirtualStreamSocket &&s) : Socket(std::move(s)) {}
472-
~VirtualStreamSocket() = default;
473-
VirtualStreamSocket &operator=(const VirtualStreamSocket &s) = default;
452+
474453
absl::Status Connect(const VirtualAddress &addr);
475454

476455
absl::Status Bind(const VirtualAddress &addr, bool listen);
@@ -496,6 +475,7 @@ class StreamSocket {
496475
StreamSocket(StreamSocket &&s) = default;
497476
~StreamSocket() = default;
498477
StreamSocket &operator=(const StreamSocket &s) = default;
478+
StreamSocket &operator=(StreamSocket &&s) = default;
499479

500480
// Binders for TCP, Virtual, and Unix sockets.
501481
//

0 commit comments

Comments
 (0)