ref: 07665995b1973c612a8874badec060114393fa4d
parent: a374e069c66850906eaa241b8fcc0e312ff298bd
author: halfwit <michaelmisch1985@gmail.com>
date: Mon Apr 28 17:18:30 PDT 2025
Odd commit issue
--- a/kern/posix.c
+++ b/kern/posix.c
@@ -35,7 +35,6 @@
};
static pthread_key_t prdakey;
-//typedef void (*startfn)(int, char**);
Proc*
_getproc(void)
@@ -136,118 +135,7 @@
sched_yield();
}
-
-static void*
-trex(void *vp)
-{
- Proc *p;
- Tos tos;
- int argc;
-
- p = vp;
- tos.pid = p->pid;
- argc = nelem((char**)p->arg);
- if(pthread_setspecific(prdakey, p))
- panic("cannot setspecific");
- /* Our entrypoint moves forward to accomodate the trampoline code */
- start(up->bin->entry+(TRAMPSIZE*BY2SE), &tos, argc, p->arg);
- pexit("", 0);
- return 0;
-}
-
void
-osexec(Proc *p)
-{
- pthread_t pid;
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- if(pthread_create(&pid, &attr, trex, p)){
- oserrstr();
- panic("osexec: %r");
- }
- pthread_join(pid, nil);
- pthread_attr_destroy(&attr);
-}
-
-void
-osclrmem(void)
-{
- /* Clean up text, data, bss */
- if(up->bin->text)
- munmap((void*)up->bin->text, up->bin->ts);
- if(up->bin->data)
- munmap((void*)up->bin->data, up->bin->ds);
- if(up->bin->bss)
- munmap((void*)up->bin->bss, up->bin->bs);
-}
-
-void
-osbuildtext(Chan *tc)
-{
- int n;
- void *text;
-
- text = mmap(nil, up->bin->ts, PROT_WRITE|PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
- n = devtab[tc->type]->read(tc, text, up->bin->ts, 0);
- if(!text || n == 0)
- error("unable to set up text segment");
- /* Stash this in text for now, we will be moving and rewriting in the patch */
- up->bin->text = (uintptr)text;
-}
-
-void
-ospatchtext(void)
-{
- void *text, *final;
- int flag;
-
- /* Set up trampoline. Mach dependent */
- text = mallocz(TRAMPSIZE, 1);
- trampoline(text);
-
- flag = MAP_PRIVATE|MAP_ANONYMOUS;
-#ifdef __APPLE__
- flag |= MAP_JIT;
-#endif
- final = mmap(nil, up->bin->ts+TRAMPSIZE, PROT_WRITE|PROT_READ, flag, -1, 0);
- memmove(final, text, TRAMPSIZE);
- memmove(final+TRAMPSIZE, (void*)up->bin->text, up->bin->ts);
- if(!final)
- error("unable to set up text segment with trampoline");
-
- /* Patch. Mach dependent */
- if(patch(final-TRAMPSIZE, up->bin->ts) < 0)
- error("unable to patch syscalls");
- if(mprotect((void*)up->bin->text, up->bin->ts+TRAMPSIZE, PROT_EXEC) != 0)
- error("Unable to mprotect: %r");
- up->bin->text = (uintptr)final;
-}
-
-void
-osbuilddata(Chan *tc)
-{
- int n;
- void *data;
-
- data = mmap((void*)up->bin->data, up->bin->ds, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
- n = devtab[tc->type]->read(tc, data, up->bin->ds, up->bin->ts);
- if(!data || n == 0)
- error("unable to set up data segment");
- up->bin->data = (uintptr)data;
-}
-
-void
-osbuildbss(Chan *tc)
-{
- void *bss;
- // BSS - set it up in READ/WRITE
- bss = mmap((void*)up->bin->bss, up->bin->bs, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
- if(!bss)
- error("unable to set up bss segment");
- up->bin->bss = (uintptr)bss;
-}
-
-void
osexit(void)
{
pthread_setspecific(prdakey, 0);
@@ -360,6 +248,39 @@
return snprint(status, nstatus, "%d 0 0 0 'signal: %d'", pid, s);
}
return snprint(status, nstatus, "%d 0 0 0 'odd status: 0x%x'", pid, s);
+}
+
+void
+osclrmem(uintptr mem, uintptr ms)
+{
+ if(mem)
+ munmap((void*)mem, ms);
+}
+
+void *
+osbuildmem(Chan *tc, uintptr ts, uintptr ds, uintptr bss, int offset)
+{
+ int n;
+ void *exec, *binary;
+
+ /* Read in initial datum */
+ exec = mallocz(ts+ds, 1);
+ n = devtab[tc->type]->read(tc, exec, ts+ds, offset);
+ if(!exec || n < (ts+ds))
+ error("read error");
+
+ /* Contiguous memory block for text/data/bss */
+ binary = mmap(nil, UTZERO+n+bss, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+ if(binary == MAP_FAILED)
+ error("Failed: %r");
+
+ /* Mark text portion executable */
+ memcpy(binary+UTZERO, exec, n);
+ if(mprotect(binary+UTZERO, ts, PROT_EXEC|PROT_READ) != 0)
+ error("Unable to mprotect: %r");
+
+ free(exec);
+ return binary;
}
int
--- a/kern/sysproc.c
+++ b/kern/sysproc.c
@@ -1,213 +1,218 @@
-#include "u.h"
-#include "lib.h"
-#include "dat.h"
-#include "fns.h"
-#include "error.h"
-#include "user.h"
-#include "mem.h"
-#include <a.out.h>
-#include <signal.h>
-#include <sys/mman.h>
+#include "u.h"
+#include "lib.h"
+#include "dat.h"
+#include "fns.h"
+#include "error.h"
+#include "user.h"
+#include "mem.h"
+#include <a.out.h>
+#include <signal.h>
+#include <sys/mman.h>
+#include <setjmp.h>
#undef rfork
+jmp_buf exec_jmp;
+typedef void (*Entry)(int, char**);
+
static void
nop(int x)
{
- USED(x);
+ USED(x);
}
+static void
+sigsegv(int sig)
+{
+ print("Segfaultin'\n");
+ longjmp(exec_jmp, 2);
+}
+
+static void
+sigquit(int sig)
+{
+ print("Sigquittin'\n");
+ longjmp(exec_jmp, 1);
+}
+
+static void
+sigsys(int sig)
+{
+ print("We here!!! sig %d\n", sig);
+}
+
int
sysrfork(int flags)
{
- int pid, status;
- int p[2];
- int n;
- char buf[128], *q;
- extern char **environ;
- struct sigaction oldchld;
+ int pid, status;
+ int p[2];
+ int n;
+ char buf[128], *q;
+ extern char **environ;
+ struct sigaction oldchld;
- memset(&oldchld, 0, sizeof oldchld);
+ memset(&oldchld, 0, sizeof oldchld);
- if((flags&(RFPROC|RFFDG|RFMEM)) == (RFPROC|RFFDG)){
- /* check other flags before we commit */
- flags &= ~(RFPROC|RFFDG|RFENVG);
- n = (flags & ~(RFNOTEG|RFNAMEG|RFNOWAIT|RFCENVG));
- if(n){
- werrstr("unknown flags %08ux in rfork", n);
- return -1;
- }
- if(flags&RFNOWAIT){
- sigaction(SIGCHLD, nil, &oldchld);
- signal(SIGCHLD, nop);
- if(pipe(p) < 0)
- return -1;
- }
- pid = fork();
- if(pid == -1)
- return -1;
- if(flags&RFNOWAIT){
- flags &= ~RFNOWAIT;
- if(pid){
- /*
- * Parent - wait for child to fork wait-free child.
- * Then read pid from pipe. Assume pipe buffer can absorb the write.
- */
- close(p[1]);
- status = 0;
- if(wait4(pid, &status, 0, 0) < 0){
- werrstr("pipe dance - wait4 - %r");
- close(p[0]);
- return -1;
- }
- n = readn(p[0], buf, sizeof buf-1);
- close(p[0]);
- if(!WIFEXITED(status) || WEXITSTATUS(status)!=0 || n <= 0){
- if(!WIFEXITED(status))
- werrstr("pipe dance - !exited 0x%ux", status);
- else if(WEXITSTATUS(status) != 0)
- werrstr("pipe dance - non-zero status 0x%ux", status);
- else if(n < 0)
- werrstr("pipe dance - pipe read error - %r");
- else if(n == 0)
- werrstr("pipe dance - pipe read eof");
- else
- werrstr("pipe dance - unknown failure");
- return -1;
- }
- buf[n] = 0;
- if(buf[0] == 'x'){
- werrstr("%s", buf+2);
- return -1;
- }
- pid = strtol(buf, &q, 0);
- }else{
- /*
- * Child - fork a new child whose wait message can't
- * get back to the parent because we're going to exit!
- */
- signal(SIGCHLD, SIG_IGN);
- close(p[0]);
- pid = fork();
- if(pid){
- /* Child parent - send status over pipe and exit. */
- if(pid > 0)
- fprint(p[1], "%d", pid);
- else
- fprint(p[1], "x %r");
- close(p[1]);
- _exit(0);
- }else{
- /* Child child - close pipe. */
- close(p[1]);
- }
- }
- sigaction(SIGCHLD, &oldchld, nil);
- }
- if(pid != 0)
- return pid;
- if(flags&RFCENVG)
- if(environ)
- *environ = nil;
- }
- if(flags&RFPROC){
- werrstr("cannot use rfork for shared memory -- use libthread");
- return -1;
- }
- if(flags&RFNAMEG){
- /* XXX set $NAMESPACE to a new directory */
- flags &= ~RFNAMEG;
- }
- if(flags&RFNOTEG){
- setpgid(0, getpid());
- flags &= ~RFNOTEG;
- }
- if(flags&RFNOWAIT){
- werrstr("cannot use RFNOWAIT without RFPROC");
- return -1;
- }
- if(flags){
- werrstr("unknown flags %08ux in rfork", flags);
- return -1;
- }
- return 0;
-}
+ if((flags&(RFPROC|RFFDG|RFMEM)) == (RFPROC|RFFDG)){
+ flags &= ~(RFPROC|RFFDG|RFENVG);
+ n = (flags & ~(RFNOTEG|RFNAMEG|RFNOWAIT|RFCENVG));
+ if(n){
+ werrstr("unknown flags %08ux in rfork", n);
+ return -1;
+ }
+ if(flags&RFNOWAIT){
+ sigaction(SIGCHLD, nil, &oldchld);
+ signal(SIGCHLD, nop);
+ if(pipe(p) < 0)
+ return -1;
+ }
+ pid = fork();
+ if(pid == -1)
+ return -1;
+ if(flags&RFNOWAIT){
+ flags &= ~RFNOWAIT;
+ if(pid){
+ close(p[1]);
+ status = 0;
+ if(wait4(pid, &status, 0, 0) < 0){
+ werrstr("pipe dance - wait4 - %r");
+ close(p[0]);
+ return -1;
+ }
+ n = readn(p[0], buf, sizeof buf-1);
+ close(p[0]);
+ if(!WIFEXITED(status) || WEXITSTATUS(status)!=0 || n <= 0){
+ if(!WIFEXITED(status))
+ werrstr("pipe dance - !exited 0x%ux", status);
+ else if(WEXITSTATUS(status) != 0)
+ werrstr("pipe dance - non-zero status 0x%ux", status);
+ else if(n < 0)
+ werrstr("pipe dance - pipe read error - %r");
+ else if(n == 0)
+ werrstr("pipe dance - pipe read eof");
+ else
+ werrstr("pipe dance - unknown failure");
+ return -1;
+ }
+ buf[n] = 0;
+ if(buf[0] == 'x'){
+ werrstr("%s", buf+2);
+ return -1;
+ }
+ pid = strtol(buf, &q, 0);
+ }else{
+ signal(SIGCHLD, SIG_IGN);
+ close(p[0]);
+ pid = fork();
+ if(pid){
+ if(pid > 0)
+ fprint(p[1], "%d", pid);
+ else
+ fprint(p[1], "x %r");
+ close(p[1]);
+ _exit(0);
+ }else{
+ close(p[1]);
+ }
+ }
+ sigaction(SIGCHLD, &oldchld, nil);
+ }
+ if(pid != 0)
+ return pid;
+ if(flags&RFCENVG)
+ if(environ)
+ *environ = nil;
+ }
+ if(flags&RFPROC){
+ werrstr("cannot use rfork for shared memory -- use libthread");
+ return -1;
+ }
+ if(flags&RFNAMEG){
+ flags &= ~RFNAMEG;
+ }
+ if(flags&RFNOTEG){
+ setpgid(0, getpid());
+ flags &= ~RFNOTEG;
+ }
+ if(flags&RFNOWAIT){
+ werrstr("cannot use RFNOWAIT without RFPROC");
+ return -1;
+ }
+ if(flags){
+ werrstr("unknown flags %08ux in rfork", flags);
+ return -1;
+ }
+ return 0;
+}
static int
shargs(char *s, int n, char **ap, int nap)
{
- char *p;
- int i;
+ char *p;
+ int i;
- if(n <= 2 || s[0] != '#' || s[1] != '!')
- return -1;
- s += 2;
- n -= 2; /* skip #! */
- if((p = memchr(s, '\n', n)) == nil)
- return 0;
- *p = 0;
- i = tokenize(s, ap, nap-1);
- ap[i] = nil;
- return i;
+ if(n <= 2 || s[0] != '#' || s[1] != '!')
+ return -1;
+ s += 2;
+ n -= 2;
+ if((p = memchr(s, '\n', n)) == nil)
+ return 0;
+ *p = 0;
+ i = tokenize(s, ap, nap-1);
+ ap[i] = nil;
+ return i;
}
ulong
beswal(ulong l)
{
- uchar *p;
-
- p = (uchar*)&l;
- return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
+ uchar *p;
+ p = (uchar*)&l;
+ return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
}
uvlong
beswav(uvlong v)
{
- uchar *p;
-
- p = (uchar*)&v;
- return ((uvlong)p[0]<<56) | ((uvlong)p[1]<<48) | ((uvlong)p[2]<<40)
- | ((uvlong)p[3]<<32) | ((uvlong)p[4]<<24)
- | ((uvlong)p[5]<<16) | ((uvlong)p[6]<<8)
- | (uvlong)p[7];
+ uchar *p;
+ p = (uchar*)&v;
+ return ((uvlong)p[0]<<56) | ((uvlong)p[1]<<48) | ((uvlong)p[2]<<40)
+ | ((uvlong)p[3]<<32) | ((uvlong)p[4]<<24)
+ | ((uvlong)p[5]<<16) | ((uvlong)p[6]<<8)
+ | (uvlong)p[7];
}
void
evenaddr(uintptr addr)
{
- if(addr & 3){
- postnote(up, 1, "sys: odd address", NDebug);
- error(Ebadarg);
- }
+ if(addr & 3){
+ postnote(up, 1, "sys: odd address", NDebug);
+ error(Ebadarg);
+ }
}
-/*
- * &s[0] is known to be a valid address.
- */
void*
vmemchr(void *s, int c, ulong n)
{
- uintptr a;
- ulong m, i;
- void *t;
+ uintptr a;
+ ulong m, i;
+ void *t;
- i = n;
- a = (uintptr)s;
- for(;;){
- m = BY2PG - (a & (BY2PG-1));
- if(i <= m)
- break;
- /* spans pages; handle this page */
- t = memchr((void*)a, c, m);
- if(t != nil)
- return t;
- a += m;
- i -= m;
- if(a < KZERO)
- validaddr(a, 1, 0);
- }
- /* fits in one page */
- return memchr((void*)a, c, i);
+ i = n;
+ a = (uintptr)s;
+ for(;;){
+ m = BY2PG - (a & (BY2PG-1));
+ if(i <= m)
+ break;
+ t = memchr((void*)a, c, m);
+ if(t != nil)
+ return t;
+ a += m;
+ i -= m;
+ if(a < KZERO)
+ validaddr(a, 1, 0);
+ }
+ return memchr((void*)a, c, i);
}
#undef read
@@ -214,144 +219,119 @@
int
sysexec(int argc, char **argv)
{
- union {
- struct {
- Exec ex;
- uvlong hdr[1];
- } ehdr;
- char buf[256];
- } u;
+ union {
+ struct {
+ Exec ex;
+ uvlong hdr[1];
+ } ehdr;
+ char buf[256];
+ } u;
- char line[256];
- char *progarg[32+1];
- char *file, *elem;
- Chan *tc;
- ulong magic;
- uintptr align, bssend;
- int n, indir;
+ char line[256];
+ char *progarg[32+1];
+ char *file, *elem;
+ void *base;
+ Chan *tc;
+ Tos tos;
+ ulong magic;
+ uintptr t, b, entry, text, data, bss, align;
+ int n, indir;
- elem = nil;
- align = BY2PG-1;
- indir = 0;
- file = argv[0];
- up->bin = mallocz(sizeof(Binary*), 1);
+ elem = nil;
+ align = BY2PG-1;
+ indir = 0;
+ file = argv[0];
- for(;;){
- tc = namec(file, Aopen, OEXEC, 0);
- if(waserror()){
- cclose(tc);
- nexterror();
- }
- if(!indir)
- kstrdup(&elem, up->genbuf);
- // TODO: Triple check this for accurate text/entry. Ensure they are right, our ts should not be the same each time, for example
- n = devtab[tc->type]->read(tc, u.buf, sizeof(u.buf), 0);
- if (n >= sizeof(Exec)){
- magic = beswal(u.ehdr.ex.magic);
- if(magic & AOUT_MAGIC) {
+ for(;;){
+ tc = namec(file, Aopen, OEXEC, 0);
+ if(waserror()){
+ cclose(tc);
+ nexterror();
+ }
+ if(!indir)
+ kstrdup(&elem, up->genbuf);
+ n = devtab[tc->type]->read(tc, u.buf, sizeof(u.buf), 0);
+ if (n >= sizeof(Exec)){
+ magic = beswal(u.ehdr.ex.magic);
+ if(magic & AOUT_MAGIC) {
if(magic & HDR_MAGIC){
- if(n < sizeof(u.ehdr))
- error(Ebadexec);
- up->bin->entry = beswav(u.ehdr.hdr[0]);
- up->bin->ts = UTZERO+sizeof(u.ehdr);
- } else {
- up->bin->entry = beswal(u.ehdr.ex.entry);
- up->bin->ts = UTZERO+sizeof(Exec);
- }
- if(up->bin->entry < up->bin->ts)
+ if(n < sizeof(u.ehdr))
+ error(Ebadexec);
+ entry = beswav(u.ehdr.hdr[0]);
+ text = UTZERO+sizeof(u.ehdr);
+ } else {
+ entry = beswal(u.ehdr.ex.entry);
+ text = UTZERO+sizeof(u.ehdr);
+ }
+ if(entry < text)
+ error(Ebadexec);
+ text += beswal(u.ehdr.ex.text);
+ if(text <= entry || text >= (USTKTOP-USTKSIZE))
error(Ebadexec);
+ switch(magic){
+ case S_MAGIC:
+ align = 0x1fffff;
+ break;
+ case P_MAGIC:
+ case V_MAGIC:
+ align = 0x3fff;
+ break;
+ case R_MAGIC:
+ align = 0xffff;
+ break;
+ }
+ break;
+ }
+ }
+ if(indir++)
+ error(Ebadexec);
- up->bin->ts += beswal(u.ehdr.ex.text);
- if(up->bin->ts <= up->bin->entry || up->bin->ts >= (uintptr)(USTKTOP-USTKSIZE))
- error(Ebadexec);
- switch(magic){
- case S_MAGIC: /* 2MB segment alignment for amd64 */
- align = 0x1fffff;
- break;
- case P_MAGIC: /* 16K segment alignment for spim */
- case V_MAGIC: /* 16K segment alignment for mips */
- align = 0x3fff;
- break;
- case R_MAGIC: /* 64K segment alignment for arm64 */
- align = 0xffff;
- break;
- }
- up->arg = argv;
- argv[argc] = nil;
- break; /* for binary */
- }
- }
- if(indir++)
- error(Ebadexec);
+ memmove(line, u.buf, sizeof(u.buf));
+ n = shargs(line, n, progarg, nelem(progarg));
+ if(n < 1)
+ error(Ebadexec);
+ progarg[n++] = file;
+ progarg[n] = nil;
+ file = progarg[0];
+ progarg[0] = elem;
+ poperror();
+ cclose(tc);
+ }
- /* Process #!/bin/sh args */
- memmove(line, u.buf, n);
- n = shargs(line, n, progarg, nelem(progarg));
- if(n < 1)
- error(Ebadexec);
+ entry -= sizeof(u.ehdr);
+ text = beswal(u.ehdr.ex.text);
+ data = beswal(u.ehdr.ex.data);
+ bss = beswal(u.ehdr.ex.bss);
- progarg[n++] = file;
- progarg[n] = nil;
- argv++;
- file = progarg[0];
- progarg[0] = elem;
- strcpy(up->text, elem);
- poperror();
- cclose(tc);
- // Check the actual sysproc, there's some missing bits here still
- up->arg = progarg;
- }
+ /* Set up text, data, and bss. OS dependent. */
+ base = osbuildmem(tc, text, data, bss, sizeof(u.ehdr));
+ b = ((uintptr)base + align) & ~align;
- up->bin->ds = beswal(u.ehdr.ex.data);
- up->bin->bs = beswal(u.ehdr.ex.bss);
- up->bin->text = align;
- up->bin->ts -= UTZERO;
- align = BY2PG-1;
- up->bin->data = ((up->bin->ts+align) & ~align) / BY2WD;
- bssend = up->bin->ts + up->bin->ds + up->bin->bs;
- up->bin->bss = ((bssend + align) & ~align) / BY2WD;
- up->bin->bss -= up->bin->bs;
+ poperror();
+ cclose(tc);
- /* Set up text, data, and bss. Patch syscalls. OS dependent. */
- osbuildtext(tc);
- if(waserror()){
- print("%s\n", up->errstr);
- osclrmem();
- nexterror();
- }
- ospatchtext();
- if(waserror()){
- print("%s\n", up->errstr);
- osclrmem();
- nexterror();
- }
- osbuilddata(tc);
- if(waserror()){
- print("%s\n", up->errstr);
- osclrmem();
- nexterror();
- }
- osbuildbss(tc);
- if(waserror()){
- print("%s\n", up->errstr);
- osclrmem();
- nexterror();
- }
+ /* Meaningful signals to us */
+ signal(SIGSEGV, sigsegv);
+ signal(SIGQUIT, sigquit);
+ signal(SIGINT, sigquit);
+ signal(SIGSYS, sigsys);
- /* Run binary. OS dependent. */
- osexec(up);
+ switch(setjmp(exec_jmp)) {
+ case 0:
+ tos.pid = getpid();
+ print("Base %ux, Entry %ux, Text %ux\n", b, entry, text);
+ start(b+entry, &tos, argc, argv);
+ longjmp(exec_jmp, 1);
+ break;
+ case 1:
+ print("Normal exit\n");
+ osclrmem((uintptr)base, text+data+bss);
+ return 0;
+ case 2:
+ print("SIGSEGV!\n");
+ return -1;
+ }
- print("Exiting sysproc\n");
- /* Clean up */
- osclrmem();
- up->arg = nil;
- free(up->bin);
-
- poperror(); /* osbuildtext */
- poperror(); /* ospatchtext */
- poperror(); /* osbuilddata */
- poperror(); /* osbuildbss */
- cclose(tc);
-
- return 0;
+ /* Can't happen */
+ return 1;
}
\ No newline at end of file