[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [bug-gawk] Sandbox improvements
From: |
arnold |
Subject: |
Re: [bug-gawk] Sandbox improvements |
Date: |
Mon, 06 May 2019 01:06:49 -0600 |
User-agent: |
Heirloom mailx 12.5 7/5/10 |
Hi.
Nolan Woods <address@hidden> wrote:
> Hi, thank you for such a great tool.
>
> The sandbox functionality of gawk is great, but it needs significant
> improvements.
>
> Even with sandbox, arbitrary files can be read using the following code:
>
> BEGIN {
> ARGV[ARGC]="/etc/passwd";
> ARGC++;
> }1
>
> Argument rewriting is an important feature as it allows controlling
> execution (like the example rewind() function).
I thought about this some more and decided to see if I could disable
this in sandbox mode. The diff is below. I will get this into git soon.
Thanks,
Arnold
------------------------------------------------------------
diff --git a/awk.h b/awk.h
index 19a5eb5f..8d87fc6a 100644
--- a/awk.h
+++ b/awk.h
@@ -1402,6 +1402,7 @@ extern NODE *do_asort(int nargs);
extern NODE *do_asorti(int nargs);
extern unsigned long (*hash)(const char *s, size_t len, unsigned long hsize,
size_t *code);
extern void init_env_array(NODE *env_node);
+extern void init_argv_array(NODE *argv_node, NODE *shadow_node);
/* awkgram.c */
extern NODE *variable(int location, char *name, NODETYPE type);
extern int parse_program(INSTRUCTION **pcode, bool from_eval);
diff --git a/cint_array.c b/cint_array.c
index 08815e4e..0dff525b 100644
--- a/cint_array.c
+++ b/cint_array.c
@@ -73,6 +73,24 @@ const array_funcs_t cint_array_func = {
(afunc_t) 0,
};
+
+static NODE **argv_store(NODE *symbol, NODE *subs);
+
+/* special case for ARGV in sandbox mode */
+const array_funcs_t argv_array_func = {
+ "argv",
+ cint_array_init,
+ is_uinteger,
+ cint_lookup,
+ cint_exists,
+ cint_clear,
+ cint_remove,
+ cint_list,
+ cint_copy,
+ cint_dump,
+ argv_store,
+};
+
static inline int cint_hash(long k);
static inline NODE **cint_find(NODE *symbol, long k, int h1);
@@ -1230,3 +1248,65 @@ leaf_print(NODE *array, size_t bi, int indent_level)
(unsigned long) array->table_size);
}
#endif
+
+static NODE *argv_shadow_array = NULL;
+
+/* argv_store --- post assign function for ARGV in sandbox mode */
+
+static NODE **
+argv_store(NODE *symbol, NODE *subs)
+{
+ NODE **val = cint_exists(symbol, subs);
+ NODE *newval = *val;
+ char *cp;
+
+ if ((cp = strchr(newval->stptr, '=')) == NULL) {
+ if (! in_array(argv_shadow_array, newval))
+ fatal(_("cannot add a new file (%.*s) to ARGV in
sandbox mode"),
+ (int) newval->stlen, newval->stptr);
+ } else {
+ // check if it's a valid variable assignment
+ bool badvar = false;
+ char *arg = newval->stptr;
+ char *cp2;
+
+ *cp = '\0'; // temporarily
+
+ if (! is_letter((unsigned char) arg[0]))
+ badvar = true;
+ else
+ for (cp2 = arg+1; *cp2; cp2++)
+ if (! is_identchar((unsigned char) *cp2) &&
*cp2 != ':') {
+ badvar = true;
+ break;
+ }
+
+ // further checks
+ if (! badvar) {
+ char *cp = strchr(arg, ':');
+ if (cp && (cp[1] != ':' || strchr(cp + 2, ':') != NULL))
+ badvar = true;
+ }
+ *cp = '='; // restore the '='
+
+ if (badvar && ! in_array(argv_shadow_array, newval))
+ fatal(_("cannot add a new file (%.*s) to ARGV in
sandbox mode"),
+ (int) newval->stlen, newval->stptr);
+
+ // otherwise, badvar is false, let it through as variable
assignment
+ }
+ return val;
+}
+
+/* init_argv_array --- set up the pointers for ARGV in sandbox mode. A bit
hacky. */
+
+void
+init_argv_array(NODE *argv_node, NODE *shadow_node)
+{
+ /* If POSIX simply don't reset the vtable and things work as before */
+ if (! do_sandbox)
+ return;
+
+ argv_node->array_funcs = & argv_array_func;
+ argv_shadow_array = shadow_node;
+}
diff --git a/main.c b/main.c
index 8327cc74..1f23e57c 100644
--- a/main.c
+++ b/main.c
@@ -749,6 +749,7 @@ init_args(int argc0, int argc, const char *argv0, char
**argv)
{
int i, j;
NODE *sub, *val;
+ NODE *shadow_node = NULL;
ARGV_node = install_symbol(estrdup("ARGV", 4), Node_var_array);
sub = make_number(0.0);
@@ -756,15 +757,32 @@ init_args(int argc0, int argc, const char *argv0, char
**argv)
val->flags |= USER_INPUT;
assoc_set(ARGV_node, sub, val);
+ if (do_sandbox) {
+ shadow_node = make_array();
+ sub = make_string(argv0, strlen(argv0));
+ val = make_number(0.0);
+ assoc_set(shadow_node, sub, val);
+ }
+
+
for (i = argc0, j = 1; i < argc; i++, j++) {
sub = make_number((AWKNUM) j);
val = make_string(argv[i], strlen(argv[i]));
val->flags |= USER_INPUT;
assoc_set(ARGV_node, sub, val);
+
+ if (do_sandbox) {
+ sub = make_string(argv[i], strlen(argv[i]));
+ val = make_number(0.0);
+ assoc_set(shadow_node, sub, val);
+ }
}
ARGC_node = install_symbol(estrdup("ARGC", 4), Node_var);
ARGC_node->var_value = make_number((AWKNUM) j);
+
+ if (do_sandbox)
+ init_argv_array(ARGV_node, shadow_node);
}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- Re: [bug-gawk] Sandbox improvements,
arnold <=