Skip to content

Commit 0ff7fad

Browse files
committed
darwin: Use LOCAL_PEERCRED instead of SO_PEERCRED
While LOCAL_PEERCRED is somewhat similar to SO_PEERCRED, we unfortunately don't have access to the PID of the remote peer. This is something we actually need to properly distinguish the remote peer by giving it an IP address with the PID encoded, otherwise we'd end up with duplicate IPs. On the other hand, using random IP addresses also is not a very good solution here, since we actually *want* to have the same IP for the same process. Right now the UID and GID fields are not used at all on Darwin, but we really need to figure out a way to properly assign fake IP addresses. Signed-off-by: aszlig <aszlig@nix.build>
1 parent d1a9108 commit 0ff7fad

File tree

3 files changed

+50
-5
lines changed

3 files changed

+50
-5
lines changed

src/sockaddr.cc

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -107,24 +107,39 @@ bool SockAddr::set_host(const SockAddr &other)
107107
}
108108
}
109109

110-
bool SockAddr::set_host(const ucred &peercred)
110+
#if defined(SO_PEERCRED)
111+
#define PEERCRED_TYPE ucred
112+
#define PEERCRED_PID peercred.pid
113+
#define PEERCRED_GID peercred.gid
114+
#define PEERCRED_UID peercred.uid
115+
#else
116+
#define PEERCRED_TYPE xucred
117+
#define PEERCRED_PID peercred.cr_pid
118+
#define PEERCRED_GID peercred.cr_gid
119+
#define PEERCRED_UID peercred.cr_uid
120+
#endif
121+
122+
bool SockAddr::set_host(const PEERCRED_TYPE &peercred)
111123
{
112124
if (this->ss_family == AF_INET) {
113125
this->cast4()->sin_addr.s_addr =
114-
htonl(static_cast<uint32_t>(peercred.pid));
126+
htonl(static_cast<uint32_t>(PEERCRED_PID));
115127
return true;
116128
} else if (this->ss_family == AF_INET6) {
117129
sockaddr_in6 *addr = this->cast6();
118130
addr->sin6_addr.s6_addr[0] = 0xfe;
119131
addr->sin6_addr.s6_addr[1] = 0x80;
120132
addr->sin6_addr.s6_addr[2] = 0x00;
121133
addr->sin6_addr.s6_addr[3] = 0x00;
122-
uint32_t part = htonl(static_cast<uint32_t>(peercred.uid));
134+
uint32_t part = htonl(static_cast<uint32_t>(PEERCRED_UID));
123135
memcpy(addr->sin6_addr.s6_addr + 4, &part, 4);
124-
part = htonl(static_cast<uint32_t>(peercred.gid));
136+
// XXX!
137+
#if defined(SO_PEERCRED)
138+
part = htonl(static_cast<uint32_t>(PEERCRED_GID));
125139
memcpy(addr->sin6_addr.s6_addr + 8, &part, 4);
126-
part = htonl(static_cast<uint32_t>(peercred.pid));
140+
part = htonl(static_cast<uint32_t>(PEERCRED_PID));
127141
memcpy(addr->sin6_addr.s6_addr + 12, &part, 4);
142+
#endif
128143
return true;
129144
}
130145
return false;

src/sockaddr.hh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66
#include <netinet/in.h>
77
#include <sys/un.h>
88

9+
#if defined(__APPLE__)
10+
#include <sys/ucred.h>
11+
#endif
12+
913
struct SockAddr : public sockaddr_storage
1014
{
1115
SockAddr();
@@ -20,7 +24,11 @@ struct SockAddr : public sockaddr_storage
2024

2125
std::optional<std::string> get_host(void) const;
2226
bool set_host(const std::string&);
27+
#if defined(SO_PEERCRED)
2328
bool set_host(const ucred&);
29+
#else
30+
bool set_host(const xucred&);
31+
#endif
2432
bool set_host(const SockAddr&);
2533

2634
bool set_random_host(void);

src/socket.cc

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44
#include <arpa/inet.h>
55
#include <sys/un.h>
66

7+
#if defined(__APPLE__)
8+
#include <sys/ucred.h>
9+
#endif
10+
711
#include "socket.hh"
812
#include "realcalls.hh"
913
#include "logging.hh"
@@ -262,10 +266,19 @@ bool Socket::create_binding(const SockAddr &addr)
262266
if (!local.set_host(addr))
263267
return false;
264268
} else {
269+
#if defined(SO_PEERCRED)
265270
ucred local_cred;
266271
local_cred.uid = getuid();
267272
local_cred.gid = getgid();
268273
local_cred.pid = getpid();
274+
#else
275+
xucred local_cred;
276+
local_cred.cr_uid = getuid();
277+
/* XXX!
278+
local_cred.cr_gid = getgid();
279+
local_cred.cr_pid = getpid();
280+
*/
281+
#endif
269282

270283
// Our local sockaddr, which we only need if we didn't have a
271284
// bind() before our connect.
@@ -448,11 +461,20 @@ int Socket::accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
448461
} else {
449462
// We use SO_PEERCRED to get uid, gid and pid in order to generate
450463
// unique IP addresses.
464+
#if defined(SO_PEERCRED)
451465
ucred peercred;
452466
socklen_t len = sizeof peercred;
453467

454468
if (getsockopt(sockfd, SOL_SOCKET, SO_PEERCRED, &peercred, &len) == -1)
455469
return -1;
470+
#else
471+
xucred peercred;
472+
socklen_t len = sizeof peercred;
473+
474+
if (getsockopt(sockfd, SOL_LOCAL, LOCAL_PEERCRED, &peercred,
475+
&len) == -1)
476+
return -1;
477+
#endif
456478

457479
if (!peer.set_host(peercred)) {
458480
errno = EINVAL;

0 commit comments

Comments
 (0)