diff options
author | circl <circl.lastname@gmail.com> | 2021-12-31 19:20:17 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-01-01 15:08:49 +0100 |
commit | 63760603f3adec2fb696018f6c1c77feeb0dbdd0 (patch) | |
tree | 3d96a31951e538ab9cdc3c99b025ff5c9a41bb42 | |
parent | 344cfa0db4a76601754aead153fa52d2cde6db1e (diff) | |
download | serenity-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.
-rw-r--r-- | Kernel/API/Syscall.h | 2 | ||||
-rw-r--r-- | Kernel/FileSystem/VirtualFileSystem.cpp | 4 | ||||
-rw-r--r-- | Kernel/FileSystem/VirtualFileSystem.h | 2 | ||||
-rw-r--r-- | Kernel/Syscalls/chown.cpp | 15 | ||||
-rw-r--r-- | Userland/Libraries/LibC/unistd.cpp | 24 | ||||
-rw-r--r-- | Userland/Libraries/LibC/unistd.h | 2 | ||||
-rw-r--r-- | Userland/Libraries/LibCore/System.cpp | 21 | ||||
-rw-r--r-- | Userland/Libraries/LibCore/System.h | 1 |
8 files changed, 64 insertions, 7 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; } diff --git a/Userland/Libraries/LibC/unistd.cpp b/Userland/Libraries/LibC/unistd.cpp index 2c0ba9a8f1..d2a7c134bb 100644 --- a/Userland/Libraries/LibC/unistd.cpp +++ b/Userland/Libraries/LibC/unistd.cpp @@ -38,13 +38,24 @@ static __thread int s_cached_tid = 0; static int s_cached_pid = 0; +int lchown(const char* pathname, uid_t uid, gid_t gid) +{ + if (!pathname) { + errno = EFAULT; + return -1; + } + Syscall::SC_chown_params params { { pathname, strlen(pathname) }, uid, gid, AT_FDCWD, false }; + int rc = syscall(SC_chown, ¶ms); + __RETURN_WITH_ERRNO(rc, rc, -1); +} + int chown(const char* pathname, uid_t uid, gid_t gid) { if (!pathname) { errno = EFAULT; return -1; } - Syscall::SC_chown_params params { { pathname, strlen(pathname) }, uid, gid }; + Syscall::SC_chown_params params { { pathname, strlen(pathname) }, uid, gid, AT_FDCWD, true }; int rc = syscall(SC_chown, ¶ms); __RETURN_WITH_ERRNO(rc, rc, -1); } @@ -55,6 +66,17 @@ int fchown(int fd, uid_t uid, gid_t gid) __RETURN_WITH_ERRNO(rc, rc, -1); } +int fchownat(int fd, const char* pathname, uid_t uid, gid_t gid, int flags) +{ + if (!pathname) { + errno = EFAULT; + return -1; + } + Syscall::SC_chown_params params { { pathname, strlen(pathname) }, uid, gid, fd, !(flags & AT_SYMLINK_NOFOLLOW) }; + int rc = syscall(SC_chown, ¶ms); + __RETURN_WITH_ERRNO(rc, rc, -1); +} + pid_t fork() { __pthread_fork_prepare(); diff --git a/Userland/Libraries/LibC/unistd.h b/Userland/Libraries/LibC/unistd.h index 5ed0229809..b12cc237af 100644 --- a/Userland/Libraries/LibC/unistd.h +++ b/Userland/Libraries/LibC/unistd.h @@ -104,8 +104,10 @@ int mknod(const char* pathname, mode_t, dev_t); long fpathconf(int fd, int name); long pathconf(const char* path, int name); char* getlogin(); +int lchown(const char* pathname, uid_t uid, gid_t gid); int chown(const char* pathname, uid_t, gid_t); int fchown(int fd, uid_t, gid_t); +int fchownat(int fd, const char* pathname, uid_t uid, gid_t gid, int flags); int ftruncate(int fd, off_t length); int truncate(const char* path, off_t length); int mount(int source_fd, const char* target, const char* fs_type, int flags); diff --git a/Userland/Libraries/LibCore/System.cpp b/Userland/Libraries/LibCore/System.cpp index f51145fac2..462aa65236 100644 --- a/Userland/Libraries/LibCore/System.cpp +++ b/Userland/Libraries/LibCore/System.cpp @@ -368,13 +368,13 @@ ErrorOr<void> fchmod(int fd, mode_t mode) return {}; } -ErrorOr<void> chown(StringView pathname, uid_t uid, gid_t gid) +ErrorOr<void> lchown(StringView pathname, uid_t uid, gid_t gid) { if (!pathname.characters_without_null_termination()) return Error::from_syscall("chown"sv, -EFAULT); #ifdef __serenity__ - Syscall::SC_chown_params params = { { pathname.characters_without_null_termination(), pathname.length() }, uid, gid }; + Syscall::SC_chown_params params = { { pathname.characters_without_null_termination(), pathname.length() }, uid, gid, AT_FDCWD, false }; int rc = syscall(SC_chown, ¶ms); HANDLE_SYSCALL_RETURN_VALUE("chown"sv, rc, {}); #else @@ -385,6 +385,23 @@ ErrorOr<void> chown(StringView pathname, uid_t uid, gid_t gid) #endif } +ErrorOr<void> chown(StringView pathname, uid_t uid, gid_t gid) +{ + if (!pathname.characters_without_null_termination()) + return Error::from_syscall("chown"sv, -EFAULT); + +#ifdef __serenity__ + Syscall::SC_chown_params params = { { pathname.characters_without_null_termination(), pathname.length() }, uid, gid, AT_FDCWD, true }; + int rc = syscall(SC_chown, ¶ms); + HANDLE_SYSCALL_RETURN_VALUE("chown"sv, rc, {}); +#else + String path = pathname; + if (::lchown(path.characters(), uid, gid) < 0) + return Error::from_syscall("lchown"sv, -errno); + return {}; +#endif +} + ErrorOr<Optional<struct passwd>> getpwnam(StringView name) { ::setpwent(); diff --git a/Userland/Libraries/LibCore/System.h b/Userland/Libraries/LibCore/System.h index 8ea4b27693..d30457b495 100644 --- a/Userland/Libraries/LibCore/System.h +++ b/Userland/Libraries/LibCore/System.h @@ -66,6 +66,7 @@ ErrorOr<void> ioctl(int fd, unsigned request, ...); ErrorOr<struct termios> tcgetattr(int fd); ErrorOr<void> tcsetattr(int fd, int optional_actions, struct termios const&); ErrorOr<void> chmod(StringView pathname, mode_t mode); +ErrorOr<void> lchown(StringView pathname, uid_t uid, gid_t gid); ErrorOr<void> chown(StringView pathname, uid_t uid, gid_t gid); ErrorOr<Optional<struct passwd>> getpwnam(StringView name); ErrorOr<Optional<struct group>> getgrnam(StringView name); |