mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 02:17:35 +00:00
Kernel: Allow fchmod() and fchown() on pre-bind() local sockets
In order to ensure a specific owner and mode when the local socket filesystem endpoint is instantiated, we need to be able to call fchmod() and fchown() on a socket fd between socket() and bind(). This is because until we call bind(), there is no filesystem inode for the socket yet.
This commit is contained in:
parent
4abbedb6e4
commit
d84299c7be
8 changed files with 57 additions and 13 deletions
|
@ -34,6 +34,10 @@ LocalSocket::LocalSocket(int type)
|
|||
LOCKER(all_sockets().lock());
|
||||
all_sockets().resource().append(this);
|
||||
|
||||
m_prebind_uid = current->process().uid();
|
||||
m_prebind_gid = current->process().gid();
|
||||
m_prebind_mode = 0666;
|
||||
|
||||
#ifdef DEBUG_LOCAL_SOCKET
|
||||
kprintf("%s(%u) LocalSocket{%p} created with type=%u\n", current->process().name().characters(), current->pid(), this, type);
|
||||
#endif
|
||||
|
@ -76,7 +80,9 @@ KResult LocalSocket::bind(const sockaddr* address, socklen_t address_size)
|
|||
kprintf("%s(%u) LocalSocket{%p} bind(%s)\n", current->process().name().characters(), current->pid(), this, safe_address);
|
||||
#endif
|
||||
|
||||
auto result = VFS::the().open(safe_address, O_CREAT | O_EXCL, S_IFSOCK | 0666, current->process().current_directory());
|
||||
mode_t mode = S_IFSOCK | (m_prebind_mode & ~current->process().umask());
|
||||
UidAndGid owner { m_prebind_uid, m_prebind_gid };
|
||||
auto result = VFS::the().open( safe_address, O_CREAT | O_EXCL, mode, current->process().current_directory(), owner);
|
||||
if (result.is_error()) {
|
||||
if (result.error() == -EEXIST)
|
||||
return KResult(-EADDRINUSE);
|
||||
|
@ -334,3 +340,25 @@ KResult LocalSocket::getsockopt(FileDescription& description, int level, int opt
|
|||
return Socket::getsockopt(description, level, option, value, value_size);
|
||||
}
|
||||
}
|
||||
|
||||
KResult LocalSocket::chmod(mode_t mode)
|
||||
{
|
||||
if (m_file)
|
||||
return m_file->chmod(mode);
|
||||
|
||||
m_prebind_mode = mode & 04777;
|
||||
return KSuccess;
|
||||
}
|
||||
|
||||
KResult LocalSocket::chown(uid_t uid, gid_t gid)
|
||||
{
|
||||
if (m_file)
|
||||
return m_file->chown(uid, gid);
|
||||
|
||||
if (!current->process().is_superuser() && (current->process().euid() != uid || !current->process().in_group(gid)))
|
||||
return KResult(-EPERM);
|
||||
|
||||
m_prebind_uid = uid;
|
||||
m_prebind_gid = gid;
|
||||
return KSuccess;
|
||||
}
|
||||
|
|
|
@ -30,6 +30,8 @@ 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 getsockopt(FileDescription&, int level, int option, void*, socklen_t*) override;
|
||||
virtual KResult chown(uid_t, gid_t) override;
|
||||
virtual KResult chmod(mode_t) override;
|
||||
|
||||
private:
|
||||
explicit LocalSocket(int type);
|
||||
|
@ -43,6 +45,10 @@ private:
|
|||
// An open socket file on the filesystem.
|
||||
RefPtr<FileDescription> m_file;
|
||||
|
||||
uid_t m_prebind_uid { 0 };
|
||||
uid_t m_prebind_gid { 0 };
|
||||
mode_t m_prebind_mode { 0 };
|
||||
|
||||
// A single LocalSocket is shared between two file descriptions
|
||||
// on the connect side and the accept side; so we need to store
|
||||
// an additional role for the connect side and differentiate
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue