Kernel: Add getsockopt(SO_PEERCRED) for local sockets
This sockopt gives you a struct with the PID, UID and GID of a socket's peer process.
This commit is contained in:
parent
6e6e0b9de8
commit
23e802518d
Notes:
sideshowbarker
2024-07-19 10:57:21 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/23e802518d6
10 changed files with 72 additions and 12 deletions
|
@ -432,7 +432,11 @@ Optional<KBuffer> procfs$net_local(InodeIdentifier)
|
||||||
auto obj = array.add_object();
|
auto obj = array.add_object();
|
||||||
obj.add("path", String(socket.socket_path()));
|
obj.add("path", String(socket.socket_path()));
|
||||||
obj.add("origin_pid", socket.origin_pid());
|
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_pid", socket.acceptor_pid());
|
||||||
|
obj.add("acceptor_uid", socket.acceptor_pid());
|
||||||
|
obj.add("acceptor_gid", socket.acceptor_pid());
|
||||||
});
|
});
|
||||||
array.finish();
|
array.finish();
|
||||||
return builder.build();
|
return builder.build();
|
||||||
|
|
|
@ -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)
|
if (level != IPPROTO_IP)
|
||||||
return Socket::getsockopt(level, option, value, value_size);
|
return Socket::getsockopt(description, level, option, value, value_size);
|
||||||
|
|
||||||
switch (option) {
|
switch (option) {
|
||||||
case IP_TTL:
|
case IP_TTL:
|
||||||
|
|
|
@ -32,7 +32,7 @@ public:
|
||||||
virtual ssize_t sendto(FileDescription&, const void*, size_t, int, const sockaddr*, socklen_t) 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 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 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;
|
virtual int ioctl(FileDescription&, unsigned request, unsigned arg) override;
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@ LocalSocket::LocalSocket(int type)
|
||||||
{
|
{
|
||||||
LOCKER(all_sockets().lock());
|
LOCKER(all_sockets().lock());
|
||||||
all_sockets().resource().append(this);
|
all_sockets().resource().append(this);
|
||||||
|
|
||||||
#ifdef DEBUG_LOCAL_SOCKET
|
#ifdef DEBUG_LOCAL_SOCKET
|
||||||
kprintf("%s(%u) LocalSocket{%p} created with type=%u\n", current->process().name().characters(), current->pid(), this, type);
|
kprintf("%s(%u) LocalSocket{%p} created with type=%u\n", current->process().name().characters(), current->pid(), this, type);
|
||||||
#endif
|
#endif
|
||||||
|
@ -302,3 +303,34 @@ String LocalSocket::absolute_path(const FileDescription& description) const
|
||||||
|
|
||||||
return builder.to_string();
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ public:
|
||||||
virtual bool can_write(const FileDescription&) const override;
|
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 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 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:
|
private:
|
||||||
explicit LocalSocket(int type);
|
explicit LocalSocket(int type);
|
||||||
|
|
|
@ -27,7 +27,8 @@ Socket::Socket(int domain, int type, int protocol)
|
||||||
, m_type(type)
|
, m_type(type)
|
||||||
, m_protocol(protocol)
|
, m_protocol(protocol)
|
||||||
{
|
{
|
||||||
m_origin_pid = current->pid();
|
auto& process = current->process();
|
||||||
|
m_origin = { process.pid(), process.uid(), process.gid() };
|
||||||
}
|
}
|
||||||
|
|
||||||
Socket::~Socket()
|
Socket::~Socket()
|
||||||
|
@ -53,7 +54,8 @@ RefPtr<Socket> Socket::accept()
|
||||||
#endif
|
#endif
|
||||||
auto client = m_pending.take_first();
|
auto client = m_pending.take_first();
|
||||||
ASSERT(!client->is_connected());
|
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_connected = true;
|
||||||
client->m_role = Role::Accepted;
|
client->m_role = Role::Accepted;
|
||||||
return client;
|
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);
|
ASSERT(level == SOL_SOCKET);
|
||||||
switch (option) {
|
switch (option) {
|
||||||
|
|
|
@ -77,10 +77,14 @@ public:
|
||||||
virtual ssize_t recvfrom(FileDescription&, void*, size_t, int flags, sockaddr*, socklen_t*) = 0;
|
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 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 origin_pid() const { return m_origin.pid; }
|
||||||
pid_t acceptor_pid() const { return m_acceptor_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 receive_deadline() const { return m_receive_deadline; }
|
||||||
timeval send_deadline() const { return m_send_deadline; }
|
timeval send_deadline() const { return m_send_deadline; }
|
||||||
|
@ -107,12 +111,15 @@ protected:
|
||||||
|
|
||||||
Role m_role { Role::None };
|
Role m_role { Role::None };
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ucred m_origin { 0, 0, 0 };
|
||||||
|
ucred m_acceptor { 0, 0, 0 };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual bool is_socket() const final { return true; }
|
virtual bool is_socket() const final { return true; }
|
||||||
|
|
||||||
Lock m_lock { "Socket" };
|
Lock m_lock { "Socket" };
|
||||||
pid_t m_origin_pid { 0 };
|
|
||||||
pid_t m_acceptor_pid { 0 };
|
|
||||||
int m_domain { 0 };
|
int m_domain { 0 };
|
||||||
int m_type { 0 };
|
int m_type { 0 };
|
||||||
int m_protocol { 0 };
|
int m_protocol { 0 };
|
||||||
|
|
|
@ -2678,7 +2678,7 @@ int Process::sys$getsockopt(const Syscall::SC_getsockopt_params* params)
|
||||||
if (!description->is_socket())
|
if (!description->is_socket())
|
||||||
return -ENOTSOCK;
|
return -ENOTSOCK;
|
||||||
auto& socket = *description->socket();
|
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)
|
int Process::sys$setsockopt(const Syscall::SC_setsockopt_params* params)
|
||||||
|
|
|
@ -337,6 +337,7 @@ struct pollfd {
|
||||||
#define SO_SNDTIMEO 2
|
#define SO_SNDTIMEO 2
|
||||||
#define SO_KEEPALIVE 3
|
#define SO_KEEPALIVE 3
|
||||||
#define SO_ERROR 4
|
#define SO_ERROR 4
|
||||||
|
#define SO_PEERCRED 5
|
||||||
|
|
||||||
#define IPPROTO_IP 0
|
#define IPPROTO_IP 0
|
||||||
#define IPPROTO_ICMP 1
|
#define IPPROTO_ICMP 1
|
||||||
|
@ -345,6 +346,12 @@ struct pollfd {
|
||||||
|
|
||||||
#define IP_TTL 2
|
#define IP_TTL 2
|
||||||
|
|
||||||
|
struct ucred {
|
||||||
|
pid_t pid;
|
||||||
|
uid_t uid;
|
||||||
|
gid_t gid;
|
||||||
|
};
|
||||||
|
|
||||||
struct sockaddr {
|
struct sockaddr {
|
||||||
u16 sa_family;
|
u16 sa_family;
|
||||||
char sa_data[14];
|
char sa_data[14];
|
||||||
|
|
|
@ -46,6 +46,12 @@ struct sockaddr_in {
|
||||||
char sin_zero[8];
|
char sin_zero[8];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ucred {
|
||||||
|
pid_t pid;
|
||||||
|
uid_t uid;
|
||||||
|
gid_t gid;
|
||||||
|
};
|
||||||
|
|
||||||
#define SOL_SOCKET 1
|
#define SOL_SOCKET 1
|
||||||
#define SOMAXCONN 128
|
#define SOMAXCONN 128
|
||||||
|
|
||||||
|
@ -53,6 +59,7 @@ struct sockaddr_in {
|
||||||
#define SO_SNDTIMEO 2
|
#define SO_SNDTIMEO 2
|
||||||
#define SO_KEEPALIVE 3
|
#define SO_KEEPALIVE 3
|
||||||
#define SO_ERROR 4
|
#define SO_ERROR 4
|
||||||
|
#define SO_PEERCRED 5
|
||||||
|
|
||||||
int socket(int domain, int type, int protocol);
|
int socket(int domain, int type, int protocol);
|
||||||
int bind(int sockfd, const struct sockaddr* addr, socklen_t);
|
int bind(int sockfd, const struct sockaddr* addr, socklen_t);
|
||||||
|
|
Loading…
Add table
Reference in a new issue