mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-24 14:22:28 +00:00
Add .PLEDGE/.CPU/.MEMORY/etc. to Landlock Make 1.2
This commit is contained in:
parent
6c0bbfac4a
commit
7ab15e0b23
20 changed files with 494 additions and 329 deletions
67
ape/loader.c
67
ape/loader.c
|
@ -18,6 +18,7 @@
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "ape/loader.h"
|
#include "ape/loader.h"
|
||||||
|
|
||||||
|
#define SET_EXE_FILE 0 /* needs root ;_; */
|
||||||
#define TROUBLESHOOT 0
|
#define TROUBLESHOOT 0
|
||||||
#define TROUBLESHOOT_OS LINUX
|
#define TROUBLESHOOT_OS LINUX
|
||||||
|
|
||||||
|
@ -123,6 +124,8 @@
|
||||||
#define X_OK 1
|
#define X_OK 1
|
||||||
#define XCR0_SSE 2
|
#define XCR0_SSE 2
|
||||||
#define XCR0_AVX 4
|
#define XCR0_AVX 4
|
||||||
|
#define PR_SET_MM 35
|
||||||
|
#define PR_SET_MM_EXE_FILE 13
|
||||||
|
|
||||||
#define Read32(S) \
|
#define Read32(S) \
|
||||||
((unsigned)(255 & (S)[3]) << 030 | (unsigned)(255 & (S)[2]) << 020 | \
|
((unsigned)(255 & (S)[3]) << 030 | (unsigned)(255 & (S)[2]) << 020 | \
|
||||||
|
@ -174,7 +177,10 @@ struct ElfPhdr {
|
||||||
unsigned long p_align;
|
unsigned long p_align;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern char ehdr[];
|
||||||
|
extern char _end[];
|
||||||
static void *syscall;
|
static void *syscall;
|
||||||
|
static char relocated;
|
||||||
static struct PathSearcher ps;
|
static struct PathSearcher ps;
|
||||||
extern char __syscall_loader[];
|
extern char __syscall_loader[];
|
||||||
|
|
||||||
|
@ -182,7 +188,7 @@ static int ToLower(int c) {
|
||||||
return 'A' <= c && c <= 'Z' ? c + ('a' - 'A') : c;
|
return 'A' <= c && c <= 'Z' ? c + ('a' - 'A') : c;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *MemCpy(char *d, const char *s, unsigned long n) {
|
char *MemCpy(char *d, const char *s, unsigned long n) {
|
||||||
unsigned long i = 0;
|
unsigned long i = 0;
|
||||||
for (; i < n; ++i) d[i] = s[i];
|
for (; i < n; ++i) d[i] = s[i];
|
||||||
return d + n;
|
return d + n;
|
||||||
|
@ -373,6 +379,26 @@ __attribute__((__noinline__)) static long Mmap(long addr, long size, int prot,
|
||||||
return ax;
|
return ax;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int MunmapLinux(const void *addr, unsigned long size) {
|
||||||
|
int ax;
|
||||||
|
asm volatile("syscall"
|
||||||
|
: "=a"(ax)
|
||||||
|
: "0"(11), "D"(addr), "S"(size)
|
||||||
|
: "rcx", "r11", "memory");
|
||||||
|
return ax;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int PrctlLinux(int op, long a, long b, long c, long d) {
|
||||||
|
int rc;
|
||||||
|
asm volatile("mov\t%5,%%r10\n\t"
|
||||||
|
"mov\t%6,%%r8\n\t"
|
||||||
|
"syscall"
|
||||||
|
: "=a"(rc)
|
||||||
|
: "0"(157), "D"(op), "S"(a), "d"(b), "g"(c), "g"(d)
|
||||||
|
: "rcx", "r8", "r10", "r11", "memory");
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
static void Emit(int os, const char *s) {
|
static void Emit(int os, const char *s) {
|
||||||
Write(2, s, StrLen(s), os);
|
Write(2, s, StrLen(s), os);
|
||||||
}
|
}
|
||||||
|
@ -539,6 +565,23 @@ __attribute__((__noreturn__)) static void Spawn(int os, const char *exe, int fd,
|
||||||
if (!code) {
|
if (!code) {
|
||||||
Pexit(os, exe, 0, "ELF needs PT_LOAD phdr w/ PF_X");
|
Pexit(os, exe, 0, "ELF needs PT_LOAD phdr w/ PF_X");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if SET_EXE_FILE
|
||||||
|
// change /proc/pid/exe to new executable path
|
||||||
|
if (IsLinux() && relocated) {
|
||||||
|
MunmapLinux((char *)0x200000, (long)(_end - ehdr));
|
||||||
|
PrctlLinux(PR_SET_MM, PR_SET_MM_EXE_FILE, fd, 0, 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (relocated) {
|
||||||
|
int ax;
|
||||||
|
asm volatile("syscall"
|
||||||
|
: "=a"(ax)
|
||||||
|
: "0"(1), "D"(1), "S"("hello\n"), "d"(6)
|
||||||
|
: "rcx", "r11", "memory");
|
||||||
|
}
|
||||||
|
|
||||||
Close(fd, os);
|
Close(fd, os);
|
||||||
|
|
||||||
// authorize only the loaded program to issue system calls. if this
|
// authorize only the loaded program to issue system calls. if this
|
||||||
|
@ -584,7 +627,7 @@ __attribute__((__noreturn__)) void ApeLoader(long di, long *sp, char dl,
|
||||||
struct ApeLoader *handoff) {
|
struct ApeLoader *handoff) {
|
||||||
int rc;
|
int rc;
|
||||||
long *auxv;
|
long *auxv;
|
||||||
struct ElfEhdr *ehdr;
|
struct ElfEhdr *eh;
|
||||||
int c, i, fd, os, argc;
|
int c, i, fd, os, argc;
|
||||||
char *p, *exe, *prog, **argv, **envp, *page;
|
char *p, *exe, *prog, **argv, **envp, *page;
|
||||||
static union {
|
static union {
|
||||||
|
@ -630,7 +673,7 @@ __attribute__((__noreturn__)) void ApeLoader(long di, long *sp, char dl,
|
||||||
fd = handoff->fd;
|
fd = handoff->fd;
|
||||||
exe = handoff->prog;
|
exe = handoff->prog;
|
||||||
page = handoff->page;
|
page = handoff->page;
|
||||||
ehdr = (struct ElfEhdr *)handoff->page;
|
eh = (struct ElfEhdr *)handoff->page;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// detect openbsd
|
// detect openbsd
|
||||||
|
@ -653,6 +696,20 @@ __attribute__((__noreturn__)) void ApeLoader(long di, long *sp, char dl,
|
||||||
os = LINUX;
|
os = LINUX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if SET_EXE_FILE
|
||||||
|
if (IsLinux() && !relocated) {
|
||||||
|
char *b1 = (char *)0x200000;
|
||||||
|
char *b2 = (char *)0x300000;
|
||||||
|
void (*pApeLoader)(long, long *, char, struct ApeLoader *);
|
||||||
|
Mmap((long)b2, (long)(_end - ehdr), PROT_READ | PROT_WRITE | PROT_EXEC,
|
||||||
|
MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0, os);
|
||||||
|
relocated = 1;
|
||||||
|
MemCpy(b2, b1, (long)(_end - ehdr));
|
||||||
|
pApeLoader = (void *)((char *)&ApeLoader - b1 + b2);
|
||||||
|
pApeLoader(di, sp, dl, handoff);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// we can load via shell, shebang, or binfmt_misc
|
// we can load via shell, shebang, or binfmt_misc
|
||||||
if (argc >= 3 && !StrCmp(argv[1], "-")) {
|
if (argc >= 3 && !StrCmp(argv[1], "-")) {
|
||||||
// if the first argument is a hyphen then we give the user the
|
// if the first argument is a hyphen then we give the user the
|
||||||
|
@ -686,7 +743,7 @@ __attribute__((__noreturn__)) void ApeLoader(long di, long *sp, char dl,
|
||||||
}
|
}
|
||||||
|
|
||||||
page = u.p;
|
page = u.p;
|
||||||
ehdr = &u.ehdr;
|
eh = &u.ehdr;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TROUBLESHOOT
|
#if TROUBLESHOOT
|
||||||
|
@ -726,7 +783,7 @@ __attribute__((__noreturn__)) void ApeLoader(long di, long *sp, char dl,
|
||||||
page[i++] = c;
|
page[i++] = c;
|
||||||
}
|
}
|
||||||
if (i >= 64 && Read32(page) == Read32("\177ELF")) {
|
if (i >= 64 && Read32(page) == Read32("\177ELF")) {
|
||||||
Spawn(os, exe, fd, sp, page, ehdr);
|
Spawn(os, exe, fd, sp, page, eh);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,8 @@ SECTIONS {
|
||||||
*(.bss)
|
*(.bss)
|
||||||
. = ALIGN(4096);
|
. = ALIGN(4096);
|
||||||
}
|
}
|
||||||
memsz = . - ehdr;
|
_end = .;
|
||||||
|
memsz = _end - ehdr;
|
||||||
/DISCARD/ : {
|
/DISCARD/ : {
|
||||||
*(.*)
|
*(.*)
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,33 +45,33 @@ int main(int argc, char *argv[]) {
|
||||||
1. / 65536 * si.loads[1], //
|
1. / 65536 * si.loads[1], //
|
||||||
1. / 65536 * si.loads[2]); //
|
1. / 65536 * si.loads[2]); //
|
||||||
|
|
||||||
FormatMemorySize(ibuf, si.totalram);
|
FormatMemorySize(ibuf, si.totalram, 1024);
|
||||||
printf("%-16s %s\n", "totalram", ibuf);
|
printf("%-16s %s\n", "totalram", ibuf);
|
||||||
|
|
||||||
FormatMemorySize(ibuf, si.freeram);
|
FormatMemorySize(ibuf, si.freeram, 1024);
|
||||||
printf("%-16s %s\n", "freeram", ibuf);
|
printf("%-16s %s\n", "freeram", ibuf);
|
||||||
|
|
||||||
FormatMemorySize(ibuf, si.sharedram);
|
FormatMemorySize(ibuf, si.sharedram, 1024);
|
||||||
printf("%-16s %s\n", "sharedram", ibuf);
|
printf("%-16s %s\n", "sharedram", ibuf);
|
||||||
|
|
||||||
FormatMemorySize(ibuf, si.bufferram);
|
FormatMemorySize(ibuf, si.bufferram, 1024);
|
||||||
printf("%-16s %s\n", "bufferram", ibuf);
|
printf("%-16s %s\n", "bufferram", ibuf);
|
||||||
|
|
||||||
FormatMemorySize(ibuf, si.totalswap);
|
FormatMemorySize(ibuf, si.totalswap, 1024);
|
||||||
printf("%-16s %s\n", "totalswap", ibuf);
|
printf("%-16s %s\n", "totalswap", ibuf);
|
||||||
|
|
||||||
FormatMemorySize(ibuf, si.freeswap);
|
FormatMemorySize(ibuf, si.freeswap, 1024);
|
||||||
printf("%-16s %s\n", "freeswap", ibuf);
|
printf("%-16s %s\n", "freeswap", ibuf);
|
||||||
|
|
||||||
printf("%-16s %lu\n", "processes", si.procs);
|
printf("%-16s %lu\n", "processes", si.procs);
|
||||||
|
|
||||||
FormatMemorySize(ibuf, si.totalhigh);
|
FormatMemorySize(ibuf, si.totalhigh, 1024);
|
||||||
printf("%-16s %s\n", "totalhigh", ibuf);
|
printf("%-16s %s\n", "totalhigh", ibuf);
|
||||||
|
|
||||||
FormatMemorySize(ibuf, si.freehigh);
|
FormatMemorySize(ibuf, si.freehigh, 1024);
|
||||||
printf("%-16s %s\n", "freehigh", ibuf);
|
printf("%-16s %s\n", "freehigh", ibuf);
|
||||||
|
|
||||||
FormatMemorySize(ibuf, si.mem_unit);
|
FormatMemorySize(ibuf, si.mem_unit, 1024);
|
||||||
printf("%-16s %s\n", "mem_unit", ibuf);
|
printf("%-16s %s\n", "mem_unit", ibuf);
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
@ -825,7 +825,7 @@ static privileged void *MemCpy(void *d, const void *s, unsigned long n) {
|
||||||
return (char *)d + n;
|
return (char *)d + n;
|
||||||
}
|
}
|
||||||
|
|
||||||
static privileged char *FixCpy(char p[17], uint64_t x, uint8_t k) {
|
static privileged char *FixCpy(char p[17], uint64_t x, int k) {
|
||||||
while (k > 0) *p++ = "0123456789abcdef"[(x >> (k -= 4)) & 15];
|
while (k > 0) *p++ = "0123456789abcdef"[(x >> (k -= 4)) & 15];
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
return p;
|
return p;
|
||||||
|
@ -868,7 +868,6 @@ static privileged void Log(const char *s, ...) {
|
||||||
|
|
||||||
static privileged int Prctl(int op, long a, void *b, long c, long d) {
|
static privileged int Prctl(int op, long a, void *b, long c, long d) {
|
||||||
int rc;
|
int rc;
|
||||||
va_list va;
|
|
||||||
asm volatile("mov\t%5,%%r10\n\t"
|
asm volatile("mov\t%5,%%r10\n\t"
|
||||||
"mov\t%6,%%r8\n\t"
|
"mov\t%6,%%r8\n\t"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
|
@ -19,26 +19,26 @@
|
||||||
#include "libc/fmt/itoa.h"
|
#include "libc/fmt/itoa.h"
|
||||||
#include "libc/macros.internal.h"
|
#include "libc/macros.internal.h"
|
||||||
|
|
||||||
static const struct {
|
|
||||||
char suffix;
|
|
||||||
uint64_t size;
|
|
||||||
} kUnits[] = {
|
|
||||||
{'e', 1024ULL * 1024 * 1024 * 1024 * 1024 * 1024},
|
|
||||||
{'p', 1024ULL * 1024 * 1024 * 1024 * 1024},
|
|
||||||
{'t', 1024ULL * 1024 * 1024 * 1024},
|
|
||||||
{'g', 1024ULL * 1024 * 1024},
|
|
||||||
{'m', 1024ULL * 1024},
|
|
||||||
{'k', 1024ULL},
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents size of memory readably.
|
* Represents size of memory readably.
|
||||||
*
|
*
|
||||||
* @param p is output buffer
|
* @param p is output buffer
|
||||||
|
* @param b should be 1024 or 1000
|
||||||
* @return pointer to nul byte
|
* @return pointer to nul byte
|
||||||
*/
|
*/
|
||||||
char *FormatMemorySize(char *p, uint64_t x) {
|
char *FormatMemorySize(char *p, uint64_t x, uint64_t b) {
|
||||||
int i, suffix;
|
int i, suffix;
|
||||||
|
struct {
|
||||||
|
char suffix;
|
||||||
|
uint64_t size;
|
||||||
|
} kUnits[] = {
|
||||||
|
{'e', b * b * b * b * b * b},
|
||||||
|
{'p', b * b * b * b * b},
|
||||||
|
{'t', b * b * b * b},
|
||||||
|
{'g', b * b * b},
|
||||||
|
{'m', b * b},
|
||||||
|
{'k', b},
|
||||||
|
};
|
||||||
for (suffix = i = 0; i < ARRAYLEN(kUnits); ++i) {
|
for (suffix = i = 0; i < ARRAYLEN(kUnits); ++i) {
|
||||||
if (x >= kUnits[i].size * 9) {
|
if (x >= kUnits[i].size * 9) {
|
||||||
x = (x + kUnits[i].size / 2) / kUnits[i].size;
|
x = (x + kUnits[i].size / 2) / kUnits[i].size;
|
||||||
|
|
|
@ -21,7 +21,7 @@ char *FormatFlex64(char[hasatleast 24], int64_t, char);
|
||||||
size_t uint64toarray_radix16(uint64_t, char[hasatleast 17]);
|
size_t uint64toarray_radix16(uint64_t, char[hasatleast 17]);
|
||||||
size_t uint64toarray_fixed16(uint64_t, char[hasatleast 17], uint8_t);
|
size_t uint64toarray_fixed16(uint64_t, char[hasatleast 17], uint8_t);
|
||||||
size_t uint64toarray_radix8(uint64_t, char[hasatleast 24]);
|
size_t uint64toarray_radix8(uint64_t, char[hasatleast 24]);
|
||||||
char *FormatMemorySize(char *, uint64_t);
|
char *FormatMemorySize(char *, uint64_t, uint64_t);
|
||||||
|
|
||||||
#ifndef __STRICT_ANSI__
|
#ifndef __STRICT_ANSI__
|
||||||
size_t int128toarray_radix10(int128_t, char *);
|
size_t int128toarray_radix10(int128_t, char *);
|
||||||
|
|
|
@ -158,7 +158,7 @@ static bool IsSockaddrAllowed(struct sockaddr_storage *addr) {
|
||||||
}
|
}
|
||||||
if (addr->ss_family == AF_INET) {
|
if (addr->ss_family == AF_INET) {
|
||||||
ip = ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr);
|
ip = ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr);
|
||||||
if (!IsPublicIp(ip)) {
|
if (IsPrivateIp(ip) || IsLoopbackIp(ip)) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
kprintf("warning: attempted to communicate with public ip "
|
kprintf("warning: attempted to communicate with public ip "
|
||||||
|
|
|
@ -35,7 +35,7 @@ void SetUpOnce(void) {
|
||||||
TEST(setsockopt, SO_RCVTIMEO) {
|
TEST(setsockopt, SO_RCVTIMEO) {
|
||||||
char buf[32];
|
char buf[32];
|
||||||
struct timeval tv = {0, 10000};
|
struct timeval tv = {0, 10000};
|
||||||
struct sockaddr_in sa = {AF_INET};
|
struct sockaddr_in sa = {AF_INET, 0, {htonl(0x7f000001)}};
|
||||||
EXPECT_SYS(0, 3, socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP));
|
EXPECT_SYS(0, 3, socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP));
|
||||||
EXPECT_SYS(0, 0, setsockopt(3, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)));
|
EXPECT_SYS(0, 0, setsockopt(3, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)));
|
||||||
EXPECT_SYS(0, 0, bind(3, &sa, sizeof(struct sockaddr_in)));
|
EXPECT_SYS(0, 0, bind(3, &sa, sizeof(struct sockaddr_in)));
|
||||||
|
|
188
third_party/make/README
vendored
188
third_party/make/README
vendored
|
@ -1,188 +0,0 @@
|
||||||
This directory contains the 4.3 release of GNU Make.
|
|
||||||
|
|
||||||
See the file NEWS for the user-visible changes from previous releases.
|
|
||||||
In addition, there have been bugs fixed.
|
|
||||||
|
|
||||||
Please check the system-specific notes below for any caveats related to your
|
|
||||||
operating system.
|
|
||||||
|
|
||||||
If you are trying to build GNU make from a Git clone rather than a downloaded
|
|
||||||
source distribution, see the README.git file for instructions.
|
|
||||||
|
|
||||||
For source distribution building and installation instructions, see the file
|
|
||||||
INSTALL.
|
|
||||||
|
|
||||||
If you need to build GNU Make and have no other 'make' program to use, you can
|
|
||||||
use the shell script 'build.sh' instead. To do this, first run 'configure' as
|
|
||||||
described in INSTALL. Then, instead of typing 'make' to build the program,
|
|
||||||
type 'sh build.sh'. This should compile the program in the current directory.
|
|
||||||
Then you will have a Make program that you can use for './make install', or
|
|
||||||
whatever else.
|
|
||||||
|
|
||||||
Some systems' Make programs cannot process the Makefile for GNU Make. If you
|
|
||||||
get errors from your system's Make when building GNU Make, try using
|
|
||||||
'build.sh' instead.
|
|
||||||
|
|
||||||
|
|
||||||
GNU Make is free software. See the file COPYING for copying conditions.
|
|
||||||
GNU Make is copyright by the Free Software Foundation. Copyright notices
|
|
||||||
condense sequential years into a range; e.g. "1987-1994" means all years
|
|
||||||
from 1987 to 1994 inclusive.
|
|
||||||
|
|
||||||
Downloading
|
|
||||||
-----------
|
|
||||||
|
|
||||||
GNU Make can be obtained in many different ways. See a description here:
|
|
||||||
|
|
||||||
http://www.gnu.org/software/software.html
|
|
||||||
|
|
||||||
|
|
||||||
Documentation
|
|
||||||
-------------
|
|
||||||
|
|
||||||
GNU make is fully documented in the GNU Make manual, which is contained
|
|
||||||
in this distribution as the file make.texinfo. You can also find
|
|
||||||
on-line and preformatted (PostScript and DVI) versions at the FSF's web
|
|
||||||
site. There is information there about ordering hardcopy documentation.
|
|
||||||
|
|
||||||
http://www.gnu.org/
|
|
||||||
http://www.gnu.org/doc/doc.html
|
|
||||||
http://www.gnu.org/manual/manual.html
|
|
||||||
|
|
||||||
|
|
||||||
Development
|
|
||||||
-----------
|
|
||||||
|
|
||||||
GNU Make development is hosted by Savannah, the FSF's online development
|
|
||||||
management tool. Savannah is here:
|
|
||||||
|
|
||||||
http://savannah.gnu.org
|
|
||||||
|
|
||||||
And the GNU Make development page is here:
|
|
||||||
|
|
||||||
http://savannah.gnu.org/projects/make/
|
|
||||||
|
|
||||||
You can find most information concerning the development of GNU Make at
|
|
||||||
this site.
|
|
||||||
|
|
||||||
|
|
||||||
Bug Reporting
|
|
||||||
-------------
|
|
||||||
|
|
||||||
You can send GNU make bug reports to <bug-make@gnu.org>. Please see the
|
|
||||||
section of the GNU make manual entitled 'Problems and Bugs' for
|
|
||||||
information on submitting useful and complete bug reports.
|
|
||||||
|
|
||||||
You can also use the online bug tracking system in the Savannah GNU Make
|
|
||||||
project to submit new problem reports or search for existing ones:
|
|
||||||
|
|
||||||
http://savannah.gnu.org/bugs/?group=make
|
|
||||||
|
|
||||||
If you need help using GNU make, try these forums:
|
|
||||||
|
|
||||||
help-make@gnu.org
|
|
||||||
help-utils@gnu.org
|
|
||||||
news:gnu.utils.help
|
|
||||||
news:gnu.utils.bug
|
|
||||||
|
|
||||||
|
|
||||||
Git Access
|
|
||||||
----------
|
|
||||||
|
|
||||||
The GNU make source repository is available via Git from the GNU Savannah Git
|
|
||||||
server; look here for details:
|
|
||||||
|
|
||||||
http://savannah.gnu.org/git/?group=make
|
|
||||||
|
|
||||||
Please note: you won't be able to build GNU make from Git without installing
|
|
||||||
appropriate maintainer's tools, such as GNU m4, automake, autoconf, Perl, GNU
|
|
||||||
make, and GCC.
|
|
||||||
|
|
||||||
See the README.git file for instructions on how to build GNU make once these
|
|
||||||
tools are available. We make no guarantees about the contents or quality of
|
|
||||||
the latest code in the Git repository: it is not unheard of for code that is
|
|
||||||
known to be broken to be checked in. Use at your own risk.
|
|
||||||
|
|
||||||
|
|
||||||
System-specific Notes
|
|
||||||
---------------------
|
|
||||||
|
|
||||||
It has been reported that the XLC 1.2 compiler on AIX 3.2 is buggy such
|
|
||||||
that if you compile make with 'cc -O' on AIX 3.2, it will not work
|
|
||||||
correctly. It is said that using 'cc' without '-O' does work.
|
|
||||||
|
|
||||||
The standard /bin/sh on SunOS 4.1.3_U1 and 4.1.4 is broken and cannot be
|
|
||||||
used to configure GNU make. Please install a different shell such as
|
|
||||||
bash or pdksh in order to run "configure". See this message for more
|
|
||||||
information:
|
|
||||||
http://mail.gnu.org/archive/html/bug-autoconf/2003-10/msg00190.html
|
|
||||||
|
|
||||||
One area that is often a problem in configuration and porting is the code
|
|
||||||
to check the system's current load average. To make it easier to test and
|
|
||||||
debug this code, you can do 'make check-loadavg' to see if it works
|
|
||||||
properly on your system. (You must run 'configure' beforehand, but you
|
|
||||||
need not build Make itself to run this test.)
|
|
||||||
|
|
||||||
Another potential source of porting problems is the support for large
|
|
||||||
files (LFS) in configure for those operating systems that provide it.
|
|
||||||
Please report any bugs that you find in this area. If you run into
|
|
||||||
difficulties, then as a workaround you should be able to disable LFS by
|
|
||||||
adding the '--disable-largefile' option to the 'configure' script.
|
|
||||||
|
|
||||||
On systems that support micro- and nano-second timestamp values and
|
|
||||||
where stat(2) provides this information, GNU make will use it when
|
|
||||||
comparing timestamps to get the most accurate possible result. However,
|
|
||||||
note that many current implementations of tools that *set* timestamps do
|
|
||||||
not preserve micro- or nano-second granularity. This means that "cp -p"
|
|
||||||
and other similar tools (tar, etc.) may not exactly duplicate timestamps
|
|
||||||
with micro- and nano-second granularity on some systems. If your build
|
|
||||||
system contains rules that depend on proper behavior of tools like "cp
|
|
||||||
-p", you should consider using the .LOW_RESOLUTION_TIME pseudo-target to
|
|
||||||
force make to treat them properly. See the manual for details.
|
|
||||||
|
|
||||||
|
|
||||||
Ports
|
|
||||||
-----
|
|
||||||
|
|
||||||
- See README.customs for details on integrating GNU make with the
|
|
||||||
Customs distributed build environment from the Pmake distribution.
|
|
||||||
|
|
||||||
- See README.VMS for details about GNU Make on OpenVMS.
|
|
||||||
|
|
||||||
- See README.Amiga for details about GNU Make on AmigaDOS.
|
|
||||||
|
|
||||||
- See README.W32 for details about GNU Make on Windows NT, 95, or 98.
|
|
||||||
|
|
||||||
- See README.DOS for compilation instructions on MS-DOS and MS-Windows
|
|
||||||
using DJGPP tools.
|
|
||||||
|
|
||||||
A precompiled binary of the MSDOS port of GNU Make is available as part
|
|
||||||
of DJGPP; see the WWW page http://www.delorie.com/djgpp/ for more
|
|
||||||
information.
|
|
||||||
|
|
||||||
The Cygwin project maintains its own port of GNU make. That port may have
|
|
||||||
patches which are not present in this version. If you are using Cygwin
|
|
||||||
you should use their version of GNU make, and if you have questions about
|
|
||||||
it you should start by asking on those mailing lists and forums.
|
|
||||||
|
|
||||||
Please note there are two _separate_ ports of GNU make for Microsoft
|
|
||||||
systems: a native Windows tool built with (for example) MSVC or Cygwin,
|
|
||||||
and a DOS-based tool built with DJGPP. Please be sure you are looking
|
|
||||||
at the right README!
|
|
||||||
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
Copyright (C) 1988-2020 Free Software Foundation, Inc.
|
|
||||||
This file is part of GNU Make.
|
|
||||||
|
|
||||||
GNU Make is free software; you can redistribute it and/or modify it under the
|
|
||||||
terms of the GNU General Public License as published by the Free Software
|
|
||||||
Foundation; either version 3 of the License, or (at your option) any later
|
|
||||||
version.
|
|
||||||
|
|
||||||
GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along with
|
|
||||||
this program. If not, see <http://www.gnu.org/licenses/>.
|
|
25
third_party/make/README.cosmo
vendored
25
third_party/make/README.cosmo
vendored
|
@ -1,12 +1,29 @@
|
||||||
|
DESCRIPTION
|
||||||
|
|
||||||
|
Landlock Make is a fork of GNU Make that adds support for automatic
|
||||||
|
sandboxing, resource limits, and network access restrictions.
|
||||||
|
|
||||||
ORIGIN
|
ORIGIN
|
||||||
|
|
||||||
GNU Make 4.3
|
GNU Make 4.3
|
||||||
http://ftp.gnu.org/gnu/make/make-4.3.tar.gz
|
http://ftp.gnu.org/gnu/make/make-4.3.tar.gz
|
||||||
|
|
||||||
|
LICENSE
|
||||||
|
|
||||||
|
GNU GPL version 3 or later
|
||||||
|
http://gnu.org/licenses/gpl.html
|
||||||
|
|
||||||
LOCAL CHANGES
|
LOCAL CHANGES
|
||||||
|
|
||||||
- Remove portability torture code
|
- .INTERNET variable to allow internet access
|
||||||
- Add support for Landlock LSM sandboxing
|
- .PLEDGE variable which restricts system calls
|
||||||
- Add .UNSANDBOXED variable to disable it
|
- .UNVEIL variable which controls Landlock LSM
|
||||||
- Add .UNVEIL variable which works like .EXTRA_PREREQS
|
- .STRICT variable to disable implicit unveiling
|
||||||
|
- .UNSANDBOXED variable to disable pledge / unveil
|
||||||
|
- .CPU variable which tunes CPU rlimit in seconds
|
||||||
|
- .MEMORY variable for virtual memory limit, e.g. 512m
|
||||||
|
- .FSIZE variable which tunes max file size, e.g. 1g
|
||||||
|
- .NPROC variable which tunes fork() / clone() limit
|
||||||
|
- Do automatic setup and teardown of TMPDIR per rule
|
||||||
- Remove code that forces slow path if not using /bin/sh
|
- Remove code that forces slow path if not using /bin/sh
|
||||||
|
- Remove 200,000 lines of VAX/OS2/DOS/AMIGA/etc. code
|
||||||
|
|
2
third_party/make/function.c
vendored
2
third_party/make/function.c
vendored
|
@ -1640,7 +1640,7 @@ func_shell_base (char *o, char **argv, int trim_newlines)
|
||||||
child.output.err = errfd;
|
child.output.err = errfd;
|
||||||
child.environment = envp;
|
child.environment = envp;
|
||||||
|
|
||||||
pid = child_execute_job (&child, 1, command_argv);
|
pid = child_execute_job (&child, 1, command_argv, false);
|
||||||
|
|
||||||
free (child.cmd_name);
|
free (child.cmd_name);
|
||||||
}
|
}
|
||||||
|
|
365
third_party/make/job.c
vendored
365
third_party/make/job.c
vendored
|
@ -22,23 +22,31 @@ this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||||
/**/
|
/**/
|
||||||
#include "libc/assert.h"
|
#include "libc/assert.h"
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
|
#include "libc/calls/pledge.h"
|
||||||
|
#include "libc/calls/pledge.internal.h"
|
||||||
#include "libc/calls/struct/bpf.h"
|
#include "libc/calls/struct/bpf.h"
|
||||||
#include "libc/calls/struct/filter.h"
|
#include "libc/calls/struct/filter.h"
|
||||||
#include "libc/calls/struct/seccomp.h"
|
#include "libc/calls/struct/seccomp.h"
|
||||||
|
#include "libc/calls/struct/sysinfo.h"
|
||||||
#include "libc/calls/struct/timeval.h"
|
#include "libc/calls/struct/timeval.h"
|
||||||
|
#include "libc/dce.h"
|
||||||
#include "libc/elf/def.h"
|
#include "libc/elf/def.h"
|
||||||
#include "libc/elf/elf.h"
|
#include "libc/elf/elf.h"
|
||||||
#include "libc/elf/struct/ehdr.h"
|
#include "libc/elf/struct/ehdr.h"
|
||||||
#include "libc/elf/struct/phdr.h"
|
#include "libc/elf/struct/phdr.h"
|
||||||
|
#include "libc/fmt/conv.h"
|
||||||
#include "libc/fmt/fmt.h"
|
#include "libc/fmt/fmt.h"
|
||||||
|
#include "libc/fmt/itoa.h"
|
||||||
#include "libc/intrin/bits.h"
|
#include "libc/intrin/bits.h"
|
||||||
|
#include "libc/intrin/kprintf.h"
|
||||||
|
#include "libc/intrin/promises.internal.h"
|
||||||
#include "libc/intrin/safemacros.internal.h"
|
#include "libc/intrin/safemacros.internal.h"
|
||||||
#include "libc/log/backtrace.internal.h"
|
#include "libc/log/backtrace.internal.h"
|
||||||
#include "libc/log/log.h"
|
#include "libc/log/log.h"
|
||||||
#include "libc/log/rop.h"
|
#include "libc/log/rop.h"
|
||||||
#include "libc/macros.internal.h"
|
#include "libc/macros.internal.h"
|
||||||
|
#include "libc/nexgen32e/kcpuids.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
#include "libc/runtime/stack.h"
|
|
||||||
#include "libc/sock/sock.h"
|
#include "libc/sock/sock.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
#include "libc/sysv/consts/audit.h"
|
#include "libc/sysv/consts/audit.h"
|
||||||
|
@ -49,6 +57,7 @@ this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||||
#include "libc/sysv/consts/prot.h"
|
#include "libc/sysv/consts/prot.h"
|
||||||
#include "libc/time/time.h"
|
#include "libc/time/time.h"
|
||||||
#include "libc/x/x.h"
|
#include "libc/x/x.h"
|
||||||
|
#include "third_party/libcxx/math.h"
|
||||||
#include "third_party/make/commands.h"
|
#include "third_party/make/commands.h"
|
||||||
#include "third_party/make/dep.h"
|
#include "third_party/make/dep.h"
|
||||||
#include "third_party/make/os.h"
|
#include "third_party/make/os.h"
|
||||||
|
@ -75,8 +84,6 @@ int batch_mode_shell = 0;
|
||||||
|
|
||||||
#define WAIT_T int
|
#define WAIT_T int
|
||||||
|
|
||||||
bool g_strict;
|
|
||||||
|
|
||||||
/* Different systems have different requirements for pid_t.
|
/* Different systems have different requirements for pid_t.
|
||||||
Plus we have to support gettext string translation... Argh. */
|
Plus we have to support gettext string translation... Argh. */
|
||||||
static const char *
|
static const char *
|
||||||
|
@ -377,19 +384,39 @@ child_error (struct child *child,
|
||||||
|
|
||||||
/* [jart] manage temporary directories per rule */
|
/* [jart] manage temporary directories per rule */
|
||||||
|
|
||||||
|
bool
|
||||||
|
parse_bool (const char *s)
|
||||||
|
{
|
||||||
|
while (isspace (*s))
|
||||||
|
++s;
|
||||||
|
if (isdigit (*s))
|
||||||
|
return !! atoi (s);
|
||||||
|
return startswithi (s, "true");
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
get_target_variable (const char *name,
|
||||||
|
size_t length,
|
||||||
|
struct file *file,
|
||||||
|
const char *dflt)
|
||||||
|
{
|
||||||
|
const struct variable *var;
|
||||||
|
if ((file &&
|
||||||
|
((var = lookup_variable_in_set (name, length,
|
||||||
|
file->variables->set)) ||
|
||||||
|
(file->pat_variables &&
|
||||||
|
(var = lookup_variable_in_set (name, length,
|
||||||
|
file->pat_variables->set))))) ||
|
||||||
|
(var = lookup_variable (name, length)))
|
||||||
|
return variable_expand (var->value);
|
||||||
|
else
|
||||||
|
return dflt;
|
||||||
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
get_tmpdir (struct file *file)
|
get_tmpdir (struct file *file)
|
||||||
{
|
{
|
||||||
const struct variable *var;
|
return get_target_variable (STRING_SIZE_TUPLE("TMPDIR"), file, 0);
|
||||||
if ((var = lookup_variable_in_set (STRING_SIZE_TUPLE("TMPDIR"),
|
|
||||||
file->variables->set)) ||
|
|
||||||
(file->pat_variables &&
|
|
||||||
(var = lookup_variable_in_set (STRING_SIZE_TUPLE("TMPDIR"),
|
|
||||||
file->pat_variables->set))) ||
|
|
||||||
(var = lookup_variable (STRING_SIZE_TUPLE("TMPDIR"))))
|
|
||||||
return variable_expand (var->value);
|
|
||||||
else
|
|
||||||
return kTmpPath;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
|
@ -1154,7 +1181,7 @@ start_job_command (struct child *child)
|
||||||
parent_environ = environ;
|
parent_environ = environ;
|
||||||
jobserver_pre_child (flags & COMMANDS_RECURSE);
|
jobserver_pre_child (flags & COMMANDS_RECURSE);
|
||||||
child->pid = child_execute_job ((struct childbase *)child,
|
child->pid = child_execute_job ((struct childbase *)child,
|
||||||
child->good_stdin, argv);
|
child->good_stdin, argv, true);
|
||||||
environ = parent_environ; /* Restore value child may have clobbered. */
|
environ = parent_environ; /* Restore value child may have clobbered. */
|
||||||
jobserver_post_child (flags & COMMANDS_RECURSE);
|
jobserver_post_child (flags & COMMANDS_RECURSE);
|
||||||
}
|
}
|
||||||
|
@ -1277,7 +1304,8 @@ new_job (struct file *file)
|
||||||
c->sh_batch_file = NULL;
|
c->sh_batch_file = NULL;
|
||||||
|
|
||||||
/* [jart] manage temporary directories per rule */
|
/* [jart] manage temporary directories per rule */
|
||||||
if ((c->tmpdir = new_tmpdir (get_tmpdir (file), file)))
|
if ((c->tmpdir = get_tmpdir (file)) &&
|
||||||
|
(c->tmpdir = new_tmpdir (c->tmpdir, file)))
|
||||||
{
|
{
|
||||||
var = define_variable_for_file ("TMPDIR", 6, c->tmpdir,
|
var = define_variable_for_file ("TMPDIR", 6, c->tmpdir,
|
||||||
o_override, 0, file);
|
o_override, 0, file);
|
||||||
|
@ -1764,22 +1792,98 @@ unveil_variable (const struct variable *var)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
int
|
||||||
Vartoi (const struct variable *var)
|
get_base_cpu_freq_mhz (void)
|
||||||
{
|
{
|
||||||
return var && atoi (variable_expand (var->value));
|
return KCPUIDS(16H, EAX) & 0x7fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
set_cpu_limit (int secs)
|
||||||
|
{
|
||||||
|
int mhz, lim;
|
||||||
|
struct rlimit rlim;
|
||||||
|
if (secs <= 0) return;
|
||||||
|
if (IsWindows()) return;
|
||||||
|
if (!(mhz = get_base_cpu_freq_mhz())) return;
|
||||||
|
lim = ceil(3100. / mhz * secs);
|
||||||
|
rlim.rlim_cur = lim;
|
||||||
|
rlim.rlim_max = lim + 1;
|
||||||
|
if (setrlimit(RLIMIT_CPU, &rlim) == -1)
|
||||||
|
{
|
||||||
|
if (getrlimit(RLIMIT_CPU, &rlim) == -1)
|
||||||
|
return;
|
||||||
|
if (lim < rlim.rlim_cur)
|
||||||
|
{
|
||||||
|
rlim.rlim_cur = lim;
|
||||||
|
setrlimit(RLIMIT_CPU, &rlim);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
set_fsz_limit (long n)
|
||||||
|
{
|
||||||
|
struct rlimit rlim;
|
||||||
|
if (n <= 0) return;
|
||||||
|
if (IsWindows()) return;
|
||||||
|
rlim.rlim_cur = n;
|
||||||
|
rlim.rlim_max = n << 1;
|
||||||
|
if (setrlimit(RLIMIT_FSIZE, &rlim) == -1)
|
||||||
|
{
|
||||||
|
if (getrlimit(RLIMIT_FSIZE, &rlim) == -1)
|
||||||
|
return;
|
||||||
|
rlim.rlim_cur = n;
|
||||||
|
setrlimit(RLIMIT_FSIZE, &rlim);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
set_mem_limit (long n)
|
||||||
|
{
|
||||||
|
struct rlimit rlim = {n, n};
|
||||||
|
if (n <= 0) return;
|
||||||
|
if (IsWindows() || IsXnu()) return;
|
||||||
|
setrlimit(RLIMIT_AS, &rlim);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
set_pro_limit (long n)
|
||||||
|
{
|
||||||
|
struct rlimit rlim = {n, n};
|
||||||
|
if (n <= 0) return;
|
||||||
|
setrlimit(RLIMIT_NPROC, &rlim);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct sysinfo g_sysinfo;
|
||||||
|
|
||||||
|
__attribute__((__constructor__)) static void
|
||||||
|
get_sysinfo (void)
|
||||||
|
{
|
||||||
|
int e = errno;
|
||||||
|
sysinfo (&g_sysinfo);
|
||||||
|
errno = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool internet;
|
||||||
|
static char *promises;
|
||||||
|
|
||||||
/* POSIX:
|
/* POSIX:
|
||||||
Create a child process executing the command in ARGV.
|
Create a child process executing the command in ARGV.
|
||||||
Returns the PID or -1. */
|
Returns the PID or -1. */
|
||||||
pid_t
|
pid_t
|
||||||
child_execute_job (struct childbase *child, int good_stdin, char **argv)
|
child_execute_job (struct childbase *child,
|
||||||
|
int good_stdin,
|
||||||
|
char **argv,
|
||||||
|
bool is_build_rule)
|
||||||
{
|
{
|
||||||
const int fdin = good_stdin ? FD_STDIN : get_bad_stdin ();
|
const int fdin = good_stdin ? FD_STDIN : get_bad_stdin ();
|
||||||
struct dep *d;
|
struct dep *d;
|
||||||
|
bool strict;
|
||||||
bool sandboxed;
|
bool sandboxed;
|
||||||
|
bool unsandboxed;
|
||||||
struct child *c;
|
struct child *c;
|
||||||
|
unsigned long ipromises;
|
||||||
char pathbuf[PATH_MAX];
|
char pathbuf[PATH_MAX];
|
||||||
char outpathbuf[PATH_MAX];
|
char outpathbuf[PATH_MAX];
|
||||||
int fdout = FD_STDOUT;
|
int fdout = FD_STDOUT;
|
||||||
|
@ -1808,28 +1912,145 @@ child_execute_job (struct childbase *child, int good_stdin, char **argv)
|
||||||
if (stack_limit.rlim_cur)
|
if (stack_limit.rlim_cur)
|
||||||
setrlimit (RLIMIT_STACK, &stack_limit);
|
setrlimit (RLIMIT_STACK, &stack_limit);
|
||||||
|
|
||||||
g_strict = Vartoi (lookup_variable (STRING_SIZE_TUPLE (".STRICT")));
|
/* Tell build rules apart from $(shell foo). */
|
||||||
|
if (is_build_rule) {
|
||||||
intptr_t loc = (intptr_t)child; /* we can cast if it's on the heap ;_; */
|
|
||||||
if (!(GetStackAddr() < loc && loc < GetStackAddr() + GetStackSize())) {
|
|
||||||
c = (struct child *)child;
|
c = (struct child *)child;
|
||||||
} else {
|
} else {
|
||||||
c = 0;
|
c = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
sandboxed = (
|
internet = parse_bool (get_target_variable
|
||||||
!Vartoi (lookup_variable
|
(STRING_SIZE_TUPLE(".INTERNET"),
|
||||||
(STRING_SIZE_TUPLE(".UNSANDBOXED"))) &&
|
c ? c->file : 0, "0"));
|
||||||
(!c || !Vartoi (lookup_variable_in_set
|
|
||||||
(STRING_SIZE_TUPLE(".UNSANDBOXED"),
|
|
||||||
c->file->variables->set))) &&
|
|
||||||
(!c || !c->file->pat_variables ||
|
|
||||||
!Vartoi (lookup_variable_in_set
|
|
||||||
(STRING_SIZE_TUPLE(".UNSANDBOXED"),
|
|
||||||
c->file->pat_variables->set))));
|
|
||||||
|
|
||||||
/* resolve command into executable path */
|
unsandboxed = parse_bool (get_target_variable
|
||||||
if (!g_strict || !sandboxed)
|
(STRING_SIZE_TUPLE(".UNSANDBOXED"),
|
||||||
|
c ? c->file : 0, "0"));
|
||||||
|
|
||||||
|
if (c)
|
||||||
|
{
|
||||||
|
sandboxed = !unsandboxed;
|
||||||
|
strict = parse_bool (get_target_variable
|
||||||
|
(STRING_SIZE_TUPLE(".STRICT"),
|
||||||
|
c->file, "0"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sandboxed = false;
|
||||||
|
strict = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!unsandboxed)
|
||||||
|
{
|
||||||
|
promises = emptytonull (get_target_variable
|
||||||
|
(STRING_SIZE_TUPLE(".PLEDGE"),
|
||||||
|
c ? c->file : 0, 0));
|
||||||
|
if (promises)
|
||||||
|
promises = xstrdup (promises);
|
||||||
|
if (ParsePromises (promises, &ipromises))
|
||||||
|
{
|
||||||
|
OSS (error, NILF, "%s: invalid .PLEDGE string: %s",
|
||||||
|
argv[0], strerror (errno));
|
||||||
|
_Exit (127);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
promises = NULL;
|
||||||
|
ipromises = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DB (DB_JOBS,
|
||||||
|
(_("Executing %s for %s%s%s%s\n"),
|
||||||
|
argv[0], c ? c->file->name : "$(shell)",
|
||||||
|
sandboxed ? " with sandboxing" : " without sandboxing",
|
||||||
|
strict ? " in .STRICT mode" : "",
|
||||||
|
internet ? " with internet access" : ""));
|
||||||
|
|
||||||
|
/* [jart] Set cpu seconds quota. */
|
||||||
|
if ((s = get_target_variable (STRING_SIZE_TUPLE(".CPU"),
|
||||||
|
c ? c->file : 0, 0)))
|
||||||
|
{
|
||||||
|
int secs;
|
||||||
|
secs = atoi (s);
|
||||||
|
DB (DB_JOBS, (_("Setting cpu limit of %d seconds\n"), secs));
|
||||||
|
set_cpu_limit (secs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* [jart] Set virtual memory quota. */
|
||||||
|
if ((s = get_target_variable (STRING_SIZE_TUPLE(".MEMORY"),
|
||||||
|
c ? c->file : 0, 0)))
|
||||||
|
{
|
||||||
|
long bytes;
|
||||||
|
char buf[16];
|
||||||
|
if (!strchr (s, '%'))
|
||||||
|
bytes = sizetol (s, 1024);
|
||||||
|
else
|
||||||
|
bytes = strtod (s, 0) / 100. * g_sysinfo.totalram;
|
||||||
|
DB (DB_JOBS, (_("Setting virtual memory limit of %s\n"),
|
||||||
|
(FormatMemorySize (buf, bytes, 1024), buf)));
|
||||||
|
set_mem_limit (bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* [jart] Set file size limit. */
|
||||||
|
if ((s = get_target_variable (STRING_SIZE_TUPLE(".FSIZE"),
|
||||||
|
c ? c->file : 0, 0)))
|
||||||
|
{
|
||||||
|
long bytes;
|
||||||
|
char buf[16];
|
||||||
|
bytes = sizetol (s, 1000);
|
||||||
|
DB (DB_JOBS, (_("Setting file size limit of %s\n"),
|
||||||
|
(FormatMemorySize (buf, bytes, 1000), buf)));
|
||||||
|
set_fsz_limit (bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* [jart] Set process limit. */
|
||||||
|
if ((s = get_target_variable (STRING_SIZE_TUPLE(".NPROC"),
|
||||||
|
c ? c->file : 0, 0)))
|
||||||
|
{
|
||||||
|
int procs;
|
||||||
|
if ((procs = atoi (s)) > 0)
|
||||||
|
{
|
||||||
|
DB (DB_JOBS, (_("Setting process limit to %d + %d preexisting\n"),
|
||||||
|
procs, g_sysinfo.procs));
|
||||||
|
set_pro_limit (procs + g_sysinfo.procs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* [jart] Prevent builds from talking to the Internet. */
|
||||||
|
if (internet)
|
||||||
|
DB (DB_JOBS, (_("Allowing Internet access\n")));
|
||||||
|
else if (!(~ipromises & (1ul << PROMISE_INET)) &&
|
||||||
|
!(~ipromises & (1ul << PROMISE_DNS)))
|
||||||
|
DB (DB_JOBS, (_("Internet access will be blocked by pledge\n")));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
e = errno;
|
||||||
|
if (!nointernet())
|
||||||
|
DB (DB_JOBS, (_("Blocked Internet access with seccomp ptrace\n")));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (errno = EPERM)
|
||||||
|
{
|
||||||
|
errno = e;
|
||||||
|
DB (DB_JOBS, (_("Can't block Internet if already traced\n")));
|
||||||
|
}
|
||||||
|
else if (errno == ENOSYS)
|
||||||
|
{
|
||||||
|
errno = e;
|
||||||
|
DB (DB_JOBS, (_("Need SECCOMP ptrace() to block Internet\n")));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
OSS (error, NILF, "%s: failed to block internet access: %s",
|
||||||
|
argv[0], strerror (errno));
|
||||||
|
_Exit (127);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* [jart] Resolve command into executable path. */
|
||||||
|
if (!strict || !sandboxed)
|
||||||
{
|
{
|
||||||
if ((s = commandv (argv[0], pathbuf, sizeof (pathbuf))))
|
if ((s = commandv (argv[0], pathbuf, sizeof (pathbuf))))
|
||||||
argv[0] = s;
|
argv[0] = s;
|
||||||
|
@ -1841,15 +2062,13 @@ child_execute_job (struct childbase *child, int good_stdin, char **argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* [jart] sandbox command based on prerequisites */
|
/* [jart] Sandbox build rule commands based on prerequisites. */
|
||||||
if (c)
|
if (c)
|
||||||
{
|
{
|
||||||
errno = 0;
|
errno = 0;
|
||||||
if (sandboxed)
|
if (sandboxed)
|
||||||
{
|
{
|
||||||
DB (DB_JOBS, (_("Sandboxing %s\n"), c->file->name));
|
if (!strict && argv[0][0] == '/' && IsDynamicExecutable (argv[0]))
|
||||||
|
|
||||||
if (!g_strict && argv[0][0] == '/' && IsDynamicExecutable (argv[0]))
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* weaken sandbox if user is using dynamic shared lolbjects
|
* weaken sandbox if user is using dynamic shared lolbjects
|
||||||
|
@ -1883,6 +2102,8 @@ child_execute_job (struct childbase *child, int good_stdin, char **argv)
|
||||||
* only if the ape loader exists on a well-known path.
|
* only if the ape loader exists on a well-known path.
|
||||||
*/
|
*/
|
||||||
e = errno;
|
e = errno;
|
||||||
|
DB (DB_JOBS, (_("Unveiling %s with permissions %s\n"),
|
||||||
|
"/usr/bin/ape", "rx"));
|
||||||
if (unveil ("/usr/bin/ape", "rx") == -1)
|
if (unveil ("/usr/bin/ape", "rx") == -1)
|
||||||
{
|
{
|
||||||
char *s, *t;
|
char *s, *t;
|
||||||
|
@ -1902,15 +2123,15 @@ child_execute_job (struct childbase *child, int good_stdin, char **argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* unveil executable */
|
/* Unveil executable. */
|
||||||
RETURN_ON_ERROR (Unveil (argv[0], "rx"));
|
RETURN_ON_ERROR (Unveil (argv[0], "rx"));
|
||||||
|
|
||||||
/* unveil temporary directory */
|
/* Unveil temporary directory. */
|
||||||
if (c->tmpdir)
|
if (c->tmpdir)
|
||||||
RETURN_ON_ERROR (Unveil (c->tmpdir, "rwcx"));
|
RETURN_ON_ERROR (Unveil (c->tmpdir, "rwcx"));
|
||||||
|
|
||||||
/* unveil lazy mode files */
|
/* Unveil lazy mode files. */
|
||||||
if (!g_strict)
|
if (!strict)
|
||||||
{
|
{
|
||||||
RETURN_ON_ERROR (Unveil ("/tmp", "rwc"));
|
RETURN_ON_ERROR (Unveil ("/tmp", "rwc"));
|
||||||
RETURN_ON_ERROR (Unveil ("/dev/zero", "r"));
|
RETURN_ON_ERROR (Unveil ("/dev/zero", "r"));
|
||||||
|
@ -1922,6 +2143,50 @@ child_execute_job (struct childbase *child, int good_stdin, char **argv)
|
||||||
RETURN_ON_ERROR (Unveil ("/etc/hosts", "r"));
|
RETURN_ON_ERROR (Unveil ("/etc/hosts", "r"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Unveil .PLEDGE = tmppath. */
|
||||||
|
if (!strict && promises && (~ipromises & (1ul << PROMISE_TMPPATH)))
|
||||||
|
RETURN_ON_ERROR (Unveil ("/tmp", "rwc"));
|
||||||
|
|
||||||
|
/* Unveil .PLEDGE = vminfo. */
|
||||||
|
if (promises && (~ipromises & (1ul << PROMISE_VMINFO)))
|
||||||
|
{
|
||||||
|
RETURN_ON_ERROR (Unveil ("/proc/stat", "r"));
|
||||||
|
RETURN_ON_ERROR (Unveil ("/proc/meminfo", "r"));
|
||||||
|
RETURN_ON_ERROR (Unveil ("/proc/cpuinfo", "r"));
|
||||||
|
RETURN_ON_ERROR (Unveil ("/proc/diskstats", "r"));
|
||||||
|
RETURN_ON_ERROR (Unveil ("/proc/self/maps", "r"));
|
||||||
|
RETURN_ON_ERROR (Unveil ("/sys/devices/system/cpu", "r"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unveil .PLEDGE = tty. */
|
||||||
|
if (promises && (~ipromises & (1ul << PROMISE_TTY)))
|
||||||
|
{
|
||||||
|
RETURN_ON_ERROR (Unveil (ttyname(0), "rw"));
|
||||||
|
RETURN_ON_ERROR (Unveil ("/dev/tty", "rw"));
|
||||||
|
RETURN_ON_ERROR (Unveil ("/dev/console", "rw"));
|
||||||
|
RETURN_ON_ERROR (Unveil ("/etc/terminfo", "r"));
|
||||||
|
RETURN_ON_ERROR (Unveil ("/usr/lib/terminfo", "r"));
|
||||||
|
RETURN_ON_ERROR (Unveil ("/usr/share/terminfo", "r"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unveil .PLEDGE = dns. */
|
||||||
|
if (promises && (~ipromises & (1ul << PROMISE_DNS)))
|
||||||
|
{
|
||||||
|
RETURN_ON_ERROR (Unveil ("/etc/hosts", "r"));
|
||||||
|
RETURN_ON_ERROR (Unveil ("/etc/hostname", "r"));
|
||||||
|
RETURN_ON_ERROR (Unveil ("/etc/services", "r"));
|
||||||
|
RETURN_ON_ERROR (Unveil ("/etc/protocols", "r"));
|
||||||
|
RETURN_ON_ERROR (Unveil ("/etc/resolv.conf", "r"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unveil .PLEDGE = inet. */
|
||||||
|
if (promises && (~ipromises & (1ul << PROMISE_INET)))
|
||||||
|
RETURN_ON_ERROR (Unveil ("/etc/ssl/certs/ca-certificates.crt", "r"));
|
||||||
|
|
||||||
|
/* Unveil .PLEDGE = rpath. */
|
||||||
|
if (promises && (~ipromises & (1ul << PROMISE_INET)))
|
||||||
|
RETURN_ON_ERROR (Unveil ("/proc/filesystems", "r"));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* unveils target output file
|
* unveils target output file
|
||||||
*
|
*
|
||||||
|
@ -2017,6 +2282,20 @@ exec_command (char **argv, char **envp)
|
||||||
/* Be the user, permanently. */
|
/* Be the user, permanently. */
|
||||||
child_access ();
|
child_access ();
|
||||||
|
|
||||||
|
/* Restrict system calls. */
|
||||||
|
if (promises)
|
||||||
|
{
|
||||||
|
__pledge_mode = PLEDGE_PENALTY_RETURN_EPERM;
|
||||||
|
DB (DB_JOBS, (_("Pledging %s\n"), promises));
|
||||||
|
promises = xstrcat (promises, " prot_exec exec");
|
||||||
|
if (pledge (promises, promises))
|
||||||
|
{
|
||||||
|
OSS (error, NILF, "pledge(%s) failed: %s",
|
||||||
|
promises, strerror (errno));
|
||||||
|
_Exit (127);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Run the program. */
|
/* Run the program. */
|
||||||
environ = envp;
|
environ = envp;
|
||||||
execv (argv[0], argv);
|
execv (argv[0], argv);
|
||||||
|
|
2
third_party/make/job.h
vendored
2
third_party/make/job.h
vendored
|
@ -71,7 +71,7 @@ void start_waiting_jobs (void);
|
||||||
char **construct_command_argv (char *line, char **restp, struct file *file,
|
char **construct_command_argv (char *line, char **restp, struct file *file,
|
||||||
int cmd_flags, char** batch_file);
|
int cmd_flags, char** batch_file);
|
||||||
|
|
||||||
pid_t child_execute_job (struct childbase *child, int good_stdin, char **argv);
|
pid_t child_execute_job (struct childbase *, int, char **, bool);
|
||||||
|
|
||||||
#ifdef _AMIGA
|
#ifdef _AMIGA
|
||||||
void exec_command (char **argv) NORETURN;
|
void exec_command (char **argv) NORETURN;
|
||||||
|
|
50
third_party/make/main.c
vendored
50
third_party/make/main.c
vendored
|
@ -14,40 +14,36 @@ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
You should have received a copy of the GNU General Public License along with
|
You should have received a copy of the GNU General Public License along with
|
||||||
this program. If not, see <http://www.gnu.org/licenses/>. */
|
this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
/* clang-format off */
|
|
||||||
#include "third_party/make/makeint.inc"
|
#include "third_party/make/makeint.inc"
|
||||||
#include "third_party/make/os.h"
|
/**/
|
||||||
#include "third_party/make/filedef.h"
|
#include "third_party/make/filedef.h"
|
||||||
|
#include "third_party/make/os.h"
|
||||||
|
/**/
|
||||||
#include "third_party/make/dep.h"
|
#include "third_party/make/dep.h"
|
||||||
#include "third_party/make/variable.h"
|
|
||||||
#include "third_party/make/job.h"
|
#include "third_party/make/job.h"
|
||||||
|
#include "third_party/make/variable.h"
|
||||||
|
/**/
|
||||||
#include "third_party/make/commands.h"
|
#include "third_party/make/commands.h"
|
||||||
#include "third_party/make/rule.h"
|
|
||||||
#include "third_party/make/debug.h"
|
#include "third_party/make/debug.h"
|
||||||
#include "libc/runtime/stack.h"
|
#include "third_party/make/rule.h"
|
||||||
#include "libc/limits.h"
|
/**/
|
||||||
#include "libc/sysv/consts/sig.h"
|
|
||||||
#include "libc/log/log.h"
|
|
||||||
#include "libc/log/log.h"
|
|
||||||
#include "libc/log/log.h"
|
|
||||||
#include "libc/sock/sock.h"
|
|
||||||
#include "libc/dce.h"
|
|
||||||
#include "libc/calls/syscall_support-sysv.internal.h"
|
|
||||||
#include "libc/calls/struct/seccomp.h"
|
|
||||||
#include "libc/calls/struct/bpf.h"
|
|
||||||
#include "libc/sysv/consts/audit.h"
|
|
||||||
#include "libc/calls/struct/seccomp.h"
|
|
||||||
#include "libc/sysv/consts/pr.h"
|
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/macros.internal.h"
|
#include "libc/calls/struct/bpf.h"
|
||||||
#include "libc/stdio/stdio.h"
|
|
||||||
#include "libc/calls/struct/filter.h"
|
#include "libc/calls/struct/filter.h"
|
||||||
|
#include "libc/calls/struct/seccomp.h"
|
||||||
|
#include "libc/calls/syscall_support-sysv.internal.h"
|
||||||
|
#include "libc/dce.h"
|
||||||
|
#include "libc/limits.h"
|
||||||
|
#include "libc/macros.internal.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/stack.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/sock/sock.h"
|
||||||
#include "libc/log/log.h"
|
#include "libc/stdio/stdio.h"
|
||||||
#include "libc/log/log.h"
|
#include "libc/sysv/consts/audit.h"
|
||||||
|
#include "libc/sysv/consts/pr.h"
|
||||||
|
#include "libc/sysv/consts/sig.h"
|
||||||
#include "third_party/make/getopt.h"
|
#include "third_party/make/getopt.h"
|
||||||
|
// clang-format off
|
||||||
|
|
||||||
STATIC_STACK_SIZE(0x200000); // 2mb stack
|
STATIC_STACK_SIZE(0x200000); // 2mb stack
|
||||||
|
|
||||||
|
@ -985,10 +981,6 @@ main (int argc, char **argv, char **envp)
|
||||||
unsigned int syncing = 0;
|
unsigned int syncing = 0;
|
||||||
int argv_slots;
|
int argv_slots;
|
||||||
|
|
||||||
// block internet access
|
|
||||||
if (!getenv("MAKE_RESTARTS"))
|
|
||||||
nointernet ();
|
|
||||||
|
|
||||||
/* Useful for attaching debuggers, etc. */
|
/* Useful for attaching debuggers, etc. */
|
||||||
SPIN ("main-entry");
|
SPIN ("main-entry");
|
||||||
|
|
||||||
|
@ -2982,7 +2974,7 @@ print_version (void)
|
||||||
/* Do it only once. */
|
/* Do it only once. */
|
||||||
return;
|
return;
|
||||||
|
|
||||||
printf ("%sLandlock Make 1.1.1 (GNU Make %s)\n", precede, version_string);
|
printf ("%sLandlock Make 1.2 (GNU Make %s)\n", precede, version_string);
|
||||||
|
|
||||||
if (!remote_description || *remote_description == '\0')
|
if (!remote_description || *remote_description == '\0')
|
||||||
printf (_("%sBuilt for %s\n"), precede, make_host);
|
printf (_("%sBuilt for %s\n"), precede, make_host);
|
||||||
|
|
|
@ -254,7 +254,9 @@ static int OpMunmap(struct Machine *m, int64_t virt, uint64_t size) {
|
||||||
|
|
||||||
static int64_t OpMmap(struct Machine *m, int64_t virt, size_t size, int prot,
|
static int64_t OpMmap(struct Machine *m, int64_t virt, size_t size, int prot,
|
||||||
int flags, int fd, int64_t offset) {
|
int flags, int fd, int64_t offset) {
|
||||||
|
int e;
|
||||||
void *tmp;
|
void *tmp;
|
||||||
|
ssize_t rc;
|
||||||
uint64_t key;
|
uint64_t key;
|
||||||
VERBOSEF("MMAP%s %012lx %,ld %#x %#x %d %#lx", GetSimulated(), virt, size,
|
VERBOSEF("MMAP%s %012lx %,ld %#x %#x %d %#lx", GetSimulated(), virt, size,
|
||||||
prot, flags, fd, offset);
|
prot, flags, fd, offset);
|
||||||
|
@ -277,7 +279,13 @@ static int64_t OpMmap(struct Machine *m, int64_t virt, size_t size, int prot,
|
||||||
if (fd != -1 && !(flags & MAP_ANONYMOUS)) {
|
if (fd != -1 && !(flags & MAP_ANONYMOUS)) {
|
||||||
/* TODO: lazy file mappings */
|
/* TODO: lazy file mappings */
|
||||||
CHECK_NOTNULL((tmp = malloc(size)));
|
CHECK_NOTNULL((tmp = malloc(size)));
|
||||||
CHECK_EQ(size, pread(fd, tmp, size, offset));
|
for (e = errno;;) {
|
||||||
|
rc = pread(fd, tmp, size, offset);
|
||||||
|
if (rc != -1) break;
|
||||||
|
CHECK_EQ(EINTR, errno);
|
||||||
|
errno = e;
|
||||||
|
}
|
||||||
|
CHECK_EQ(size, rc);
|
||||||
VirtualRecvWrite(m, virt, tmp, size);
|
VirtualRecvWrite(m, virt, tmp, size);
|
||||||
free(tmp);
|
free(tmp);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7104,7 +7104,7 @@ static void HandleShutdown(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// this function coroutines with linenoise
|
// this function coroutines with linenoise
|
||||||
static int EventLoop(int ms) {
|
int EventLoop(int ms) {
|
||||||
struct timespec t;
|
struct timespec t;
|
||||||
DEBUGF("(repl) event loop");
|
DEBUGF("(repl) event loop");
|
||||||
while (!terminated) {
|
while (!terminated) {
|
||||||
|
|
|
@ -7,9 +7,9 @@
|
||||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||||
╚─────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────*/
|
||||||
#endif
|
#endif
|
||||||
#include "libc/intrin/bits.h"
|
|
||||||
#include "libc/calls/internal.h"
|
#include "libc/calls/internal.h"
|
||||||
#include "libc/fmt/itoa.h"
|
#include "libc/fmt/itoa.h"
|
||||||
|
#include "libc/intrin/bits.h"
|
||||||
#include "libc/macros.internal.h"
|
#include "libc/macros.internal.h"
|
||||||
#include "libc/runtime/memtrack.internal.h"
|
#include "libc/runtime/memtrack.internal.h"
|
||||||
#include "libc/stdio/stdio.h"
|
#include "libc/stdio/stdio.h"
|
||||||
|
@ -30,7 +30,7 @@ uint64_t last;
|
||||||
|
|
||||||
void plan2(uint64_t addr, uint64_t end, const char *name) {
|
void plan2(uint64_t addr, uint64_t end, const char *name) {
|
||||||
char sz[32];
|
char sz[32];
|
||||||
FormatMemorySize(sz, end-addr+1);
|
FormatMemorySize(sz, end-addr+1, 1024);
|
||||||
printf("%08x-%08x %-6s %s\n", addr>>16, end>>16, sz, name);
|
printf("%08x-%08x %-6s %s\n", addr>>16, end>>16, sz, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue