bug-gawk
[Top][All Lists]
Advanced

[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);
 }
 
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]