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



reply via email to

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