From 7409cf5abf68b464a67e3aee0d4e6099691d393a Mon Sep 17 00:00:00 2001 From: Matheus Date: Sun, 24 May 2026 10:06:16 -0300 Subject: [PATCH] localsocket: implement SO_PEERCRED --- kernel-src/io/net/localsocket.c | 56 +++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/kernel-src/io/net/localsocket.c b/kernel-src/io/net/localsocket.c index 4c997696..2c102557 100644 --- a/kernel-src/io/net/localsocket.c +++ b/kernel-src/io/net/localsocket.c @@ -10,6 +10,12 @@ #define FILE_COUNT 16 #define BARRIER_SIZE 16 +typedef struct { + pid_t pid; + uid_t uid; + gid_t gid; +} localsock_cred_t; + struct localpair_t; struct binding_t; typedef struct { @@ -29,6 +35,7 @@ typedef struct { uintmax_t barrierwrite; // shared with pair int filesremaining[BARRIER_SIZE]; // shared with pair int bytesremaining[BARRIER_SIZE]; // shared with pair + localsock_cred_t cred; } localsocket_t; // created by the client socket @@ -575,6 +582,9 @@ static int localsock_accept(socket_t *_server, socket_t *_clientconnection, sock clientconnection->pair = pair; pair->server = clientconnection; + if (current_thread()->proc) + clientconnection->cred = server->cred; + // signal to the client that they can start sending data now poll_event(&pair->client->socket.pollheader, POLLOUT); @@ -608,6 +618,12 @@ static int localsock_connect(socket_t *socket, sockaddr_t *addr, uintmax_t flags goto leave; } + if (current_thread()->proc) { + localsocket->cred.pid = current_thread()->proc->pid; + localsocket->cred.uid = current_thread()->proc->cred.euid; + localsocket->cred.uid = current_thread()->proc->cred.egid; + } + // get the vnode specified in addr refnode = addr->path[0] == '/' ? proc_get_root() : proc_get_cwd(); error = vfs_lookup(&result, refnode, addr->path, NULL, 0); @@ -776,6 +792,12 @@ static int localsock_listen(socket_t *socket, int backlogsize) { goto leave; } + if (current_thread()->proc) { + localsocket->cred.pid = current_thread()->proc->pid; + localsocket->cred.uid = current_thread()->proc->cred.euid; + localsocket->cred.uid = current_thread()->proc->cred.egid; + } + MUTEX_ACQUIRE(&localsocket->binding->mutex); localsocket->backlog = alloc(backlogsize * sizeof(localpair_t *)); @@ -985,6 +1007,13 @@ int localsock_pair(socket_t **ret1, socket_t **ret2) { ((localsocket_t *)socket1)->pair = pair; ((localsocket_t *)socket2)->pair = pair; + if (current_thread()->proc) { + pair->server->cred.pid = current_thread()->proc->pid; + pair->server->cred.uid = current_thread()->proc->cred.euid; + pair->server->cred.uid = current_thread()->proc->cred.egid; + pair->client->cred = pair->server->cred; + } + *ret1 = socket1; *ret2 = socket2; return 0; @@ -1074,6 +1103,7 @@ static int localsock_setopt(socket_t *socket, int layer, int optname, void *buff } static int localsock_getopt(socket_t *socket, int layer, int optname, void *unsafe_buffer, socklen_t *unsafe_len, cred_t *cred) { + localsocket_t *localsocket = (localsocket_t *)socket; socklen_t len; int error = USERCOPY_POSSIBLY_FROM_USER(&len, unsafe_len, sizeof(len)); if (error) @@ -1081,6 +1111,32 @@ static int localsock_getopt(socket_t *socket, int layer, int optname, void *unsa if (layer == SOL_SOCKET) { switch (optname) { + case SO_PEERCRED: { + if (len != sizeof(localsock_cred_t)) + return EINVAL; + + localpair_t *pair = localsocket->pair; + // socket not connected + if (pair == NULL) { + MUTEX_RELEASE(&socket->mutex); + return ENOTCONN; + } + + MUTEX_ACQUIRE(&pair->mutex); + localsocket_t *peer = pair->client == localsocket ? pair->server : pair->client; + if (peer == NULL) { + MUTEX_RELEASE(&pair->mutex); + MUTEX_RELEASE(&socket->mutex); + return ENOTCONN; + } + + localsock_cred_t cred = peer->cred; + + MUTEX_RELEASE(&pair->mutex); + + int error = USERCOPY_POSSIBLY_TO_USER(unsafe_buffer, &cred, sizeof(cred)); + return error; + } case SO_SNDLOWAT: { int value = 1; return USERCOPY_POSSIBLY_TO_USER(unsafe_buffer, &value, len);