diff --git a/Kernel/FileSystem/ProcFS.cpp b/Kernel/FileSystem/ProcFS.cpp index 749a169538..26b8332265 100644 --- a/Kernel/FileSystem/ProcFS.cpp +++ b/Kernel/FileSystem/ProcFS.cpp @@ -432,7 +432,11 @@ Optional procfs$net_local(InodeIdentifier) auto obj = array.add_object(); obj.add("path", String(socket.socket_path())); obj.add("origin_pid", socket.origin_pid()); + obj.add("origin_uid", socket.origin_uid()); + obj.add("origin_gid", socket.origin_gid()); obj.add("acceptor_pid", socket.acceptor_pid()); + obj.add("acceptor_uid", socket.acceptor_pid()); + obj.add("acceptor_gid", socket.acceptor_pid()); }); array.finish(); return builder.build(); diff --git a/Kernel/Net/IPv4Socket.cpp b/Kernel/Net/IPv4Socket.cpp index 06d3e21249..a1f4cd6229 100644 --- a/Kernel/Net/IPv4Socket.cpp +++ b/Kernel/Net/IPv4Socket.cpp @@ -361,10 +361,10 @@ KResult IPv4Socket::setsockopt(int level, int option, const void* value, socklen } } -KResult IPv4Socket::getsockopt(int level, int option, void* value, socklen_t* value_size) +KResult IPv4Socket::getsockopt(FileDescription& description, int level, int option, void* value, socklen_t* value_size) { if (level != IPPROTO_IP) - return Socket::getsockopt(level, option, value, value_size); + return Socket::getsockopt(description, level, option, value, value_size); switch (option) { case IP_TTL: diff --git a/Kernel/Net/IPv4Socket.h b/Kernel/Net/IPv4Socket.h index 5c887ae2d6..6c9c5f2121 100644 --- a/Kernel/Net/IPv4Socket.h +++ b/Kernel/Net/IPv4Socket.h @@ -32,7 +32,7 @@ public: virtual ssize_t sendto(FileDescription&, const void*, size_t, int, const sockaddr*, socklen_t) override; virtual ssize_t recvfrom(FileDescription&, void*, size_t, int flags, sockaddr*, socklen_t*) override; virtual KResult setsockopt(int level, int option, const void*, socklen_t) override; - virtual KResult getsockopt(int level, int option, void*, socklen_t*) override; + virtual KResult getsockopt(FileDescription&, int level, int option, void*, socklen_t*) override; virtual int ioctl(FileDescription&, unsigned request, unsigned arg) override; diff --git a/Kernel/Net/LocalSocket.cpp b/Kernel/Net/LocalSocket.cpp index d41d445620..26affa2ee4 100644 --- a/Kernel/Net/LocalSocket.cpp +++ b/Kernel/Net/LocalSocket.cpp @@ -33,6 +33,7 @@ LocalSocket::LocalSocket(int type) { LOCKER(all_sockets().lock()); all_sockets().resource().append(this); + #ifdef DEBUG_LOCAL_SOCKET kprintf("%s(%u) LocalSocket{%p} created with type=%u\n", current->process().name().characters(), current->pid(), this, type); #endif @@ -302,3 +303,34 @@ String LocalSocket::absolute_path(const FileDescription& description) const return builder.to_string(); } + +KResult LocalSocket::getsockopt(FileDescription& description, int level, int option, void* value, socklen_t* value_size) +{ + if (level != SOL_SOCKET) + return Socket::getsockopt(description, level, option, value, value_size); + + switch (option) { + case SO_PEERCRED: { + if (*value_size < sizeof(ucred)) + return KResult(-EINVAL); + auto& creds = *(ucred*)value; + switch (role(description)) { + case Role::Accepted: + creds = m_origin; + *value_size = sizeof(ucred); + return KSuccess; + case Role::Connected: + creds = m_acceptor; + *value_size = sizeof(ucred); + return KSuccess; + case Role::Connecting: + return KResult(-ENOTCONN); + default: + return KResult(-EINVAL); + } + break; + } + default: + return Socket::getsockopt(description, level, option, value, value_size); + } +} diff --git a/Kernel/Net/LocalSocket.h b/Kernel/Net/LocalSocket.h index 7677a25e8d..2d3566eb4c 100644 --- a/Kernel/Net/LocalSocket.h +++ b/Kernel/Net/LocalSocket.h @@ -29,6 +29,7 @@ public: virtual bool can_write(const FileDescription&) const override; virtual ssize_t sendto(FileDescription&, const void*, size_t, int, const sockaddr*, socklen_t) override; virtual ssize_t recvfrom(FileDescription&, void*, size_t, int flags, sockaddr*, socklen_t*) override; + virtual KResult getsockopt(FileDescription&, int level, int option, void*, socklen_t*) override; private: explicit LocalSocket(int type); diff --git a/Kernel/Net/Socket.cpp b/Kernel/Net/Socket.cpp index b174cba69b..e65507da82 100644 --- a/Kernel/Net/Socket.cpp +++ b/Kernel/Net/Socket.cpp @@ -27,7 +27,8 @@ Socket::Socket(int domain, int type, int protocol) , m_type(type) , m_protocol(protocol) { - m_origin_pid = current->pid(); + auto& process = current->process(); + m_origin = { process.pid(), process.uid(), process.gid() }; } Socket::~Socket() @@ -53,7 +54,8 @@ RefPtr Socket::accept() #endif auto client = m_pending.take_first(); ASSERT(!client->is_connected()); - client->m_acceptor_pid = m_origin_pid; + auto& process = current->process(); + client->m_acceptor = { process.pid(), process.uid(), process.gid() }; client->m_connected = true; client->m_role = Role::Accepted; return client; @@ -91,7 +93,7 @@ KResult Socket::setsockopt(int level, int option, const void* value, socklen_t v } } -KResult Socket::getsockopt(int level, int option, void* value, socklen_t* value_size) +KResult Socket::getsockopt(FileDescription&, int level, int option, void* value, socklen_t* value_size) { ASSERT(level == SOL_SOCKET); switch (option) { diff --git a/Kernel/Net/Socket.h b/Kernel/Net/Socket.h index c297aa8e7b..6a1a21334d 100644 --- a/Kernel/Net/Socket.h +++ b/Kernel/Net/Socket.h @@ -77,10 +77,14 @@ public: virtual ssize_t recvfrom(FileDescription&, void*, size_t, int flags, sockaddr*, socklen_t*) = 0; virtual KResult setsockopt(int level, int option, const void*, socklen_t); - virtual KResult getsockopt(int level, int option, void*, socklen_t*); + virtual KResult getsockopt(FileDescription&, int level, int option, void*, socklen_t*); - pid_t origin_pid() const { return m_origin_pid; } - pid_t acceptor_pid() const { return m_acceptor_pid; } + pid_t origin_pid() const { return m_origin.pid; } + uid_t origin_uid() const { return m_origin.uid; } + gid_t origin_gid() const { return m_origin.gid; } + pid_t acceptor_pid() const { return m_acceptor.pid; } + uid_t acceptor_uid() const { return m_acceptor.uid; } + gid_t acceptor_gid() const { return m_acceptor.gid; } timeval receive_deadline() const { return m_receive_deadline; } timeval send_deadline() const { return m_send_deadline; } @@ -107,12 +111,15 @@ protected: Role m_role { Role::None }; +protected: + ucred m_origin { 0, 0, 0 }; + ucred m_acceptor { 0, 0, 0 }; + private: virtual bool is_socket() const final { return true; } Lock m_lock { "Socket" }; - pid_t m_origin_pid { 0 }; - pid_t m_acceptor_pid { 0 }; + int m_domain { 0 }; int m_type { 0 }; int m_protocol { 0 }; diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 074e96896a..b7041c190a 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -2678,7 +2678,7 @@ int Process::sys$getsockopt(const Syscall::SC_getsockopt_params* params) if (!description->is_socket()) return -ENOTSOCK; auto& socket = *description->socket(); - return socket.getsockopt(level, option, value, value_size); + return socket.getsockopt(*description, level, option, value, value_size); } int Process::sys$setsockopt(const Syscall::SC_setsockopt_params* params) diff --git a/Kernel/UnixTypes.h b/Kernel/UnixTypes.h index 20af416642..d23b3c7fc5 100644 --- a/Kernel/UnixTypes.h +++ b/Kernel/UnixTypes.h @@ -337,6 +337,7 @@ struct pollfd { #define SO_SNDTIMEO 2 #define SO_KEEPALIVE 3 #define SO_ERROR 4 +#define SO_PEERCRED 5 #define IPPROTO_IP 0 #define IPPROTO_ICMP 1 @@ -345,6 +346,12 @@ struct pollfd { #define IP_TTL 2 +struct ucred { + pid_t pid; + uid_t uid; + gid_t gid; +}; + struct sockaddr { u16 sa_family; char sa_data[14]; diff --git a/Libraries/LibC/sys/socket.h b/Libraries/LibC/sys/socket.h index c89a2176d7..af98d67d05 100644 --- a/Libraries/LibC/sys/socket.h +++ b/Libraries/LibC/sys/socket.h @@ -46,6 +46,12 @@ struct sockaddr_in { char sin_zero[8]; }; +struct ucred { + pid_t pid; + uid_t uid; + gid_t gid; +}; + #define SOL_SOCKET 1 #define SOMAXCONN 128 @@ -53,6 +59,7 @@ struct sockaddr_in { #define SO_SNDTIMEO 2 #define SO_KEEPALIVE 3 #define SO_ERROR 4 +#define SO_PEERCRED 5 int socket(int domain, int type, int protocol); int bind(int sockfd, const struct sockaddr* addr, socklen_t);