mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 13:12:46 +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 }; | ||||
| } | ||||
| 
 | ||||
| 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; | ||||
|     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; | ||||
|     return nullptr; | ||||
|  |  | |||
|  | @ -16,8 +16,8 @@ public: | |||
|     virtual const char* class_name() const override { return "DevPtsFS"; } | ||||
| 
 | ||||
|     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_directory(InodeIdentifier parentInode, const String& name, mode_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, uid_t, gid_t, int& error) override; | ||||
|     virtual RefPtr<Inode> get_inode(InodeIdentifier) const override; | ||||
| 
 | ||||
|     static void register_slave_pty(SlavePTY&); | ||||
|  |  | |||
|  | @ -1284,7 +1284,7 @@ bool Ext2FS::set_block_allocation_state(BlockIndex block_index, bool new_state) | |||
|     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); | ||||
|     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.
 | ||||
|     //       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) | ||||
|         return nullptr; | ||||
| 
 | ||||
|  | @ -1328,7 +1328,7 @@ RefPtr<Inode> Ext2FS::create_directory(InodeIdentifier parent_id, const String& | |||
|     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); | ||||
|     ASSERT(parent_id.fsid() == fsid()); | ||||
|  | @ -1378,8 +1378,8 @@ RefPtr<Inode> Ext2FS::create_inode(InodeIdentifier parent_id, const String& name | |||
|     ext2_inode e2inode; | ||||
|     memset(&e2inode, 0, sizeof(ext2_inode)); | ||||
|     e2inode.i_mode = mode; | ||||
|     e2inode.i_uid = current->process().euid(); | ||||
|     e2inode.i_gid = current->process().egid(); | ||||
|     e2inode.i_uid = uid; | ||||
|     e2inode.i_gid = gid; | ||||
|     e2inode.i_size = size; | ||||
|     e2inode.i_atime = now.tv_sec; | ||||
|     e2inode.i_ctime = now.tv_sec; | ||||
|  |  | |||
|  | @ -99,8 +99,8 @@ private: | |||
| 
 | ||||
|     virtual const char* class_name() 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_directory(InodeIdentifier parentInode, const String& name, mode_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, uid_t, gid_t, int& error) override; | ||||
|     virtual RefPtr<Inode> get_inode(InodeIdentifier) const override; | ||||
|     virtual void flush_writes() override; | ||||
| 
 | ||||
|  |  | |||
|  | @ -58,8 +58,8 @@ public: | |||
|         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_directory(InodeIdentifier parentInode, const String& name, mode_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, uid_t, gid_t, int& error) = 0; | ||||
| 
 | ||||
|     virtual RefPtr<Inode> get_inode(InodeIdentifier) const = 0; | ||||
| 
 | ||||
|  |  | |||
|  | @ -947,13 +947,13 @@ const char* ProcFS::class_name() const | |||
|     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"); | ||||
|     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; | ||||
|     return nullptr; | ||||
|  |  | |||
|  | @ -23,8 +23,8 @@ public: | |||
|     virtual InodeIdentifier root_inode() 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_directory(InodeIdentifier parent_id, const String& name, mode_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, uid_t, gid_t, int& error) override; | ||||
| 
 | ||||
|     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); | ||||
|  |  | |||
|  | @ -62,7 +62,7 @@ RefPtr<Inode> TmpFS::get_inode(InodeIdentifier identifier) const | |||
|     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); | ||||
|     ASSERT(parent_id.fsid() == fsid()); | ||||
|  | @ -75,8 +75,8 @@ RefPtr<Inode> TmpFS::create_inode(InodeIdentifier parent_id, const String& name, | |||
| 
 | ||||
|     InodeMetadata metadata; | ||||
|     metadata.mode = mode; | ||||
|     metadata.uid = current->process().euid(); | ||||
|     metadata.gid = current->process().egid(); | ||||
|     metadata.uid = uid; | ||||
|     metadata.gid = gid; | ||||
|     metadata.atime = now.tv_sec; | ||||
|     metadata.ctime = 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; | ||||
| } | ||||
| 
 | ||||
| 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.
 | ||||
|     mode &= ~0170000; | ||||
|     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) | ||||
|  |  | |||
|  | @ -22,8 +22,8 @@ public: | |||
|     virtual InodeIdentifier root_inode() 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_directory(InodeIdentifier parent_id, const String& name, mode_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, uid_t, gid_t, int& error) override; | ||||
| 
 | ||||
| private: | ||||
|     TmpFS(); | ||||
|  |  | |||
|  | @ -183,7 +183,7 @@ KResultOr<InodeMetadata> VFS::lookup_metadata(StringView path, Custody& base, in | |||
|     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)) | ||||
|         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.error() != -ENOENT) | ||||
|                 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) | ||||
|             return KResult(-EEXIST); | ||||
|  | @ -263,14 +263,14 @@ KResult VFS::mknod(StringView path, mode_t mode, dev_t dev, Custody& base) | |||
|     FileSystemPath p(path); | ||||
|     dbg() << "VFS::mknod: '" << p.basename() << "' mode=" << mode << " dev=" << dev << " in " << parent_inode.identifier(); | ||||
|     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) | ||||
|         return KResult(error); | ||||
| 
 | ||||
|     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; | ||||
| 
 | ||||
|  | @ -285,7 +285,10 @@ KResultOr<NonnullRefPtr<FileDescription>> VFS::create(StringView path, int optio | |||
|     FileSystemPath p(path); | ||||
|     dbg() << "VFS::create: '" << p.basename() << "' in " << parent_inode.identifier(); | ||||
|     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) | ||||
|         return KResult(error); | ||||
| 
 | ||||
|  | @ -311,7 +314,7 @@ KResult VFS::mkdir(StringView path, mode_t mode, Custody& base) | |||
|     FileSystemPath p(path); | ||||
|     dbg() << "VFS::mkdir: '" << p.basename() << "' in " << parent_inode.identifier(); | ||||
|     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) | ||||
|         return KSuccess; | ||||
|     return KResult(error); | ||||
|  | @ -556,7 +559,7 @@ KResult VFS::symlink(StringView target, StringView linkpath, Custody& base) | |||
|     FileSystemPath p(linkpath); | ||||
|     dbg() << "VFS::symlink: '" << p.basename() << "' (-> '" << target << "') in " << parent_inode.identifier(); | ||||
|     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) | ||||
|         return KResult(error); | ||||
|     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 FileDescription; | ||||
| 
 | ||||
| struct UidAndGid { | ||||
|     uid_t uid; | ||||
|     gid_t gid; | ||||
| }; | ||||
| 
 | ||||
| class VFS { | ||||
|     AK_MAKE_ETERNAL | ||||
| public: | ||||
|  | @ -62,8 +67,8 @@ public: | |||
|     KResult mount(NonnullRefPtr<FS>&&, Custody& mount_point); | ||||
|     KResult unmount(InodeIdentifier guest_inode_id); | ||||
| 
 | ||||
|     KResultOr<NonnullRefPtr<FileDescription>> open(StringView path, int options, mode_t mode, Custody& base); | ||||
|     KResultOr<NonnullRefPtr<FileDescription>> create(StringView path, int options, mode_t mode, Custody& parent_custody); | ||||
|     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, Optional<UidAndGid> = {}); | ||||
|     KResult mkdir(StringView path, mode_t mode, Custody& base); | ||||
|     KResult link(StringView old_path, StringView new_path, Custody& base); | ||||
|     KResult unlink(StringView path, Custody& base); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling