From 875ce1adf733a0aeb9d50d69c81834c8b82f130b Mon Sep 17 00:00:00 2001 From: Jonas 'Sortie' Termansen Date: Mon, 28 Sep 2015 01:57:22 +0200 Subject: [PATCH] Fix faccessat(2) not reporting correct permissions. --- kernel/io.cpp | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/kernel/io.cpp b/kernel/io.cpp index d07c3ca6..07bc1882 100644 --- a/kernel/io.cpp +++ b/kernel/io.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -192,11 +193,12 @@ int sys_openat(int dirfd, const char* path, int flags, mode_t mode) return ret; } -// TODO: This is a hack! Stat the file in some manner and check permissions. -int sys_faccessat(int dirfd, const char* path, int /*mode*/, int flags) +int sys_faccessat(int dirfd, const char* path, int mode, int flags) { if ( flags & ~(AT_SYMLINK_NOFOLLOW | AT_EACCESS) ) return errno = EINVAL, -1; + if ( mode & ~(X_OK | W_OK | R_OK) ) + return errno = EINVAL, -1; char* pathcopy = GetStringFromUser(path); if ( !pathcopy ) return -1; @@ -206,7 +208,26 @@ int sys_faccessat(int dirfd, const char* path, int /*mode*/, int flags) int open_flags = O_READ | (flags & AT_SYMLINK_NOFOLLOW ? O_SYMLINK_NOFOLLOW : 0); Ref desc = from->open(&ctx, pathcopy, open_flags); delete[] pathcopy; - return desc ? 0 : -1; + if ( !desc ) + return -1; + ioctx_t kctx; SetupKernelIOCtx(&kctx); + struct stat st; + if ( desc->stat(&kctx, &st) < 0 ) + return -1; + mode_t mask; + if ( kctx.uid == st.st_uid ) + mask = 0700; + else if ( kctx.gid == st.st_gid ) + mask = 0070; + else + mask = 0007; + if ( (mode & X_OK) && !(st.st_mode & 0111 & mask) ) + return errno = EACCES, -1; + if ( (mode & W_OK) && !(st.st_mode & 0222 & mask) ) + return errno = EACCES, -1; + if ( (mode & R_OK) && !(st.st_mode & 0444 & mask) ) + return errno = EACCES, -1; + return 0; } int sys_unlinkat(int dirfd, const char* path, int flags)