Skip to content

Commit 92cd86f

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 aef1c6f commit 92cd86f

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

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

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

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

0 commit comments

Comments
 (0)