Skip to content

Commit 6d6101d

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 fa17393 commit 6d6101d

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"
@@ -266,10 +270,19 @@ bool Socket::create_binding(const SockAddr &addr)
266270
if (!local.set_host(addr))
267271
return false;
268272
} else {
273+
#if defined(SO_PEERCRED)
269274
ucred local_cred;
270275
local_cred.uid = getuid();
271276
local_cred.gid = getgid();
272277
local_cred.pid = getpid();
278+
#else
279+
xucred local_cred;
280+
local_cred.cr_uid = getuid();
281+
/* XXX!
282+
local_cred.cr_gid = getgid();
283+
local_cred.cr_pid = getpid();
284+
*/
285+
#endif
273286

274287
// Our local sockaddr, which we only need if we didn't have a
275288
// bind() before our connect.
@@ -454,11 +467,20 @@ int Socket::accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
454467
} else {
455468
// We use SO_PEERCRED to get uid, gid and pid in order to generate
456469
// unique IP addresses.
470+
#if defined(SO_PEERCRED)
457471
ucred peercred;
458472
socklen_t len = sizeof peercred;
459473

460474
if (getsockopt(sockfd, SOL_SOCKET, SO_PEERCRED, &peercred, &len) == -1)
461475
return -1;
476+
#else
477+
xucred peercred;
478+
socklen_t len = sizeof peercred;
479+
480+
if (getsockopt(sockfd, SOL_LOCAL, LOCAL_PEERCRED, &peercred,
481+
&len) == -1)
482+
return -1;
483+
#endif
462484

463485
if (!peer.set_host(peercred)) {
464486
errno = EINVAL;

0 commit comments

Comments
 (0)