Explicitly disable Linux capabilities

This commit is contained in:
Justine Tunney 2022-07-23 12:06:41 -07:00
parent ffedbfe14d
commit 16fc83f9ce
12 changed files with 269 additions and 20 deletions

View file

@ -31,25 +31,36 @@
privileged int prctl(int operation, ...) { privileged int prctl(int operation, ...) {
int rc; int rc;
va_list va; va_list va;
intptr_t a, b; intptr_t a, b, c, d;
register intptr_t c asm("r10");
register intptr_t d asm("r8");
va_start(va, operation); va_start(va, operation);
a = va_arg(va, intptr_t); a = va_arg(va, intptr_t);
b = va_arg(va, intptr_t); b = va_arg(va, intptr_t);
c = va_arg(va, intptr_t); c = va_arg(va, intptr_t);
d = va_arg(va, intptr_t); d = va_arg(va, intptr_t);
va_end(va); va_end(va);
if (IsLinux()) { if (IsLinux()) {
asm volatile("syscall" asm volatile("mov\t%5,%%r10\n\t"
"mov\t%6,%%r8\n\t"
"syscall"
: "=a"(rc) : "=a"(rc)
: "0"(157), "D"(operation), "S"(a), "d"(b), "r"(c), "r"(d) : "0"(157), "D"(operation), "S"(a), "d"(b), "g"(c), "g"(d)
: "rcx", "r11", "memory"); : "rcx", "r8", "r10", "r11", "memory");
if (rc > -4096u) errno = -rc, rc = -1; if (rc > -4096u) errno = -rc, rc = -1;
} else { } else {
rc = enosys(); rc = enosys();
} }
STRACE("prctl(%s, %p, %p, %p, %p) → %d% m", DescribePrctlOperation(operation),
a, b, c, d, rc); #ifdef SYSDEBUG
if (operation == PR_CAPBSET_READ || operation == PR_CAPBSET_DROP) {
STRACE("prctl(%s, %s) → %d% m", DescribePrctlOperation(operation),
DescribeCapability(a), rc);
} else {
STRACE("prctl(%s, %p, %p, %p, %p) → %d% m",
DescribePrctlOperation(operation), a, b, c, d, rc);
}
#endif
return rc; return rc;
} }

View file

@ -0,0 +1,82 @@
/*-*- 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 2022 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/fmt/itoa.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/macros.internal.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/cap.h"
static const struct thatispacked {
unsigned char x;
const char *s;
} kCapabilityName[] = {
{CAP_CHOWN, "CHOWN"}, //
{CAP_DAC_OVERRIDE, "DAC_OVERRIDE"}, //
{CAP_DAC_READ_SEARCH, "DAC_READ_SEARCH"}, //
{CAP_FOWNER, "FOWNER"}, //
{CAP_FSETID, "FSETID"}, //
{CAP_KILL, "KILL"}, //
{CAP_SETGID, "SETGID"}, //
{CAP_SETUID, "SETUID"}, //
{CAP_SETPCAP, "SETPCAP"}, //
{CAP_LINUX_IMMUTABLE, "LINUX_IMMUTABLE"}, //
{CAP_NET_BIND_SERVICE, "NET_BIND_SERVICE"}, //
{CAP_NET_BROADCAST, "NET_BROADCAST"}, //
{CAP_NET_ADMIN, "NET_ADMIN"}, //
{CAP_NET_RAW, "NET_RAW"}, //
{CAP_IPC_LOCK, "IPC_LOCK"}, //
{CAP_IPC_OWNER, "IPC_OWNER"}, //
{CAP_SYS_MODULE, "SYS_MODULE"}, //
{CAP_SYS_RAWIO, "SYS_RAWIO"}, //
{CAP_SYS_CHROOT, "SYS_CHROOT"}, //
{CAP_SYS_PTRACE, "SYS_PTRACE"}, //
{CAP_SYS_PACCT, "SYS_PACCT"}, //
{CAP_SYS_ADMIN, "SYS_ADMIN"}, //
{CAP_SYS_BOOT, "SYS_BOOT"}, //
{CAP_SYS_NICE, "SYS_NICE"}, //
{CAP_SYS_RESOURCE, "SYS_RESOURCE"}, //
{CAP_SYS_TIME, "SYS_TIME"}, //
{CAP_SYS_TTY_CONFIG, "SYS_TTY_CONFIG"}, //
{CAP_MKNOD, "MKNOD"}, //
{CAP_LEASE, "LEASE"}, //
{CAP_AUDIT_WRITE, "AUDIT_WRITE"}, //
{CAP_AUDIT_CONTROL, "AUDIT_CONTROL"}, //
{CAP_SETFCAP, "SETFCAP"}, //
{CAP_MAC_OVERRIDE, "MAC_OVERRIDE"}, //
{CAP_MAC_ADMIN, "MAC_ADMIN"}, //
{CAP_SYSLOG, "SYSLOG"}, //
{CAP_WAKE_ALARM, "WAKE_ALARM"}, //
{CAP_BLOCK_SUSPEND, "BLOCK_SUSPEND"}, //
{CAP_AUDIT_READ, "AUDIT_READ"}, //
{CAP_PERFMON, "PERFMON"}, //
{CAP_BPF, "BPF"}, //
{CAP_CHECKPOINT_RESTORE, "CHECKPOINT_RESTORE"}, //
};
const char *(DescribeCapability)(char buf[20], int x) {
int i;
for (i = 0; i < ARRAYLEN(kCapabilityName); ++i) {
if (kCapabilityName[i].x == x) {
stpcpy(stpcpy(buf, "CAP_"), kCapabilityName[i].s);
return buf;
}
}
FormatInt32(buf, x);
return buf;
}

View file

@ -24,6 +24,7 @@ struct thatispacked DescribeFlags {
const char *DescribeFlags(char *, size_t, struct DescribeFlags *, size_t, const char *DescribeFlags(char *, size_t, struct DescribeFlags *, size_t,
const char *, unsigned); const char *, unsigned);
const char *DescribeCapability(char[20], int);
const char *DescribeClockName(char[32], int); const char *DescribeClockName(char[32], int);
const char *DescribeDirfd(char[12], int); const char *DescribeDirfd(char[12], int);
const char *DescribeFrame(char[32], int); const char *DescribeFrame(char[32], int);
@ -74,6 +75,7 @@ const char *DescribeTimeval(char[45], int, const struct timeval *);
void DescribeIov(const struct iovec *, int, ssize_t); void DescribeIov(const struct iovec *, int, ssize_t);
void DescribeIovNt(const struct NtIovec *, uint32_t, ssize_t); void DescribeIovNt(const struct NtIovec *, uint32_t, ssize_t);
#define DescribeCapability(x) DescribeCapability(alloca(20), x)
#define DescribeClockName(x) DescribeClockName(alloca(32), x) #define DescribeClockName(x) DescribeClockName(alloca(32), x)
#define DescribeDirfd(dirfd) DescribeDirfd(alloca(12), dirfd) #define DescribeDirfd(dirfd) DescribeDirfd(alloca(12), dirfd)
#define DescribeFrame(x) DescribeFrame(alloca(32), x) #define DescribeFrame(x) DescribeFrame(alloca(32), x)

View file

@ -27,6 +27,10 @@ const char *DescribePrctlOperation(int x) {
return "PR_SET_SECCOMP"; return "PR_SET_SECCOMP";
case PR_GET_SECCOMP: case PR_GET_SECCOMP:
return "PR_GET_SECCOMP"; return "PR_GET_SECCOMP";
case PR_CAPBSET_READ:
return "PR_CAPBSET_READ";
case PR_CAPBSET_DROP:
return "PR_CAPBSET_DROP";
default: default:
return "PRCTL_???"; return "PRCTL_???";
} }

View file

@ -1045,16 +1045,18 @@ static bool AllowSocketUnix(struct Filter *f) {
// - PR_GET_SECCOMP (21) // - PR_GET_SECCOMP (21)
// - PR_SET_SECCOMP (22) // - PR_SET_SECCOMP (22)
// - PR_SET_NO_NEW_PRIVS (38) // - PR_SET_NO_NEW_PRIVS (38)
// - PR_CAPBSET_READ (23)
// //
static bool AllowPrctl(struct Filter *f) { static bool AllowPrctl(struct Filter *f) {
static const struct sock_filter fragment[] = { static const struct sock_filter fragment[] = {
/*L0*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_linux_prctl, 0, 9 - 1), /*L0*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_linux_prctl, 0, 10 - 1),
/*L1*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[0])), /*L1*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[0])),
/*L2*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 15, 7 - 3, 0), /*L2*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 15, 5, 0),
/*L3*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 16, 7 - 4, 0), /*L3*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 16, 4, 0),
/*L4*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 21, 7 - 5, 0), /*L4*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 21, 3, 0),
/*L5*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 22, 7 - 6, 0), /*L5*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 22, 2, 0),
/*L6*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 38, 0, 8 - 7), /*L5*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 23, 1, 0),
/*L6*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 38, 0, 1),
/*L7*/ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW), /*L7*/ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
/*L8*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)), /*L8*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)),
/*L9*/ /* next filter */ /*L9*/ /* next filter */

View file

@ -48,8 +48,10 @@
#include "libc/sock/sock.h" #include "libc/sock/sock.h"
#include "libc/str/str.h" #include "libc/str/str.h"
#include "libc/sysv/consts/auxv.h" #include "libc/sysv/consts/auxv.h"
#include "libc/sysv/consts/cap.h"
#include "libc/sysv/consts/f.h" #include "libc/sysv/consts/f.h"
#include "libc/sysv/consts/poll.h" #include "libc/sysv/consts/poll.h"
#include "libc/sysv/consts/pr.h"
#include "libc/sysv/consts/rlim.h" #include "libc/sysv/consts/rlim.h"
#include "libc/sysv/consts/sig.h" #include "libc/sysv/consts/sig.h"
#include "libc/sysv/consts/termios.h" #include "libc/sysv/consts/termios.h"
@ -137,6 +139,9 @@ static noasan void PrintDependencies(const char *prologue) {
} while ((ldr = ldr->Next) && ldr != head); } while ((ldr = ldr->Next) && ldr != head);
} }
static noasan void Print(const char *prologue) {
}
/** /**
* Prints lots of information about this process, e.g. * Prints lots of information about this process, e.g.
* *
@ -150,6 +155,7 @@ textstartup void __printargs(const char *prologue) {
long key; long key;
char **env; char **env;
sigset_t ss; sigset_t ss;
bool gotsome;
unsigned i, n; unsigned i, n;
int e, x, flags; int e, x, flags;
uintptr_t *auxp; uintptr_t *auxp;
@ -223,8 +229,9 @@ textstartup void __printargs(const char *prologue) {
PRINT(" L%d%s%s %u-way %,u byte cache w/%s " PRINT(" L%d%s%s %u-way %,u byte cache w/%s "
"%,u sets of %,u byte lines shared across %u threads%s", "%,u sets of %,u byte lines shared across %u threads%s",
CPUID4_CACHE_LEVEL, CPUID4_CACHE_LEVEL,
CPUID4_CACHE_TYPE == 1 ? " data" CPUID4_CACHE_TYPE == 1 ? " data"
: CPUID4_CACHE_TYPE == 2 ? " code" : "", : CPUID4_CACHE_TYPE == 2 ? " code"
: "",
CPUID4_IS_FULLY_ASSOCIATIVE ? " fully-associative" : "", CPUID4_IS_FULLY_ASSOCIATIVE ? " fully-associative" : "",
CPUID4_WAYS_OF_ASSOCIATIVITY, CPUID4_CACHE_SIZE_IN_BYTES, CPUID4_WAYS_OF_ASSOCIATIVITY, CPUID4_CACHE_SIZE_IN_BYTES,
CPUID4_PHYSICAL_LINE_PARTITIONS > 1 ? " physically partitioned" : "", CPUID4_PHYSICAL_LINE_PARTITIONS > 1 ? " physically partitioned" : "",
@ -289,6 +296,24 @@ textstartup void __printargs(const char *prologue) {
PRINT(" error: sigprocmask() failed %m"); PRINT(" error: sigprocmask() failed %m");
} }
if (IsLinux()) {
PRINT("");
PRINT("CAPABILITIES");
if (prctl(PR_CAPBSET_READ, 0) != -1) {
for (gotsome = i = 0; i <= CAP_LAST_CAP; ++i) {
if (prctl(PR_CAPBSET_READ, i) == 1) {
PRINT(" ☼ %s", DescribeCapability(i));
gotsome = true;
}
}
if (!gotsome) {
PRINT(" ☼ %s", "none");
}
} else {
PRINT(" ☼ %s", strerror(errno));
}
}
PRINT(""); PRINT("");
PRINT("RESOURCE LIMITS"); PRINT("RESOURCE LIMITS");
for (i = 0; i < RLIM_NLIMITS; ++i) { for (i = 0; i < RLIM_NLIMITS; ++i) {

47
libc/sysv/consts/cap.h Normal file
View file

@ -0,0 +1,47 @@
#ifndef COSMOPOLITAN_LIBC_SYSV_CONSTS_CAP_H_
#define COSMOPOLITAN_LIBC_SYSV_CONSTS_CAP_H_
#define CAP_CHOWN 0
#define CAP_DAC_OVERRIDE 1
#define CAP_DAC_READ_SEARCH 2
#define CAP_FOWNER 3
#define CAP_FSETID 4
#define CAP_KILL 5
#define CAP_SETGID 6
#define CAP_SETUID 7
#define CAP_SETPCAP 8
#define CAP_LINUX_IMMUTABLE 9
#define CAP_NET_BIND_SERVICE 10
#define CAP_NET_BROADCAST 11
#define CAP_NET_ADMIN 12
#define CAP_NET_RAW 13
#define CAP_IPC_LOCK 14
#define CAP_IPC_OWNER 15
#define CAP_SYS_MODULE 16
#define CAP_SYS_RAWIO 17
#define CAP_SYS_CHROOT 18
#define CAP_SYS_PTRACE 19
#define CAP_SYS_PACCT 20
#define CAP_SYS_ADMIN 21
#define CAP_SYS_BOOT 22
#define CAP_SYS_NICE 23
#define CAP_SYS_RESOURCE 24
#define CAP_SYS_TIME 25
#define CAP_SYS_TTY_CONFIG 26
#define CAP_MKNOD 27
#define CAP_LEASE 28
#define CAP_AUDIT_WRITE 29
#define CAP_AUDIT_CONTROL 30
#define CAP_SETFCAP 31
#define CAP_MAC_OVERRIDE 32
#define CAP_MAC_ADMIN 33
#define CAP_SYSLOG 34
#define CAP_WAKE_ALARM 35
#define CAP_BLOCK_SUSPEND 36
#define CAP_AUDIT_READ 37
#define CAP_PERFMON 38
#define CAP_BPF 39
#define CAP_CHECKPOINT_RESTORE 40
#define CAP_LAST_CAP CAP_CHECKPOINT_RESTORE
#endif /* COSMOPOLITAN_LIBC_SYSV_CONSTS_CAP_H_ */

38
libc/sysv/consts/fs.h Normal file
View file

@ -0,0 +1,38 @@
#ifndef COSMOPOLITAN_LIBC_SYSV_CONSTS_FS_H_
#define COSMOPOLITAN_LIBC_SYSV_CONSTS_FS_H_
#define FS_IOC_GETFLAGS 0x80086601
#define FS_IOC_SETFLAGS 0x40086602
#define FS_IOC_GETVERSION 0x80087601
#define FS_IOC_SETVERSION 0x40087602
#define FS_IOC_FIEMAP 0xc020660b
#define FS_IOC_FSGETXATTR 0x801c581f
#define FS_IOC_FSSETXATTR 0x401c5820
#define FS_IOC_GETFSLABEL 0x81009431
#define FS_IOC_SETFSLABEL 0x41009432
#define FS_FL_USER_VISIBLE 0x0003DFFF /* user visible flags */
#define FS_FL_USER_MODIFIABLE 0x000380FF /* user modifiable flags */
#define FS_SECRM_FL 0x00000001 /* secure deletion */
#define FS_UNRM_FL 0x00000002 /* undelete */
#define FS_COMPR_FL 0x00000004 /* compress */
#define FS_SYNC_FL 0x00000008 /* synchronous */
#define FS_IMMUTABLE_FL 0x00000010
#define FS_APPEND_FL 0x00000020 /* append-only */
#define FS_NODUMP_FL 0x00000040
#define FS_NOATIME_FL 0x00000080
#define FS_DIRTY_FL 0x00000100
#define FS_COMPRBLK_FL 0x00000200
#define FS_NOCOMP_FL 0x00000400
#define FS_ENCRYPT_FL 0x00000800 /* encrypted file */
#define FS_BTREE_FL 0x00001000
#define FS_INDEX_FL 0x00001000 /* hash-indexed directory */
#define FS_IMAGIC_FL 0x00002000
#define FS_JOURNAL_DATA_FL 0x00004000
#define FS_NOTAIL_FL 0x00008000
#define FS_DIRSYNC_FL 0x00010000
#define FS_TOPDIR_FL 0x00020000
#define FS_HUGE_FILE_FL 0x00040000
#define FS_EXTENT_FL 0x00080000
#endif /* COSMOPOLITAN_LIBC_SYSV_CONSTS_FS_H_ */

View file

@ -7,6 +7,9 @@
#define SECCOMP_MODE_STRICT 1 #define SECCOMP_MODE_STRICT 1
#define SECCOMP_MODE_FILTER 2 #define SECCOMP_MODE_FILTER 2
#define PR_CAPBSET_READ 23
#define PR_CAPBSET_DROP 24
#define PR_SET_NO_NEW_PRIVS 38 #define PR_SET_NO_NEW_PRIVS 38
#define PR_GET_NO_NEW_PRIVS 39 #define PR_GET_NO_NEW_PRIVS 39
@ -73,8 +76,6 @@
#define PR_SET_MM_EXE_FILE 13 #define PR_SET_MM_EXE_FILE 13
#define PR_SET_MM_MAP 14 #define PR_SET_MM_MAP 14
#define PR_SET_MM_MAP_SIZE 15 #define PR_SET_MM_MAP_SIZE 15
#define PR_CAPBSET_READ 23
#define PR_CAPBSET_DROP 24
#define PR_GET_TSC 25 #define PR_GET_TSC 25
#define PR_SET_TSC 26 #define PR_SET_TSC 26
#define PR_GET_SECUREBITS 27 #define PR_GET_SECUREBITS 27

View file

@ -47,6 +47,7 @@
#include "libc/sysv/consts/o.h" #include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/ok.h" #include "libc/sysv/consts/ok.h"
#include "libc/sysv/consts/poll.h" #include "libc/sysv/consts/poll.h"
#include "libc/sysv/consts/pr.h"
#include "libc/sysv/consts/prio.h" #include "libc/sysv/consts/prio.h"
#include "libc/sysv/consts/prot.h" #include "libc/sysv/consts/prot.h"
#include "libc/sysv/consts/rlimit.h" #include "libc/sysv/consts/rlimit.h"
@ -66,6 +67,7 @@ usage: pledge.com [-hnN] PROG ARGS...\n\
-c PATH call chroot()\n\ -c PATH call chroot()\n\
-v [PERM:]PATH call unveil(PATH, PERM[rwxc])\n\ -v [PERM:]PATH call unveil(PATH, PERM[rwxc])\n\
-n set maximum niceness\n\ -n set maximum niceness\n\
-D don't drop capabilities\n\
-N don't normalize file descriptors\n\ -N don't normalize file descriptors\n\
-C SECS set cpu limit [default: inherited]\n\ -C SECS set cpu limit [default: inherited]\n\
-M BYTES set virtual memory limit [default: 4gb]\n\ -M BYTES set virtual memory limit [default: 4gb]\n\
@ -116,6 +118,7 @@ long g_cpuquota;
long g_fszquota; long g_fszquota;
long g_memquota; long g_memquota;
long g_proquota; long g_proquota;
long g_dontdrop;
const char *g_chroot; const char *g_chroot;
const char *g_promises; const char *g_promises;
@ -133,7 +136,7 @@ static void GetOpts(int argc, char *argv[]) {
g_fszquota = 4 * 1000 * 1000 * 1000; g_fszquota = 4 * 1000 * 1000 * 1000;
g_memquota = 4L * 1024 * 1024 * 1024; g_memquota = 4L * 1024 * 1024 * 1024;
if (!sysinfo(&si)) g_memquota = si.totalram; if (!sysinfo(&si)) g_memquota = si.totalram;
while ((opt = getopt(argc, argv, "hnNp:u:g:c:C:P:M:F:v:")) != -1) { while ((opt = getopt(argc, argv, "hnNp:u:g:c:C:D:P:M:F:v:")) != -1) {
switch (opt) { switch (opt) {
case 'n': case 'n':
g_nice = true; g_nice = true;
@ -141,6 +144,9 @@ static void GetOpts(int argc, char *argv[]) {
case 'N': case 'N':
g_noclose = true; g_noclose = true;
break; break;
case 'D':
g_dontdrop = true;
break;
case 'c': case 'c':
g_chroot = optarg; g_chroot = optarg;
break; break;
@ -493,6 +499,21 @@ void ApplyFilesystemPolicy(unsigned long ipromises) {
} }
} }
void DropCapabilities(void) {
int e, i;
for (e = errno, i = 0;; ++i) {
if (prctl(PR_CAPBSET_DROP, i) == -1) {
if (errno == EINVAL || errno == EPERM) {
errno = e;
break;
} else {
kprintf("error: prctl(PR_CAPBSET_DROP, %d) failed: %m\n", i);
_Exit(25);
}
}
}
}
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
bool hasfunbits; bool hasfunbits;
int useruid, usergid; int useruid, usergid;
@ -531,6 +552,15 @@ int main(int argc, char *argv[]) {
owneruid = geteuid(); owneruid = geteuid();
hasfunbits = usergid != ownergid || useruid != owneruid; hasfunbits = usergid != ownergid || useruid != owneruid;
if (g_dontdrop) {
if (hasfunbits) {
kprintf("error: -D flag forbidden on setuid binaries\n");
_Exit(6);
}
} else {
DropCapabilities();
}
if (hasfunbits) { if (hasfunbits) {
setuid(owneruid); setuid(owneruid);
setgid(ownergid); setgid(ownergid);

View file

@ -735,7 +735,7 @@ FUNCTIONS
Turns Lua data structure into JSON string. Turns Lua data structure into JSON string.
Since Lua uses tables for both hashmaps and arrays, we use a Since Lua uses tables are both hashmaps and arrays, we use a
simple fast algorithm for telling the two apart. Tables with simple fast algorithm for telling the two apart. Tables with
non-zero length (as reported by `#`) are encoded as arrays, non-zero length (as reported by `#`) are encoded as arrays,
and any non-array elements are ignored. For example: and any non-array elements are ignored. For example:

View file

@ -7295,6 +7295,13 @@ static void GetOpts(int argc, char *argv[]) {
void RedBean(int argc, char *argv[]) { void RedBean(int argc, char *argv[]) {
if (IsLinux()) { if (IsLinux()) {
// disable weird linux capabilities
for (int e = errno, i = 0;; ++i) {
if (prctl(PR_CAPBSET_DROP, i) == -1) {
errno = e;
break;
}
}
// disable sneak privilege since we don't use them // disable sneak privilege since we don't use them
// seccomp will fail later if this fails // seccomp will fail later if this fails
prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);