mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 09:42:45 +00:00 
			
		
		
		
	Kernel: Allow passing initial UID and GID when creating new inodes
If we're creating something that should have a different owner than the current process's UID/GID, we need to plumb that all the way through VFS down to the FS functions.
This commit is contained in:
		
							parent
							
								
									82760998a9
								
							
						
					
					
						commit
						4abbedb6e4
					
				
					 11 changed files with 41 additions and 33 deletions
				
			
		|  | @ -51,13 +51,13 @@ InodeIdentifier DevPtsFS::root_inode() const | ||||||
|     return { fsid(), 1 }; |     return { fsid(), 1 }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| RefPtr<Inode> DevPtsFS::create_inode(InodeIdentifier, const String&, mode_t, off_t, dev_t, int& error) | RefPtr<Inode> DevPtsFS::create_inode(InodeIdentifier, const String&, mode_t, off_t, dev_t, uid_t, gid_t, int& error) | ||||||
| { | { | ||||||
|     error = -EROFS; |     error = -EROFS; | ||||||
|     return nullptr; |     return nullptr; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| RefPtr<Inode> DevPtsFS::create_directory(InodeIdentifier, const String&, mode_t, int& error) | RefPtr<Inode> DevPtsFS::create_directory(InodeIdentifier, const String&, mode_t, uid_t, gid_t, int& error) | ||||||
| { | { | ||||||
|     error = -EROFS; |     error = -EROFS; | ||||||
|     return nullptr; |     return nullptr; | ||||||
|  |  | ||||||
|  | @ -16,8 +16,8 @@ public: | ||||||
|     virtual const char* class_name() const override { return "DevPtsFS"; } |     virtual const char* class_name() const override { return "DevPtsFS"; } | ||||||
| 
 | 
 | ||||||
|     virtual InodeIdentifier root_inode() const override; |     virtual InodeIdentifier root_inode() const override; | ||||||
|     virtual RefPtr<Inode> create_inode(InodeIdentifier parentInode, const String& name, mode_t, off_t size, dev_t, int& error) override; |     virtual RefPtr<Inode> create_inode(InodeIdentifier parentInode, const String& name, mode_t, off_t size, dev_t, uid_t, gid_t, int& error) override; | ||||||
|     virtual RefPtr<Inode> create_directory(InodeIdentifier parentInode, const String& name, mode_t, int& error) override; |     virtual RefPtr<Inode> create_directory(InodeIdentifier parentInode, const String& name, mode_t, uid_t, gid_t, int& error) override; | ||||||
|     virtual RefPtr<Inode> get_inode(InodeIdentifier) const override; |     virtual RefPtr<Inode> get_inode(InodeIdentifier) const override; | ||||||
| 
 | 
 | ||||||
|     static void register_slave_pty(SlavePTY&); |     static void register_slave_pty(SlavePTY&); | ||||||
|  |  | ||||||
|  | @ -1284,7 +1284,7 @@ bool Ext2FS::set_block_allocation_state(BlockIndex block_index, bool new_state) | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| RefPtr<Inode> Ext2FS::create_directory(InodeIdentifier parent_id, const String& name, mode_t mode, int& error) | RefPtr<Inode> Ext2FS::create_directory(InodeIdentifier parent_id, const String& name, mode_t mode, uid_t uid, gid_t gid, int& error) | ||||||
| { | { | ||||||
|     LOCKER(m_lock); |     LOCKER(m_lock); | ||||||
|     ASSERT(parent_id.fsid() == fsid()); |     ASSERT(parent_id.fsid() == fsid()); | ||||||
|  | @ -1296,7 +1296,7 @@ RefPtr<Inode> Ext2FS::create_directory(InodeIdentifier parent_id, const String& | ||||||
| 
 | 
 | ||||||
|     // NOTE: When creating a new directory, make the size 1 block.
 |     // NOTE: When creating a new directory, make the size 1 block.
 | ||||||
|     //       There's probably a better strategy here, but this works for now.
 |     //       There's probably a better strategy here, but this works for now.
 | ||||||
|     auto inode = create_inode(parent_id, name, mode, block_size(), 0, error); |     auto inode = create_inode(parent_id, name, mode, block_size(), 0, uid, gid, error); | ||||||
|     if (!inode) |     if (!inode) | ||||||
|         return nullptr; |         return nullptr; | ||||||
| 
 | 
 | ||||||
|  | @ -1328,7 +1328,7 @@ RefPtr<Inode> Ext2FS::create_directory(InodeIdentifier parent_id, const String& | ||||||
|     return inode; |     return inode; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| RefPtr<Inode> Ext2FS::create_inode(InodeIdentifier parent_id, const String& name, mode_t mode, off_t size, dev_t dev, int& error) | RefPtr<Inode> Ext2FS::create_inode(InodeIdentifier parent_id, const String& name, mode_t mode, off_t size, dev_t dev, uid_t uid, gid_t gid, int& error) | ||||||
| { | { | ||||||
|     LOCKER(m_lock); |     LOCKER(m_lock); | ||||||
|     ASSERT(parent_id.fsid() == fsid()); |     ASSERT(parent_id.fsid() == fsid()); | ||||||
|  | @ -1378,8 +1378,8 @@ RefPtr<Inode> Ext2FS::create_inode(InodeIdentifier parent_id, const String& name | ||||||
|     ext2_inode e2inode; |     ext2_inode e2inode; | ||||||
|     memset(&e2inode, 0, sizeof(ext2_inode)); |     memset(&e2inode, 0, sizeof(ext2_inode)); | ||||||
|     e2inode.i_mode = mode; |     e2inode.i_mode = mode; | ||||||
|     e2inode.i_uid = current->process().euid(); |     e2inode.i_uid = uid; | ||||||
|     e2inode.i_gid = current->process().egid(); |     e2inode.i_gid = gid; | ||||||
|     e2inode.i_size = size; |     e2inode.i_size = size; | ||||||
|     e2inode.i_atime = now.tv_sec; |     e2inode.i_atime = now.tv_sec; | ||||||
|     e2inode.i_ctime = now.tv_sec; |     e2inode.i_ctime = now.tv_sec; | ||||||
|  |  | ||||||
|  | @ -99,8 +99,8 @@ private: | ||||||
| 
 | 
 | ||||||
|     virtual const char* class_name() const override; |     virtual const char* class_name() const override; | ||||||
|     virtual InodeIdentifier root_inode() const override; |     virtual InodeIdentifier root_inode() const override; | ||||||
|     virtual RefPtr<Inode> create_inode(InodeIdentifier parentInode, const String& name, mode_t, off_t size, dev_t, int& error) override; |     virtual RefPtr<Inode> create_inode(InodeIdentifier parentInode, const String& name, mode_t, off_t size, dev_t, uid_t, gid_t, int& error) override; | ||||||
|     virtual RefPtr<Inode> create_directory(InodeIdentifier parentInode, const String& name, mode_t, int& error) override; |     virtual RefPtr<Inode> create_directory(InodeIdentifier parentInode, const String& name, mode_t, uid_t, gid_t, int& error) override; | ||||||
|     virtual RefPtr<Inode> get_inode(InodeIdentifier) const override; |     virtual RefPtr<Inode> get_inode(InodeIdentifier) const override; | ||||||
|     virtual void flush_writes() override; |     virtual void flush_writes() override; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -58,8 +58,8 @@ public: | ||||||
|         u8 file_type { 0 }; |         u8 file_type { 0 }; | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     virtual RefPtr<Inode> create_inode(InodeIdentifier parentInode, const String& name, mode_t, off_t size, dev_t, int& error) = 0; |     virtual RefPtr<Inode> create_inode(InodeIdentifier parentInode, const String& name, mode_t, off_t size, dev_t, uid_t, gid_t, int& error) = 0; | ||||||
|     virtual RefPtr<Inode> create_directory(InodeIdentifier parentInode, const String& name, mode_t, int& error) = 0; |     virtual RefPtr<Inode> create_directory(InodeIdentifier parentInode, const String& name, mode_t, uid_t, gid_t, int& error) = 0; | ||||||
| 
 | 
 | ||||||
|     virtual RefPtr<Inode> get_inode(InodeIdentifier) const = 0; |     virtual RefPtr<Inode> get_inode(InodeIdentifier) const = 0; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -947,13 +947,13 @@ const char* ProcFS::class_name() const | ||||||
|     return "ProcFS"; |     return "ProcFS"; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| RefPtr<Inode> ProcFS::create_inode(InodeIdentifier, const String&, mode_t, off_t, dev_t, int&) | RefPtr<Inode> ProcFS::create_inode(InodeIdentifier, const String&, mode_t, off_t, dev_t, uid_t, gid_t, int&) | ||||||
| { | { | ||||||
|     kprintf("FIXME: Implement ProcFS::create_inode()?\n"); |     kprintf("FIXME: Implement ProcFS::create_inode()?\n"); | ||||||
|     return {}; |     return {}; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| RefPtr<Inode> ProcFS::create_directory(InodeIdentifier, const String&, mode_t, int& error) | RefPtr<Inode> ProcFS::create_directory(InodeIdentifier, const String&, mode_t, uid_t, gid_t, int& error) | ||||||
| { | { | ||||||
|     error = -EROFS; |     error = -EROFS; | ||||||
|     return nullptr; |     return nullptr; | ||||||
|  |  | ||||||
|  | @ -23,8 +23,8 @@ public: | ||||||
|     virtual InodeIdentifier root_inode() const override; |     virtual InodeIdentifier root_inode() const override; | ||||||
|     virtual RefPtr<Inode> get_inode(InodeIdentifier) const override; |     virtual RefPtr<Inode> get_inode(InodeIdentifier) const override; | ||||||
| 
 | 
 | ||||||
|     virtual RefPtr<Inode> create_inode(InodeIdentifier parent_id, const String& name, mode_t, off_t size, dev_t, int& error) override; |     virtual RefPtr<Inode> create_inode(InodeIdentifier parent_id, const String& name, mode_t, off_t size, dev_t, uid_t, gid_t, int& error) override; | ||||||
|     virtual RefPtr<Inode> create_directory(InodeIdentifier parent_id, const String& name, mode_t, int& error) override; |     virtual RefPtr<Inode> create_directory(InodeIdentifier parent_id, const String& name, mode_t, uid_t, gid_t, int& error) override; | ||||||
| 
 | 
 | ||||||
|     static void add_sys_bool(String&&, Lockable<bool>&, Function<void()>&& notify_callback = nullptr); |     static void add_sys_bool(String&&, Lockable<bool>&, Function<void()>&& notify_callback = nullptr); | ||||||
|     static void add_sys_string(String&&, Lockable<String>&, Function<void()>&& notify_callback = nullptr); |     static void add_sys_string(String&&, Lockable<String>&, Function<void()>&& notify_callback = nullptr); | ||||||
|  |  | ||||||
|  | @ -62,7 +62,7 @@ RefPtr<Inode> TmpFS::get_inode(InodeIdentifier identifier) const | ||||||
|     return it->value; |     return it->value; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| RefPtr<Inode> TmpFS::create_inode(InodeIdentifier parent_id, const String& name, mode_t mode, off_t size, dev_t dev, int& error) | RefPtr<Inode> TmpFS::create_inode(InodeIdentifier parent_id, const String& name, mode_t mode, off_t size, dev_t dev, uid_t uid, gid_t gid, int& error) | ||||||
| { | { | ||||||
|     LOCKER(m_lock); |     LOCKER(m_lock); | ||||||
|     ASSERT(parent_id.fsid() == fsid()); |     ASSERT(parent_id.fsid() == fsid()); | ||||||
|  | @ -75,8 +75,8 @@ RefPtr<Inode> TmpFS::create_inode(InodeIdentifier parent_id, const String& name, | ||||||
| 
 | 
 | ||||||
|     InodeMetadata metadata; |     InodeMetadata metadata; | ||||||
|     metadata.mode = mode; |     metadata.mode = mode; | ||||||
|     metadata.uid = current->process().euid(); |     metadata.uid = uid; | ||||||
|     metadata.gid = current->process().egid(); |     metadata.gid = gid; | ||||||
|     metadata.atime = now.tv_sec; |     metadata.atime = now.tv_sec; | ||||||
|     metadata.ctime = now.tv_sec; |     metadata.ctime = now.tv_sec; | ||||||
|     metadata.mtime = now.tv_sec; |     metadata.mtime = now.tv_sec; | ||||||
|  | @ -91,12 +91,12 @@ RefPtr<Inode> TmpFS::create_inode(InodeIdentifier parent_id, const String& name, | ||||||
|     return inode; |     return inode; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| RefPtr<Inode> TmpFS::create_directory(InodeIdentifier parent_id, const String& name, mode_t mode, int& error) | RefPtr<Inode> TmpFS::create_directory(InodeIdentifier parent_id, const String& name, mode_t mode, uid_t uid, gid_t gid, int& error) | ||||||
| { | { | ||||||
|     // Ensure it's a directory.
 |     // Ensure it's a directory.
 | ||||||
|     mode &= ~0170000; |     mode &= ~0170000; | ||||||
|     mode |= 0040000; |     mode |= 0040000; | ||||||
|     return create_inode(parent_id, name, mode, 0, 0, error); |     return create_inode(parent_id, name, mode, 0, 0, uid, gid, error); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TmpFSInode::TmpFSInode(TmpFS& fs, InodeMetadata metadata, InodeIdentifier parent) | TmpFSInode::TmpFSInode(TmpFS& fs, InodeMetadata metadata, InodeIdentifier parent) | ||||||
|  |  | ||||||
|  | @ -22,8 +22,8 @@ public: | ||||||
|     virtual InodeIdentifier root_inode() const override; |     virtual InodeIdentifier root_inode() const override; | ||||||
|     virtual RefPtr<Inode> get_inode(InodeIdentifier) const override; |     virtual RefPtr<Inode> get_inode(InodeIdentifier) const override; | ||||||
| 
 | 
 | ||||||
|     virtual RefPtr<Inode> create_inode(InodeIdentifier parent_id, const String& name, mode_t, off_t size, dev_t, int& error) override; |     virtual RefPtr<Inode> create_inode(InodeIdentifier parent_id, const String& name, mode_t, off_t size, dev_t, uid_t, gid_t, int& error) override; | ||||||
|     virtual RefPtr<Inode> create_directory(InodeIdentifier parent_id, const String& name, mode_t, int& error) override; |     virtual RefPtr<Inode> create_directory(InodeIdentifier parent_id, const String& name, mode_t, uid_t, gid_t, int& error) override; | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     TmpFS(); |     TmpFS(); | ||||||
|  |  | ||||||
|  | @ -183,7 +183,7 @@ KResultOr<InodeMetadata> VFS::lookup_metadata(StringView path, Custody& base, in | ||||||
|     return custody_or_error.value()->inode().metadata(); |     return custody_or_error.value()->inode().metadata(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| KResultOr<NonnullRefPtr<FileDescription>> VFS::open(StringView path, int options, mode_t mode, Custody& base) | KResultOr<NonnullRefPtr<FileDescription>> VFS::open(StringView path, int options, mode_t mode, Custody& base, Optional<UidAndGid> owner) | ||||||
| { | { | ||||||
|     if ((options & O_CREAT) && (options & O_DIRECTORY)) |     if ((options & O_CREAT) && (options & O_DIRECTORY)) | ||||||
|         return KResult(-EINVAL); |         return KResult(-EINVAL); | ||||||
|  | @ -196,7 +196,7 @@ KResultOr<NonnullRefPtr<FileDescription>> VFS::open(StringView path, int options | ||||||
|         if (custody_or_error.is_error()) { |         if (custody_or_error.is_error()) { | ||||||
|             if (custody_or_error.error() != -ENOENT) |             if (custody_or_error.error() != -ENOENT) | ||||||
|                 return custody_or_error.error(); |                 return custody_or_error.error(); | ||||||
|             return create(path, options, mode, *parent_custody); |             return create(path, options, mode, *parent_custody, move(owner)); | ||||||
|         } |         } | ||||||
|         if (options & O_EXCL) |         if (options & O_EXCL) | ||||||
|             return KResult(-EEXIST); |             return KResult(-EEXIST); | ||||||
|  | @ -263,14 +263,14 @@ KResult VFS::mknod(StringView path, mode_t mode, dev_t dev, Custody& base) | ||||||
|     FileSystemPath p(path); |     FileSystemPath p(path); | ||||||
|     dbg() << "VFS::mknod: '" << p.basename() << "' mode=" << mode << " dev=" << dev << " in " << parent_inode.identifier(); |     dbg() << "VFS::mknod: '" << p.basename() << "' mode=" << mode << " dev=" << dev << " in " << parent_inode.identifier(); | ||||||
|     int error; |     int error; | ||||||
|     auto new_file = parent_inode.fs().create_inode(parent_inode.identifier(), p.basename(), mode, 0, dev, error); |     auto new_file = parent_inode.fs().create_inode(parent_inode.identifier(), p.basename(), mode, 0, dev, current->process().uid(), current->process().gid(), error); | ||||||
|     if (!new_file) |     if (!new_file) | ||||||
|         return KResult(error); |         return KResult(error); | ||||||
| 
 | 
 | ||||||
|     return KSuccess; |     return KSuccess; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| KResultOr<NonnullRefPtr<FileDescription>> VFS::create(StringView path, int options, mode_t mode, Custody& parent_custody) | KResultOr<NonnullRefPtr<FileDescription>> VFS::create(StringView path, int options, mode_t mode, Custody& parent_custody, Optional<UidAndGid> owner) | ||||||
| { | { | ||||||
|     (void)options; |     (void)options; | ||||||
| 
 | 
 | ||||||
|  | @ -285,7 +285,10 @@ KResultOr<NonnullRefPtr<FileDescription>> VFS::create(StringView path, int optio | ||||||
|     FileSystemPath p(path); |     FileSystemPath p(path); | ||||||
|     dbg() << "VFS::create: '" << p.basename() << "' in " << parent_inode.identifier(); |     dbg() << "VFS::create: '" << p.basename() << "' in " << parent_inode.identifier(); | ||||||
|     int error; |     int error; | ||||||
|     auto new_file = parent_inode.fs().create_inode(parent_inode.identifier(), p.basename(), mode, 0, 0, error); | 
 | ||||||
|  |     uid_t uid = owner.has_value() ? owner.value().uid : current->process().uid(); | ||||||
|  |     gid_t gid = owner.has_value() ? owner.value().gid : current->process().gid(); | ||||||
|  |     auto new_file = parent_inode.fs().create_inode(parent_inode.identifier(), p.basename(), mode, 0, 0, uid, gid, error); | ||||||
|     if (!new_file) |     if (!new_file) | ||||||
|         return KResult(error); |         return KResult(error); | ||||||
| 
 | 
 | ||||||
|  | @ -311,7 +314,7 @@ KResult VFS::mkdir(StringView path, mode_t mode, Custody& base) | ||||||
|     FileSystemPath p(path); |     FileSystemPath p(path); | ||||||
|     dbg() << "VFS::mkdir: '" << p.basename() << "' in " << parent_inode.identifier(); |     dbg() << "VFS::mkdir: '" << p.basename() << "' in " << parent_inode.identifier(); | ||||||
|     int error; |     int error; | ||||||
|     auto new_dir = parent_inode.fs().create_directory(parent_inode.identifier(), p.basename(), mode, error); |     auto new_dir = parent_inode.fs().create_directory(parent_inode.identifier(), p.basename(), mode, current->process().uid(), current->process().gid(), error); | ||||||
|     if (new_dir) |     if (new_dir) | ||||||
|         return KSuccess; |         return KSuccess; | ||||||
|     return KResult(error); |     return KResult(error); | ||||||
|  | @ -556,7 +559,7 @@ KResult VFS::symlink(StringView target, StringView linkpath, Custody& base) | ||||||
|     FileSystemPath p(linkpath); |     FileSystemPath p(linkpath); | ||||||
|     dbg() << "VFS::symlink: '" << p.basename() << "' (-> '" << target << "') in " << parent_inode.identifier(); |     dbg() << "VFS::symlink: '" << p.basename() << "' (-> '" << target << "') in " << parent_inode.identifier(); | ||||||
|     int error; |     int error; | ||||||
|     auto new_file = parent_inode.fs().create_inode(parent_inode.identifier(), p.basename(), 0120644, 0, 0, error); |     auto new_file = parent_inode.fs().create_inode(parent_inode.identifier(), p.basename(), 0120644, 0, 0, current->process().uid(), current->process().gid(), error); | ||||||
|     if (!new_file) |     if (!new_file) | ||||||
|         return KResult(error); |         return KResult(error); | ||||||
|     ssize_t nwritten = new_file->write_bytes(0, target.length(), (const u8*)target.characters_without_null_termination(), nullptr); |     ssize_t nwritten = new_file->write_bytes(0, target.length(), (const u8*)target.characters_without_null_termination(), nullptr); | ||||||
|  |  | ||||||
|  | @ -31,6 +31,11 @@ class Custody; | ||||||
| class Device; | class Device; | ||||||
| class FileDescription; | class FileDescription; | ||||||
| 
 | 
 | ||||||
|  | struct UidAndGid { | ||||||
|  |     uid_t uid; | ||||||
|  |     gid_t gid; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| class VFS { | class VFS { | ||||||
|     AK_MAKE_ETERNAL |     AK_MAKE_ETERNAL | ||||||
| public: | public: | ||||||
|  | @ -62,8 +67,8 @@ public: | ||||||
|     KResult mount(NonnullRefPtr<FS>&&, Custody& mount_point); |     KResult mount(NonnullRefPtr<FS>&&, Custody& mount_point); | ||||||
|     KResult unmount(InodeIdentifier guest_inode_id); |     KResult unmount(InodeIdentifier guest_inode_id); | ||||||
| 
 | 
 | ||||||
|     KResultOr<NonnullRefPtr<FileDescription>> open(StringView path, int options, mode_t mode, Custody& base); |     KResultOr<NonnullRefPtr<FileDescription>> open(StringView path, int options, mode_t mode, Custody& base, Optional<UidAndGid> = {}); | ||||||
|     KResultOr<NonnullRefPtr<FileDescription>> create(StringView path, int options, mode_t mode, Custody& parent_custody); |     KResultOr<NonnullRefPtr<FileDescription>> create(StringView path, int options, mode_t mode, Custody& parent_custody, Optional<UidAndGid> = {}); | ||||||
|     KResult mkdir(StringView path, mode_t mode, Custody& base); |     KResult mkdir(StringView path, mode_t mode, Custody& base); | ||||||
|     KResult link(StringView old_path, StringView new_path, Custody& base); |     KResult link(StringView old_path, StringView new_path, Custody& base); | ||||||
|     KResult unlink(StringView path, Custody& base); |     KResult unlink(StringView path, Custody& base); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling