[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: |
Fri, 14 Jun 2019 03:28:08 -0600 |
User-agent: |
Heirloom mailx 12.5 7/5/10 |
I will make a 5.0.1 release sometime soon. At that point I will put
a tag into the repo.
Thanks,
Arnold
Nolan Woods <address@hidden> wrote:
> Thanks for fixing this!
>
>
> Is it possible for you to create a 5.0.1 tag in your repo for autobuilders to
> trigger?
>
>
> Thanks again
>
> ________________________________
> From: address@hidden <address@hidden>
> Sent: Monday, May 6, 2019 12:06:49 AM
> To: Nolan Woods; address@hidden
> Subject: Re: [bug-gawk] Sandbox improvements
>
> 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);
> }
>
>