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.
This commit is contained in:
circl 2021-12-31 19:20:17 +01:00 committed by Andreas Kling
parent 344cfa0db4
commit 63760603f3
Notes: sideshowbarker 2024-07-17 21:50:39 +09:00
8 changed files with 64 additions and 7 deletions

View file

@ -400,6 +400,8 @@ struct SC_chown_params {
StringArgument path;
u32 uid;
u32 gid;
int dirfd;
int follow_symlinks;
};
struct SC_mknod_params {

View file

@ -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);
}

View file

@ -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);

View file

@ -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;
}

View file

@ -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, &params);
__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, &params);
__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, &params);
__RETURN_WITH_ERRNO(rc, rc, -1);
}
pid_t fork()
{
__pthread_fork_prepare();

View file

@ -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);

View file

@ -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, &params);
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, &params);
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();

View file

@ -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);