mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-02-07 06:53:33 +00:00
Fix some more issues
- ARM Neon headers are now exported in libc/isystem/ - stat() and access() now do a better job reporting which files are executable which ones aren't. They do this by reading the first two bytes in a file to see if it's `MZ` or `#!`.
This commit is contained in:
parent
22cf6e11eb
commit
4f5d5a6813
17 changed files with 144 additions and 49 deletions
|
@ -16,10 +16,8 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/syscall-nt.internal.h"
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
textwindows int sys_faccessat_nt(int dirfd, const char *path, int mode,
|
||||
uint32_t flags) {
|
||||
|
|
|
@ -101,7 +101,11 @@ textwindows int sys_fstat_nt(int64_t handle, struct stat *out_st) {
|
|||
if (!GetFileInformationByHandle(handle, &wst)) {
|
||||
return __winerr();
|
||||
}
|
||||
st.st_mode = 0555 & ~umask;
|
||||
st.st_mode = 0444 & ~umask;
|
||||
if ((wst.dwFileAttributes & kNtFileAttributeDirectory) ||
|
||||
IsWindowsExecutable(handle)) {
|
||||
st.st_mode |= 0111 & ~umask;
|
||||
}
|
||||
st.st_flags = wst.dwFileAttributes;
|
||||
if (!(wst.dwFileAttributes & kNtFileAttributeReadonly)) {
|
||||
st.st_mode |= 0222 & ~umask;
|
||||
|
|
|
@ -34,7 +34,7 @@ textwindows int sys_fstatat_nt(int dirfd, const char *path, struct stat *st,
|
|||
uint16_t path16[PATH_MAX];
|
||||
if (__mkntpathat(dirfd, path, 0, path16) == -1) return -1;
|
||||
if ((fh = CreateFile(
|
||||
path16, kNtFileReadAttributes,
|
||||
path16, kNtFileGenericRead,
|
||||
kNtFileShareRead | kNtFileShareWrite | kNtFileShareDelete, 0,
|
||||
kNtOpenExisting,
|
||||
kNtFileAttributeNormal | kNtFileFlagBackupSemantics |
|
||||
|
|
|
@ -18,13 +18,10 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nt/accounting.h"
|
||||
|
||||
// asan must be disabled because __proc_worker calls this on win32 stack
|
||||
|
||||
static uint32_t __kmp32(const void *buf, size_t size) {
|
||||
static textwindows uint32_t __kmp32(const void *buf, size_t size) {
|
||||
size_t i;
|
||||
uint32_t h;
|
||||
const uint32_t kPhiPrime = 0x9e3779b1;
|
||||
|
@ -39,7 +36,7 @@ textwindows uint32_t sys_getuid_nt(void) {
|
|||
uint32_t tmp, size = ARRAYLEN(buf);
|
||||
if (!(tmp = atomic_load_explicit(&uid, memory_order_acquire))) {
|
||||
GetUserName(&buf, &size);
|
||||
tmp = __kmp32(buf, size >> 1) & INT_MAX;
|
||||
tmp = __kmp32(buf, size >> 1) & 32767;
|
||||
if (!tmp) ++tmp;
|
||||
atomic_store_explicit(&uid, tmp, memory_order_release);
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ int __ensurefds_unlocked(int);
|
|||
void __printfds(void);
|
||||
uint32_t sys_getuid_nt(void);
|
||||
int __pause_thread(uint32_t);
|
||||
int IsWindowsExecutable(int64_t);
|
||||
int CountConsoleInputBytes(int64_t);
|
||||
int FlushConsoleInputBytes(int64_t);
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
|
@ -24,7 +25,11 @@
|
|||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/nt/createfile.h"
|
||||
#include "libc/nt/enum/accessmask.h"
|
||||
#include "libc/nt/enum/creationdisposition.h"
|
||||
#include "libc/nt/enum/fileflagandattributes.h"
|
||||
#include "libc/nt/enum/filesharemode.h"
|
||||
#include "libc/nt/enum/securityimpersonationlevel.h"
|
||||
#include "libc/nt/enum/securityinformation.h"
|
||||
#include "libc/nt/errors.h"
|
||||
|
@ -50,18 +55,19 @@
|
|||
* @see libc/sysv/consts.sh
|
||||
*/
|
||||
textwindows int ntaccesscheck(const char16_t *pathname, uint32_t flags) {
|
||||
int rc, e;
|
||||
void *freeme;
|
||||
int rc;
|
||||
bool32 result;
|
||||
uint32_t flagmask;
|
||||
struct NtSecurityDescriptor *s;
|
||||
struct NtGenericMapping mapping;
|
||||
struct NtPrivilegeSet privileges;
|
||||
int64_t hToken, hImpersonatedToken;
|
||||
uint32_t secsize, granted, privsize;
|
||||
int64_t hToken, hImpersonatedToken, hFile;
|
||||
intptr_t buffer[1024 / sizeof(intptr_t)];
|
||||
freeme = 0;
|
||||
if (flags & X_OK) flags |= R_OK;
|
||||
granted = 0;
|
||||
result = false;
|
||||
flagmask = flags;
|
||||
s = (void *)buffer;
|
||||
secsize = sizeof(buffer);
|
||||
privsize = sizeof(privileges);
|
||||
|
@ -70,9 +76,8 @@ textwindows int ntaccesscheck(const char16_t *pathname, uint32_t flags) {
|
|||
mapping.GenericWrite = kNtFileGenericWrite;
|
||||
mapping.GenericExecute = kNtFileGenericExecute;
|
||||
mapping.GenericAll = kNtFileAllAccess;
|
||||
MapGenericMask(&flags, &mapping);
|
||||
MapGenericMask(&flagmask, &mapping);
|
||||
hImpersonatedToken = hToken = -1;
|
||||
TryAgain:
|
||||
if (GetFileSecurity(pathname,
|
||||
kNtOwnerSecurityInformation |
|
||||
kNtGroupSecurityInformation |
|
||||
|
@ -84,13 +89,29 @@ TryAgain:
|
|||
&hToken)) {
|
||||
if (DuplicateToken(hToken, kNtSecurityImpersonation,
|
||||
&hImpersonatedToken)) {
|
||||
if (flags == kNtGenericExecute) { // X_OK
|
||||
flags |= kNtGenericRead; // R_OK
|
||||
}
|
||||
if (AccessCheck(s, hImpersonatedToken, flags, &mapping, &privileges,
|
||||
if (AccessCheck(s, hImpersonatedToken, flagmask, &mapping, &privileges,
|
||||
&privsize, &granted, &result)) {
|
||||
if (result || flags == F_OK) {
|
||||
if (flags & X_OK) {
|
||||
if ((hFile = CreateFile(
|
||||
pathname, kNtFileGenericRead,
|
||||
kNtFileShareRead | kNtFileShareWrite |
|
||||
kNtFileShareDelete,
|
||||
0, kNtOpenExisting,
|
||||
kNtFileAttributeNormal | kNtFileFlagBackupSemantics,
|
||||
0)) != -1) {
|
||||
if (IsWindowsExecutable(hFile)) {
|
||||
rc = 0;
|
||||
} else {
|
||||
rc = eacces();
|
||||
}
|
||||
CloseHandle(hFile);
|
||||
} else {
|
||||
rc = __winerr();
|
||||
}
|
||||
} else {
|
||||
rc = 0;
|
||||
}
|
||||
} else {
|
||||
NTTRACE("ntaccesscheck finale failed: result=%d flags=%x", result,
|
||||
flags);
|
||||
|
@ -112,25 +133,15 @@ TryAgain:
|
|||
strerror(errno));
|
||||
}
|
||||
} else {
|
||||
e = GetLastError();
|
||||
if (!IsTiny() && e == kNtErrorInsufficientBuffer) {
|
||||
if (!freeme && _weaken(malloc) && (freeme = _weaken(malloc)(secsize))) {
|
||||
s = freeme;
|
||||
goto TryAgain;
|
||||
} else {
|
||||
rc = enomem();
|
||||
rc = __winerr();
|
||||
NTTRACE("%s(%#hs) failed: %s", "GetFileSecurity", pathname,
|
||||
strerror(errno));
|
||||
}
|
||||
} else {
|
||||
errno = e;
|
||||
NTTRACE("%s(%#hs) failed: %s", "GetFileSecurity", pathname,
|
||||
strerror(errno));
|
||||
rc = -1;
|
||||
if (hImpersonatedToken != -1) {
|
||||
CloseHandle(hImpersonatedToken);
|
||||
}
|
||||
if (hToken != -1) {
|
||||
CloseHandle(hToken);
|
||||
}
|
||||
if (freeme && _weaken(free)) _weaken(free)(freeme);
|
||||
if (hImpersonatedToken != -1) CloseHandle(hImpersonatedToken);
|
||||
if (hToken != -1) CloseHandle(hToken);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -36,11 +36,9 @@
|
|||
#define FIODGNAME 0x80106678 // freebsd
|
||||
|
||||
static textwindows errno_t sys_ttyname_nt(int fd, char *buf, size_t size) {
|
||||
uint32_t mode;
|
||||
if (GetConsoleMode(g_fds.p[fd].handle, &mode)) {
|
||||
if (strlcpy(buf,
|
||||
(mode & kNtEnableVirtualTerminalInput) ? "CONIN$" : "CONOUT$",
|
||||
size) < size) {
|
||||
uint32_t cmode;
|
||||
if (GetConsoleMode(g_fds.p[fd].handle, &cmode)) {
|
||||
if (strlcpy(buf, "/dev/tty", size) < size) {
|
||||
return 0;
|
||||
} else {
|
||||
return ERANGE;
|
||||
|
|
28
libc/calls/winexec.c
Normal file
28
libc/calls/winexec.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2023 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
|
||||
textwindows int IsWindowsExecutable(int64_t handle) {
|
||||
char buf[2];
|
||||
uint32_t got;
|
||||
return ReadFile(handle, buf, 2, &got, 0) && got == 2 &&
|
||||
((buf[0] == 'M' && buf[1] == 'Z') || //
|
||||
(buf[0] == '#' && buf[1] == '!'));
|
||||
}
|
4
libc/isystem/arm_acle.h
Normal file
4
libc/isystem/arm_acle.h
Normal file
|
@ -0,0 +1,4 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_ISYSTEM_ARM_ACLE_H_
|
||||
#define COSMOPOLITAN_LIBC_ISYSTEM_ARM_ACLE_H_
|
||||
#include "third_party/aarch64/arm_acle.internal.h"
|
||||
#endif /* COSMOPOLITAN_LIBC_ISYSTEM_ARM_ACLE_H_ */
|
4
libc/isystem/arm_bf16.h
Normal file
4
libc/isystem/arm_bf16.h
Normal file
|
@ -0,0 +1,4 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_ISYSTEM_ARM_BF16_H_
|
||||
#define COSMOPOLITAN_LIBC_ISYSTEM_ARM_BF16_H_
|
||||
#include "third_party/aarch64/arm_bf16.internal.h"
|
||||
#endif /* COSMOPOLITAN_LIBC_ISYSTEM_ARM_BF16_H_ */
|
4
libc/isystem/arm_fp16.h
Normal file
4
libc/isystem/arm_fp16.h
Normal file
|
@ -0,0 +1,4 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_ISYSTEM_ARM_FP16_H_
|
||||
#define COSMOPOLITAN_LIBC_ISYSTEM_ARM_FP16_H_
|
||||
#include "third_party/aarch64/arm_fp16.internal.h"
|
||||
#endif /* COSMOPOLITAN_LIBC_ISYSTEM_ARM_FP16_H_ */
|
4
libc/isystem/arm_neon.h
Normal file
4
libc/isystem/arm_neon.h
Normal file
|
@ -0,0 +1,4 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_ISYSTEM_ARM_NEON_H_
|
||||
#define COSMOPOLITAN_LIBC_ISYSTEM_ARM_NEON_H_
|
||||
#include "third_party/aarch64/arm_neon.internal.h"
|
||||
#endif /* COSMOPOLITAN_LIBC_ISYSTEM_ARM_NEON_H_ */
|
|
@ -47,7 +47,7 @@ dos kNtErrorGenFailure EACCES
|
|||
dos kNtErrorGracefulDisconnect EPIPE
|
||||
dos kNtErrorHostDown EHOSTUNREACH
|
||||
dos kNtErrorHostUnreachable EHOSTUNREACH
|
||||
dos kNtErrorInsufficientBuffer EFAULT
|
||||
dos kNtErrorInsufficientBuffer ENOBUFS
|
||||
dos kNtErrorNoaccess EFAULT
|
||||
dos kNtErrorInvalidAddress EADDRNOTAVAIL
|
||||
dos kNtErrorNotAReparsePoint EINVAL
|
||||
|
|
|
@ -11,6 +11,5 @@
|
|||
.globl kDos2Errno.EFAULT
|
||||
.type kDos2Errno.EFAULT,@object
|
||||
kDos2Errno.EFAULT:
|
||||
.e kNtErrorInsufficientBuffer,EFAULT
|
||||
.e kNtErrorNoaccess,EFAULT
|
||||
.e WSAEFAULT,EFAULT
|
||||
|
|
14
libc/sysv/dos2errno/ENOBUFS.S
Normal file
14
libc/sysv/dos2errno/ENOBUFS.S
Normal file
|
@ -0,0 +1,14 @@
|
|||
// generated by libc/sysv/dos2errno.sh
|
||||
#include "libc/nt/errors.h"
|
||||
#ifndef __x86_64__
|
||||
.end
|
||||
#endif
|
||||
.macro .e doscode systemv
|
||||
.short \doscode
|
||||
.long \systemv
|
||||
.endm
|
||||
.section .sort.rodata.dos2errno.2,"a",@progbits
|
||||
.globl kDos2Errno.ENOBUFS
|
||||
.type kDos2Errno.ENOBUFS,@object
|
||||
kDos2Errno.ENOBUFS:
|
||||
.e kNtErrorInsufficientBuffer,ENOBUFS
|
|
@ -61,7 +61,7 @@ TEST(access, test) {
|
|||
}
|
||||
|
||||
TEST(access, testRequestWriteOnReadOnly_returnsEaccess) {
|
||||
return; /* TODO(jart): maybe we need root to help? */
|
||||
if (1) return; // TODO(jart): maybe we need root to help?
|
||||
ASSERT_SYS(ENOENT, -1, access("file", F_OK));
|
||||
ASSERT_SYS(0, 0, close(creat("file", 0444)));
|
||||
ASSERT_SYS(0, 0, access("file", F_OK));
|
||||
|
@ -76,3 +76,8 @@ TEST(access, testRequestWriteOnReadOnly_returnsEaccess) {
|
|||
TEST(access, runThisExecutable) {
|
||||
ASSERT_SYS(0, 0, access(GetProgramExecutableName(), R_OK | X_OK));
|
||||
}
|
||||
|
||||
TEST(access, textFileIsntExecutable) {
|
||||
ASSERT_SYS(0, 0, touch("foo.txt", 0644));
|
||||
ASSERT_SYS(EACCES, -1, access("foo.txt", R_OK | X_OK));
|
||||
}
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
#include "libc/sysv/consts/nr.h"
|
||||
#include "libc/testlib/ezbench.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
__static_yoink("zipos");
|
||||
|
||||
|
@ -61,6 +60,31 @@ TEST(stat, enotdir) {
|
|||
ASSERT_SYS(ENOTDIR, -1, stat("yo/there", &st));
|
||||
}
|
||||
|
||||
TEST(stat, textFileIsntExecutable) {
|
||||
struct stat st;
|
||||
ASSERT_SYS(0, 0, touch("foo.txt", 0644));
|
||||
ASSERT_SYS(0, 0, stat("foo.txt", &st));
|
||||
ASSERT_FALSE(st.st_mode & 0111);
|
||||
}
|
||||
|
||||
TEST(stat, shebangIsExecutable) {
|
||||
struct stat st;
|
||||
ASSERT_SYS(0, 3, creat("foo.sh", 0777));
|
||||
ASSERT_SYS(0, 2, write(3, "#!", 2));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
ASSERT_SYS(0, 0, stat("foo.sh", &st));
|
||||
ASSERT_TRUE(!!(st.st_mode & 0111));
|
||||
}
|
||||
|
||||
TEST(stat, portableExecutableIsExecutable) {
|
||||
struct stat st;
|
||||
ASSERT_SYS(0, 3, creat("foo.exe", 0777));
|
||||
ASSERT_SYS(0, 2, write(3, "MZ", 2));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
ASSERT_SYS(0, 0, stat("foo.exe", &st));
|
||||
ASSERT_TRUE(!!(st.st_mode & 0111));
|
||||
}
|
||||
|
||||
TEST(stat, zipos) {
|
||||
struct stat st;
|
||||
EXPECT_SYS(0, 0,
|
||||
|
|
Loading…
Reference in a new issue