ref: f909f803bc9daf7c78cb46684800a69ac7fe39ae
parent: b0cc8135ed4ad90ac54215ae064cde638a0a2953
author: Ori Bernstein <ori@eigenstate.org>
date: Mon Jul 25 00:48:44 EDT 2022
sysproc: raise limit on #! lines, and allow quoted args Our #! line length is very short, and the naïve quoting makes it difficult to pass more complicated arguments to the programs being run. This is fine for simple interpreters, but it's often useful to pass arguments to more complicated interpreters like auth/box or awk. This change raises the limit, but also switches to tokenizing via tokenize(2), rather than hand rolled whitespace splitting. The limits chosen are arbitrary, but they leave approximately 3 KiB of stack space on 386, and 13k on amd64. This is a lot of stack used, but it should leave enough for fairly deep devtab chan stacks.
--- a/sys/man/2/exec
+++ b/sys/man/2/exec
@@ -67,6 +67,11 @@
ls | mc
.EE
.PP
+There may be up to 256 bytes of arguments passed to the interpreter.
+These are tokenized into up to 32 arguments by
+.IR tokenize (2)
+before being passed as the interpreters argument vector.
+.PP
When a C program is executed,
it is called as follows:
.IP
--- a/sys/src/9/port/sysproc.c
+++ b/sys/src/9/port/sysproc.c
@@ -243,8 +243,9 @@
}
static int
-shargs(char *s, int n, char **ap)
+shargs(char *s, int n, char **ap, int nap)
{
+ char *p;
int i;
if(n <= 2 || s[0] != '#' || s[1] != '!')
@@ -251,27 +252,10 @@
return -1;
s += 2;
n -= 2; /* skip #! */
- for(i=0;; i++){
- if(i >= n)
- return 0;
- if(s[i]=='\n')
- break;
- }
- s[i] = 0;
-
- i = 0;
- for(;;) {
- while(*s==' ' || *s=='\t')
- s++;
- if(*s == 0)
- break;
- ap[i++] = s++;
- while(*s && *s!=' ' && *s!='\t')
- s++;
- if(*s == 0)
- break;
- *s++ = 0;
- }
+ if((p = memchr(s, '\n', n)) == nil)
+ return 0;
+ *p = 0;
+ i = tokenize(s, ap, nap-1);
ap[i] = nil;
return i;
}
@@ -300,12 +284,15 @@
uintptr
sysexec(va_list list)
{
- struct {
- Exec;
- uvlong hdr[1];
- } ehdr;
- char line[sizeof(ehdr)];
- char *progarg[sizeof(line)/2+1];
+ union {
+ struct {
+ Exec;
+ uvlong hdr[1];
+ } ehdr;
+ char buf[256];
+ } u;
+ char line[256];
+ char *progarg[32+1];
volatile char *args, *elem, *file0;
char **argv, **argp, **argp0;
char *a, *e, *charp, *file;
@@ -353,22 +340,22 @@
if(!indir)
kstrdup(&elem, up->genbuf);
- n = devtab[tc->type]->read(tc, &ehdr, sizeof(ehdr), 0);
+ n = devtab[tc->type]->read(tc, u.buf, sizeof(u.buf), 0);
if(n >= sizeof(Exec)) {
- magic = beswal(ehdr.magic);
+ magic = beswal(u.ehdr.magic);
if(magic == AOUT_MAGIC) {
if(magic & HDR_MAGIC) {
- if(n < sizeof(ehdr))
+ if(n < sizeof(u.ehdr))
error(Ebadexec);
- entry = beswav(ehdr.hdr[0]);
- text = UTZERO+sizeof(ehdr);
+ entry = beswav(u.ehdr.hdr[0]);
+ text = UTZERO+sizeof(u.ehdr);
} else {
- entry = beswal(ehdr.entry);
+ entry = beswal(u.ehdr.entry);
text = UTZERO+sizeof(Exec);
}
if(entry < text)
error(Ebadexec);
- text += beswal(ehdr.text);
+ text += beswal(u.ehdr.text);
if(text <= entry || text >= (USTKTOP-USTKSIZE))
error(Ebadexec);
@@ -393,8 +380,8 @@
/*
* Process #! /bin/sh args ...
*/
- memmove(line, &ehdr, n);
- n = shargs(line, n, progarg);
+ memmove(line, u.buf, n);
+ n = shargs(line, n, progarg, nelem(progarg));
if(n < 1)
error(Ebadexec);
/*
@@ -411,8 +398,8 @@
t = (text+align) & ~align;
text -= UTZERO;
- data = beswal(ehdr.data);
- bss = beswal(ehdr.bss);
+ data = beswal(u.ehdr.data);
+ bss = beswal(u.ehdr.bss);
align = BY2PG-1;
d = (t + data + align) & ~align;
bssend = t + data + bss;
--
⑨