mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-22 12:35:14 +00:00
Kernel: Strip SUID+SGID bits from file when written to or chowned
Fixes #1624.
This commit is contained in:
parent
040ba77d44
commit
53d0ca2ad8
Notes:
sideshowbarker
2024-07-19 07:56:12 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/53d0ca2ad8a
6 changed files with 36 additions and 0 deletions
|
@ -760,6 +760,10 @@ ssize_t Ext2FSInode::write_bytes(off_t offset, ssize_t count, const u8* data, Fi
|
|||
Locker inode_locker(m_lock);
|
||||
Locker fs_locker(fs().m_lock);
|
||||
|
||||
auto result = prepare_to_write_data();
|
||||
if (result.is_error())
|
||||
return result;
|
||||
|
||||
if (is_symlink()) {
|
||||
ASSERT(offset == 0);
|
||||
if (max((size_t)(offset + count), (size_t)m_raw_inode.i_size) < max_inline_symlink_length) {
|
||||
|
|
|
@ -217,4 +217,19 @@ void Inode::set_metadata_dirty(bool metadata_dirty)
|
|||
}
|
||||
}
|
||||
|
||||
KResult Inode::prepare_to_write_data()
|
||||
{
|
||||
// FIXME: It's a poor design that filesystems are expected to call this before writing out data.
|
||||
// We should funnel everything through an interface at the VFS layer so this can happen from a single place.
|
||||
LOCKER(m_lock);
|
||||
if (fs().is_readonly())
|
||||
return KResult(-EROFS);
|
||||
auto metadata = this->metadata();
|
||||
if (metadata.is_setuid() || metadata.is_setgid()) {
|
||||
dbg() << "Inode::prepare_to_write_data(): Stripping SUID/SGID bits from " << identifier();
|
||||
return chmod(metadata.mode & ~(04000 | 02000));
|
||||
}
|
||||
return KSuccess;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -119,6 +119,7 @@ protected:
|
|||
void set_metadata_dirty(bool);
|
||||
void inode_contents_changed(off_t, ssize_t, const u8*);
|
||||
void inode_size_changed(size_t old_size, size_t new_size);
|
||||
KResult prepare_to_write_data();
|
||||
|
||||
mutable Lock m_lock { "Inode" };
|
||||
|
||||
|
|
|
@ -1435,6 +1435,10 @@ void ProcFSInode::flush_metadata()
|
|||
|
||||
ssize_t ProcFSInode::write_bytes(off_t offset, ssize_t size, const u8* buffer, FileDescription*)
|
||||
{
|
||||
auto result = prepare_to_write_data();
|
||||
if (result.is_error())
|
||||
return result;
|
||||
|
||||
auto* directory_entry = fs().get_directory_entry(identifier());
|
||||
|
||||
Function<ssize_t(InodeIdentifier, const ByteBuffer&)> callback_tmp;
|
||||
|
|
|
@ -207,6 +207,10 @@ ssize_t TmpFSInode::write_bytes(off_t offset, ssize_t size, const u8* buffer, Fi
|
|||
ASSERT(!is_directory());
|
||||
ASSERT(offset >= 0);
|
||||
|
||||
auto result = prepare_to_write_data();
|
||||
if (result.is_error())
|
||||
return result;
|
||||
|
||||
off_t old_size = m_metadata.size;
|
||||
off_t new_size = m_metadata.size;
|
||||
if ((offset + size) > new_size)
|
||||
|
|
|
@ -511,6 +511,14 @@ KResult VFS::chown(Inode& inode, uid_t a_uid, gid_t a_gid)
|
|||
}
|
||||
|
||||
dbg() << "VFS::chown(): inode " << inode.identifier() << " <- uid:" << new_uid << " gid:" << new_gid;
|
||||
|
||||
if (metadata.is_setuid() || metadata.is_setgid()) {
|
||||
dbg() << "VFS::chown(): Stripping SUID/SGID bits from " << inode.identifier();
|
||||
auto result = inode.chmod(metadata.mode & ~(04000 | 02000));
|
||||
if (result.is_error())
|
||||
return result;
|
||||
}
|
||||
|
||||
return inode.chown(new_uid, new_gid);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue