summaryrefslogtreecommitdiff
path: root/Kernel
diff options
context:
space:
mode:
authorcircl <circl.lastname@gmail.com>2021-12-31 19:20:17 +0100
committerAndreas Kling <kling@serenityos.org>2022-01-01 15:08:49 +0100
commit63760603f3adec2fb696018f6c1c77feeb0dbdd0 (patch)
tree3d96a31951e538ab9cdc3c99b025ff5c9a41bb42 /Kernel
parent344cfa0db4a76601754aead153fa52d2cde6db1e (diff)
downloadserenity-63760603f3adec2fb696018f6c1c77feeb0dbdd0.zip
Kernel+LibC+LibCore: Add lchown and fchownat functions
This modifies sys$chown to allow specifying whether or not to follow symlinks and in which directory. This was then used to implement lchown and fchownat in LibC and LibCore.
Diffstat (limited to 'Kernel')
-rw-r--r--Kernel/API/Syscall.h2
-rw-r--r--Kernel/FileSystem/VirtualFileSystem.cpp4
-rw-r--r--Kernel/FileSystem/VirtualFileSystem.h2
-rw-r--r--Kernel/Syscalls/chown.cpp15
4 files changed, 19 insertions, 4 deletions
diff --git a/Kernel/API/Syscall.h b/Kernel/API/Syscall.h
index 6372efb165..d02184fdfd 100644
--- a/Kernel/API/Syscall.h
+++ b/Kernel/API/Syscall.h
@@ -400,6 +400,8 @@ struct SC_chown_params {
StringArgument path;
u32 uid;
u32 gid;
+ int dirfd;
+ int follow_symlinks;
};
struct SC_mknod_params {
diff --git a/Kernel/FileSystem/VirtualFileSystem.cpp b/Kernel/FileSystem/VirtualFileSystem.cpp
index 3855182999..2bcf342329 100644
--- a/Kernel/FileSystem/VirtualFileSystem.cpp
+++ b/Kernel/FileSystem/VirtualFileSystem.cpp
@@ -564,9 +564,9 @@ ErrorOr<void> VirtualFileSystem::chown(Custody& custody, UserID a_uid, GroupID a
return inode.chown(new_uid, new_gid);
}
-ErrorOr<void> VirtualFileSystem::chown(StringView path, UserID a_uid, GroupID a_gid, Custody& base)
+ErrorOr<void> VirtualFileSystem::chown(StringView path, UserID a_uid, GroupID a_gid, Custody& base, int options)
{
- auto custody = TRY(resolve_path(path, base));
+ auto custody = TRY(resolve_path(path, base, nullptr, options));
return chown(custody, a_uid, a_gid);
}
diff --git a/Kernel/FileSystem/VirtualFileSystem.h b/Kernel/FileSystem/VirtualFileSystem.h
index bee3f1504f..a1386dbb14 100644
--- a/Kernel/FileSystem/VirtualFileSystem.h
+++ b/Kernel/FileSystem/VirtualFileSystem.h
@@ -59,7 +59,7 @@ public:
ErrorOr<void> rmdir(StringView path, Custody& base);
ErrorOr<void> chmod(StringView path, mode_t, Custody& base);
ErrorOr<void> chmod(Custody&, mode_t);
- ErrorOr<void> chown(StringView path, UserID, GroupID, Custody& base);
+ ErrorOr<void> chown(StringView path, UserID, GroupID, Custody& base, int options);
ErrorOr<void> chown(Custody&, UserID, GroupID);
ErrorOr<void> access(StringView path, int mode, Custody& base);
ErrorOr<InodeMetadata> lookup_metadata(StringView path, Custody& base, int options = 0);
diff --git a/Kernel/Syscalls/chown.cpp b/Kernel/Syscalls/chown.cpp
index 92172fed61..0db2c9cccc 100644
--- a/Kernel/Syscalls/chown.cpp
+++ b/Kernel/Syscalls/chown.cpp
@@ -4,6 +4,8 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
+#include <AK/NonnullRefPtrVector.h>
+#include <Kernel/FileSystem/Custody.h>
#include <Kernel/FileSystem/OpenFileDescription.h>
#include <Kernel/Process.h>
@@ -24,7 +26,18 @@ ErrorOr<FlatPtr> Process::sys$chown(Userspace<const Syscall::SC_chown_params*> u
TRY(require_promise(Pledge::chown));
auto params = TRY(copy_typed_from_user(user_params));
auto path = TRY(get_syscall_path_argument(params.path));
- TRY(VirtualFileSystem::the().chown(path->view(), params.uid, params.gid, current_directory()));
+
+ RefPtr<Custody> base;
+ if (params.dirfd == AT_FDCWD) {
+ base = current_directory();
+ } else {
+ auto base_description = TRY(fds().open_file_description(params.dirfd));
+ if (!base_description->custody())
+ return EINVAL;
+ base = base_description->custody();
+ }
+
+ TRY(VirtualFileSystem::the().chown(path->view(), params.uid, params.gid, *base, params.follow_symlinks ? 0 : O_NOFOLLOW_NOERROR));
return 0;
}