Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: Security issue in Zsh restricted mode (zsh -r) – escape via history built‑ins



I agree with you. Yes disable those local functions!

On Tue, Feb 10, 2026 at 4:21 PM Oliver Kiddle <opk@xxxxxxx> wrote:
>
> On 1 Feb, I wrote:
> > On further deliberation, I think we should just drop the whole
> > restricted mode feature. The documentation has carried a warning that
> > "the feature may be removed in future" for the past six years.
>
> Nobody argued for a reprieve so a patch to get rid of it follows.
>
> This does leave the option in existence but it does nothing. That's
> just for backwards compatibility with old set -o or setopt commands.
>
> PM_RESTRICTED is overloaded in the zsh/param/private module so needs to
> stay. It doesn't appear that the module was relying on protections that
> option gave to variables with the flag set but I could be wrong.
>
> For what it's worth, compiling zsh statically does not help with the
> LD_ variables used by the loader. The problem is anytime the loader
> is used when invoking a command from the restricted shell. Actually,
> a couple of LD_ variables are treated as protected but not all that
> matter. And as I mentioned these vary between operating systems.
>
> Oliver
>
> diff --git a/Doc/Makefile.in b/Doc/Makefile.in
> index f68f40a9e..083e019d5 100644
> --- a/Doc/Makefile.in
> +++ b/Doc/Makefile.in
> @@ -84,7 +84,7 @@ Zsh/filelist.yo Zsh/files.yo \
>  Zsh/func.yo Zsh/grammar.yo Zsh/manual.yo \
>  Zsh/index.yo Zsh/intro.yo Zsh/invoke.yo Zsh/jobs.yo Zsh/metafaq.yo \
>  Zsh/modules.yo Zsh/modlist.yo Zsh/modmenu.yo Zsh/manmodmenu.yo $(MODDOCSRC) \
> -Zsh/options.yo Zsh/params.yo Zsh/prompt.yo Zsh/redirect.yo Zsh/restricted.yo \
> +Zsh/options.yo Zsh/params.yo Zsh/prompt.yo Zsh/redirect.yo \
>  Zsh/seealso.yo Zsh/tcpsys.yo Zsh/zftpsys.yo Zsh/zle.yo
>
>  # ========== DEPENDENCIES FOR BUILDING ==========
> @@ -219,7 +219,7 @@ $(MAN): zmacros.yo zman.yo
>
>  zsh.1 zshall.1: Zsh/intro.yo Zsh/metafaq.yo Zsh/invoke.yo Zsh/files.yo \
>                  Zsh/filelist.yo Zsh/filelist.yo Zsh/seealso.yo \
> -                Zsh/compat.yo Zsh/restricted.yo
> +                Zsh/compat.yo
>
>  zshbuiltins.1: Zsh/builtins.yo
>
> diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo
> index c322cee77..c63d66e0c 100644
> --- a/Doc/Zsh/builtins.yo
> +++ b/Doc/Zsh/builtins.yo
> @@ -570,8 +570,7 @@ change.
>
>  The var(flags) may be any of the invocation-time flags described in
>  sectref(Invocation)(zsh),
> -except that `tt(-o EMACS)' and `tt(-o VI)' may not be used.  Flags such
> -as `tt(+r)'/`tt(+o RESTRICTED)' may be prohibited in some circumstances.
> +except that `tt(-o EMACS)' and `tt(-o VI)' may not be used.
>
>  If tt(-c) var(arg) appears in var(flags), var(arg) is evaluated while the
>  requested emulation is temporarily in effect.  In this case the emulation
> diff --git a/Doc/Zsh/compat.yo b/Doc/Zsh/compat.yo
> index 4d3567d45..df0ace63d 100644
> --- a/Doc/Zsh/compat.yo
> +++ b/Doc/Zsh/compat.yo
> @@ -1,12 +1,11 @@
> -texinode(Compatibility)(Restricted Shell)()(Invocation)
> +texinode(Compatibility)()()(Invocation)
>  sect(Compatibility)
>  cindex(compatibility)
>  cindex(sh compatibility)
>  cindex(ksh compatibility)
>  Zsh tries to emulate bf(sh) or bf(ksh) when it is invoked as
>  tt(sh) or tt(ksh) respectively; more precisely, it looks at the first
> -letter of the name by which it was invoked, excluding any initial `tt(r)'
> -(assumed to stand for `restricted'), and if that is `tt(b)', `tt(s)' or `tt(k)' it
> +letter of the name by which it was invoked, and if that is `tt(b)', `tt(s)' or `tt(k)' it
>  will emulate bf(sh) or bf(ksh).  Furthermore, if invoked as tt(su) (which
>  happens on certain systems when the shell is executed by the tt(su)
>  command), the shell will try to find an alternative name from the tt(SHELL)
> diff --git a/Doc/Zsh/grammar.yo b/Doc/Zsh/grammar.yo
> index e75e66a6c..8dbfd1164 100644
> --- a/Doc/Zsh/grammar.yo
> +++ b/Doc/Zsh/grammar.yo
> @@ -531,7 +531,6 @@ itemiz(Execution of incorrectly positioned loop control structures
>  (tt(continue), tt(break)))
>  itemiz(Attempts to use regular expression with no regular expression
>  module available)
> -itemiz(Disallowed operations when the tt(RESTRICTED) options is set)
>  itemiz(Failure to create a pipe needed for a pipeline)
>  itemiz(Failure to create a multio)
>  itemiz(Failure to autoload a module needed for a declared shell feature)
> diff --git a/Doc/Zsh/invoke.yo b/Doc/Zsh/invoke.yo
> index 9c589b278..b6ed73fe5 100644
> --- a/Doc/Zsh/invoke.yo
> +++ b/Doc/Zsh/invoke.yo
> @@ -105,8 +105,6 @@ can be stacked after the `tt(-b)' and will take effect as normal.
>
>  startmenu()
>  menu(Compatibility)
> -menu(Restricted Shell)
>  endmenu()
>
>  includefile(Zsh/compat.yo)
> -includefile(Zsh/restricted.yo)
> diff --git a/Doc/Zsh/manual.yo b/Doc/Zsh/manual.yo
> index 8cbe2cfd2..c7882cebd 100644
> --- a/Doc/Zsh/manual.yo
> +++ b/Doc/Zsh/manual.yo
> @@ -64,7 +64,6 @@ menu(See Also)
>  Invocation
>
>  menu(Compatibility)
> -menu(Restricted Shell)
>
>  Shell Grammar
>
> diff --git a/Doc/Zsh/options.yo b/Doc/Zsh/options.yo
> index a7e862c70..729a6ac26 100644
> --- a/Doc/Zsh/options.yo
> +++ b/Doc/Zsh/options.yo
> @@ -1837,8 +1837,8 @@ pindex(NOLOCALOPTIONS)
>  item(tt(LOCAL_OPTIONS) <K>)(
>  If this option is set at the point of return from a shell function,
>  most options (including this one) which were in force upon entry to
> -the function are restored; options that are not restored are
> -tt(PRIVILEGED) and tt(RESTRICTED).  Otherwise, only this option,
> +the function are restored; the tt(PRIVILEGED) option is not restored.
> +Otherwise, only this option,
>  and the tt(LOCAL_LOOPS), tt(XTRACE) and tt(PRINT_EXIT_VALUE) options are
>  restored.  Hence if this is explicitly unset by a shell function the
>  other options in force at the point of return will remain so.
> @@ -2471,10 +2471,8 @@ pindex(NO_RESTRICTED)
>  pindex(NORESTRICTED)
>  cindex(restricted shell)
>  item(tt(RESTRICTED) (tt(-r)))(
> -Enables restricted mode.  This option cannot be changed using
> -tt(unsetopt), and setting it inside a function always changes it
> -globally regardless of the tt(LOCAL_OPTIONS) option.  See
> -sectref(Restricted Shell)(zsh).
> +This option is ignored and only exists for compatibility. Support
> +for restricted mode has been removed.
>  )
>  pindex(SHIN_STDIN)
>  pindex(NO_SHIN_STDIN)
> diff --git a/Doc/Zsh/restricted.yo b/Doc/Zsh/restricted.yo
> deleted file mode 100644
> index a84fd28ea..000000000
> --- a/Doc/Zsh/restricted.yo
> +++ /dev/null
> @@ -1,84 +0,0 @@
> -texinode(Restricted Shell)()(Compatibility)(Invocation)
> -sect(Restricted Shell)
> -cindex(restricted shell)
> -pindex(RESTRICTED)
> -When the basename of the command used to invoke zsh starts with the letter
> -`tt(r)' or the `tt(-r)' command line option is supplied at invocation, the
> -shell becomes restricted.  Emulation mode is determined after stripping the
> -letter `tt(r)' from the invocation name.  The following are disabled in
> -restricted mode:
> -
> -startitemize()
> -itemiz(changing directories with the tt(cd) builtin)
> -itemiz(changing or unsetting the tt(EGID), tt(EUID), tt(GID),
> -tt(HISTFILE), tt(HISTSIZE), tt(IFS), tt(LD_AOUT_LIBRARY_PATH),
> -tt(LD_AOUT_PRELOAD), tt(LD_LIBRARY_PATH), tt(LD_PRELOAD),
> -tt(MODULE_PATH), tt(module_path), tt(PATH), tt(path), tt(SHELL),
> -tt(UID) and tt(USERNAME) parameters)
> -itemiz(specifying command names containing tt(/))
> -itemiz(specifying command pathnames using tt(hash))
> -itemiz(redirecting output to files)
> -itemiz(using the tt(exec) builtin command to replace the shell with another
> -command)
> -itemiz(using tt(jobs -Z) to overwrite the shell process' argument and
> -environment space)
> -itemiz(using the tt(ARGV0) parameter to override tt(argv[0]) for external
> -commands)
> -itemiz(turning off restricted mode with tt(set +r) or tt(unsetopt
> -RESTRICTED))
> -enditemize()
> -
> -These restrictions are enforced after processing the startup files.  The
> -startup files should set up tt(PATH) to point to a directory of commands
> -which can be safely invoked in the restricted environment.  They may also
> -add further restrictions by disabling selected builtins.
> -
> -Restricted mode can also be activated any time by setting the
> -tt(RESTRICTED) option.  This immediately enables all the restrictions
> -described above even if the shell still has not processed all startup
> -files.
> -
> -A shell em(Restricted Mode) is an outdated way to restrict what users may
> -do:  modern systems have better, safer and more reliable ways to
> -confine user actions, such as em(chroot jails), em(containers) and
> -em(zones).
> -
> -A restricted shell is very difficult to implement safely.  The feature
> -may be removed in a future version of zsh.
> -
> -It is important to realise that the restrictions only apply to the shell,
> -not to the commands it runs (except for some shell builtins).  While a
> -restricted shell can only run the restricted list of commands accessible
> -via the predefined `tt(PATH)' variable, it does not prevent those
> -commands from running any other command.
> -
> -As an example, if `tt(env)' is among the list of em(allowed) commands,
> -then it allows the user to run any command as `tt(env)' is not a shell
> -builtin command and can run arbitrary executables.
> -
> -So when implementing a restricted shell framework it is important to be
> -fully aware of what actions each of the em(allowed) commands or features
> -(which may be regarded as em(modules)) can perform.
> -
> -Many commands can have their behaviour affected by environment
> -variables.  Except for the few listed above, zsh does not restrict
> -the setting of environment variables.
> -
> -If a `tt(perl)', `tt(python)', `tt(bash)', or other general purpose
> -interpreted script is treated as a restricted
> -command, the user can work around the restriction by
> -setting specially crafted `tt(PERL5LIB)', `tt(PYTHONPATH)',
> -`tt(BASH_ENV)' (etc.) environment variables. On GNU systems, any
> -command can be made to run arbitrary code when performing character set
> -conversion (including zsh itself) by setting a `tt(GCONV_PATH)'
> -environment variable.  Those are only a few examples.
> -
> -Bear in mind that, contrary to some other shells, `tt(readonly)' is not a
> -security feature in zsh as it can be undone and so cannot be used to
> -mitigate the above.
> -
> -A restricted shell only works if the allowed commands are few
> -and carefully written so as not to grant more access to users than
> -intended.  It is also important to restrict what zsh module the user may
> -load as some of them, such as `tt(zsh/system)', `tt(zsh/mapfile)' and
> -`tt(zsh/files)', allow bypassing most of the restrictions.
> diff --git a/README b/README
> index 64b0f4e4a..e546af267 100644
> --- a/README
> +++ b/README
> @@ -52,6 +52,11 @@ or, if your $VISUAL and $EDITOR environment variables vary,
>  to your .zshrc file.  These snippets are compatible with previous
>  versions of the shell.
>
> +Restricted mode has been removed.  This was associated with the option
> +RESTRICTED (-r).  This was an outdated way to restrict what users may do and
> +was very difficult to apply safely.  Furthermore, modern systems have better,
> +safer and more reliable ways to confine user actions.
> +
>  The ERR_EXIT and ERR_RETURN options were refined to be more self-
>  consistent and better aligned with the POSIX-2017 specification of
>  `set -e`:
> diff --git a/Src/Modules/db_gdbm.c b/Src/Modules/db_gdbm.c
> index 7d1720de5..34f577e30 100644
> --- a/Src/Modules/db_gdbm.c
> +++ b/Src/Modules/db_gdbm.c
> @@ -150,7 +150,7 @@ bin_ztie(char *nam, char **args, Options ops, UNUSED(int func))
>          * We need to do this before attempting to open the DB
>          * in case this variable is already tied to a DB.
>          *
> -        * This can fail if the variable is readonly or restricted.
> +        * This can fail if the variable is readonly.
>          * We could call unsetparam() and check errflag instead
>          * of the return status.
>          */
> diff --git a/Src/Modules/parameter.c b/Src/Modules/parameter.c
> index 10e4ffc5c..0743e6323 100644
> --- a/Src/Modules/parameter.c
> +++ b/Src/Modules/parameter.c
> @@ -151,17 +151,12 @@ scanpmparameters(UNUSED(HashTable ht), ScanFunc func, int flags)
>  static void
>  setpmcommand(Param pm, char *value)
>  {
> -    if (isset(RESTRICTED)) {
> -       zwarn("restricted: %s", value);
> -       zsfree(value);
> -    } else {
> -       Cmdnam cn = zshcalloc(sizeof(*cn));
> +    Cmdnam cn = zshcalloc(sizeof(*cn));
>
> -       cn->node.flags = HASHED;
> -       cn->u.cmd = value;
> +    cn->node.flags = HASHED;
> +    cn->u.cmd = value;
>
> -       cmdnamtab->addnode(cmdnamtab, ztrdup(pm->node.nam), &cn->node);
> -    }
> +    cmdnamtab->addnode(cmdnamtab, ztrdup(pm->node.nam), &cn->node);
>  }
>
>  /**/
> diff --git a/Src/builtin.c b/Src/builtin.c
> index 49fab93da..b097414fb 100644
> --- a/Src/builtin.c
> +++ b/Src/builtin.c
> @@ -841,10 +841,6 @@ bin_cd(char *nam, char **argv, Options ops, int func)
>  {
>      LinkNode dir;
>
> -    if (isset(RESTRICTED)) {
> -       zwarnnam(nam, "restricted");
> -       return 1;
> -    }
>      doprintdir = (doprintdir == -1);
>
>      chasinglinks = OPT_ISSET(ops,'P') ||
> @@ -2249,10 +2245,6 @@ typeset_single(char *cname, char *pname, Param pm, int func,
>                 paramtab->printnode(&pm->node, PRINT_INCLUDEVALUE|with_ns);
>             return pm;
>         }
> -       if ((pm->node.flags & PM_RESTRICTED) && isset(RESTRICTED)) {
> -           zerrnam(cname, "%s: restricted", pname);
> -           return pm;
> -       }
>         if ((pm->node.flags & PM_READONLY) && !(off & PM_READONLY) &&
>             /* It seems as though these checks should not be specific to
>              * PM_NAMEREF, but changing that changes historic behavior */
> @@ -2387,10 +2379,6 @@ typeset_single(char *cname, char *pname, Param pm, int func,
>
>      if (newspecial != NS_NONE) {
>         Param tpm, pm2;
> -       if ((pm->node.flags & PM_RESTRICTED) && isset(RESTRICTED)) {
> -           zerrnam(cname, "%s: restricted", pname);
> -           return pm;
> -       }
>         if (pm->node.flags & PM_SINGLE) {
>             zerrnam(cname, "%s: can only have a single instance", pname);
>             return pm;
> @@ -2631,12 +2619,7 @@ typeset_single(char *cname, char *pname, Param pm, int func,
>             pm->gsu.s->setfn(pm, ztrdup(""));
>             break;
>         case PM_INTEGER:
> -           /*
> -            * Restricted integers are dangerous to initialize to 0,
> -            * so don't do that.
> -            */
> -           if (!(pm->old->node.flags & PM_RESTRICTED))
> -               pm->gsu.i->setfn(pm, 0);
> +           pm->gsu.i->setfn(pm, 0);
>             break;
>         case PM_EFLOAT:
>         case PM_FFLOAT:
> @@ -3096,8 +3079,7 @@ bin_typeset(char *name, char **argv, LinkList assigns, Options ops, int func)
>             for (i = 0; i < paramtab->hsize; i++) {
>                 for (pm = (Param) paramtab->nodes[i]; pm;
>                      pm = (Param) pm->node.next) {
> -                   if (((pm->node.flags & PM_RESTRICTED) && isset(RESTRICTED)) ||
> -                       (pm->node.flags & PM_UNSET))
> +                   if (pm->node.flags & PM_UNSET)
>                         continue;
>                     if (pattry(pprog, pm->node.nam))
>                         addlinknode(pmlist, pm);
> @@ -3855,9 +3837,7 @@ bin_unset(char *name, char **argv, Options ops, int func)
>                     for (pm = (Param) paramtab->nodes[i]; pm; pm = next) {
>                         /* record pointer to next, since we may free this one */
>                         next = (Param) pm->node.next;
> -                       if ((!(pm->node.flags & PM_RESTRICTED) ||
> -                            unset(RESTRICTED)) &&
> -                           pattry(pprog, pm->node.nam)) {
> +                       if (pattry(pprog, pm->node.nam)) {
>                             if (!OPT_ISSET(ops,'n') &&
>                                 (pm->node.flags & PM_NAMEREF) && pm->u.str)
>                                 unsetparam(pm->u.str);
> @@ -3910,10 +3890,7 @@ bin_unset(char *name, char **argv, Options ops, int func)
>          */
>         if (!pm)
>             continue;
> -       else if ((pm->node.flags & PM_RESTRICTED) && isset(RESTRICTED)) {
> -           zerrnam(name, "%s: restricted", pm->node.nam);
> -           returnval = 1;
> -       } else if (ss) {
> +       else if (ss) {
>             if ((pm->node.flags & PM_NAMEREF) &&
>                 (!(pm = (Param)resolve_nameref(pm, NULL)) || pm->width)) {
>                 /* warning? */
> @@ -4315,34 +4292,28 @@ bin_hash(char *name, char **argv, Options ops, UNUSED(int func))
>             returnval = 1;
>             break;
>          } else if (ASG_VALUEP(asg)) {
> -           if(isset(RESTRICTED)) {
> -               zwarnnam(name, "restricted: %s", asg->value.scalar);
> -               returnval = 1;
> -           } else {
> -               /* The argument is of the form foo=bar, *
> -                * so define an entry for the table.    */
> -               if(OPT_ISSET(ops,'d')) {
> -                   /* shouldn't return NULL if asg->name is not NULL */
> -                   if (*itype_end(asg->name, IUSER, 0)) {
> -                       zwarnnam(name,
> -                                "invalid character in directory name: %s",
> -                                asg->name);
> -                       returnval = 1;
> -                       continue;
> -                   } else {
> -                       Nameddir nd = hn = zshcalloc(sizeof *nd);
> -                       nd->node.flags = 0;
> -                       nd->dir = ztrdup(asg->value.scalar);
> -                   }
> +           /* The argument is of the form foo=bar, *
> +            * so define an entry for the table.    */
> +           if (OPT_ISSET(ops, 'd')) {
> +               /* shouldn't return NULL if asg->name is not NULL */
> +               if (*itype_end(asg->name, IUSER, 0)) {
> +                   zwarnnam(name, "invalid character in directory name: %s",
> +                           asg->name);
> +                   returnval = 1;
> +                   continue;
>                 } else {
> -                   Cmdnam cn = hn = zshcalloc(sizeof *cn);
> -                   cn->node.flags = HASHED;
> -                   cn->u.cmd = ztrdup(asg->value.scalar);
> +                   Nameddir nd = hn = zshcalloc(sizeof *nd);
> +                   nd->node.flags = 0;
> +                   nd->dir = ztrdup(asg->value.scalar);
>                 }
> -               ht->addnode(ht, ztrdup(asg->name), hn);
> -               if(OPT_ISSET(ops,'v'))
> -                   ht->printnode(hn, 0);
> +           } else {
> +               Cmdnam cn = hn = zshcalloc(sizeof *cn);
> +               cn->node.flags = HASHED;
> +               cn->u.cmd = ztrdup(asg->value.scalar);
>             }
> +           ht->addnode(ht, ztrdup(asg->name), hn);
> +           if (OPT_ISSET(ops, 'v'))
> +               ht->printnode(hn, 0);
>         } else if (!(hn = ht->getnode2(ht, asg->name))) {
>             /* With no `=value' part to the argument, *
>              * work out what it ought to be.          */
> diff --git a/Src/exec.c b/Src/exec.c
> index 27bca110c..93ee7d1da 100644
> --- a/Src/exec.c
> +++ b/Src/exec.c
> @@ -35,8 +35,6 @@
>  enum {
>      /* Export the variable for "VAR=val cmd ..." */
>      ADDVAR_EXPORT =   1 << 0,
> -    /* Apply restrictions for variable */
> -    ADDVAR_RESTRICT = 1 << 1,
>      /* Variable list is being restored later */
>      ADDVAR_RESTORE =  1 << 2
>  };
> @@ -731,10 +729,6 @@ execute(LinkList args, int flags, int defpath)
>      int eno = 0, ee;
>
>      arg0 = (char *) peekfirst(args);
> -    if (isset(RESTRICTED) && (strchr(arg0, '/') || defpath)) {
> -       zerr("%s: restricted", arg0);
> -       _exit(1);
> -    }
>
>      /* If the parameter STTY is set in the command's environment, *
>       * we first run the stty command with the value of this       *
> @@ -755,7 +749,7 @@ execute(LinkList args, int flags, int defpath)
>
>      /* If ARGV0 is in the commands environment, we use *
>       * that as argv[0] for this external command       */
> -    if (unset(RESTRICTED) && (z = zgetenv("ARGV0"))) {
> +    if ((z = zgetenv("ARGV0"))) {
>         setdata(firstnode(args), (void *) ztrdup(z));
>         /*
>          * Note we don't do anything with the parameter structure
> @@ -2588,14 +2582,6 @@ addvars(Estate state, Wordcode pc, int addflags)
>                 fputc(' ', xtrerr);
>             }
>             if ((addflags & ADDVAR_EXPORT) && !strchr(name, '[')) {
> -               if ((addflags & ADDVAR_RESTRICT) && isset(RESTRICTED) &&
> -                   (pm = (Param) paramtab->removenode(paramtab, name)) &&
> -                   (pm->node.flags & PM_RESTRICTED)) {
> -                   zerr("%s: restricted", pm->node.nam);
> -                   zsfree(val);
> -                   state->pc = opc;
> -                   return;
> -               }
>                 if (strcmp(name, "STTY") == 0) {
>                     zsfree(STTYval);
>                     STTYval = ztrdup(val);
> @@ -2604,7 +2590,7 @@ addvars(Estate state, Wordcode pc, int addflags)
>                 opts[ALLEXPORT] = 1;
>                 if (isset(KSHARRAYS))
>                     unsetparam(name);
> -               pm = assignsparam(name, val, myflags);
> +               pm = assignsparam(name, val, myflags);
>                 opts[ALLEXPORT] = allexp;
>             } else
>                 pm = assignsparam(name, val, myflags);
> @@ -3418,15 +3404,6 @@ execcmd_exec(Estate state, Execcmd_params eparams,
>                         shelltime(&shti, &chti, &then, 1);
>                     return;
>                 }
> -           } else if (isset(RESTRICTED) && (cflags & BINF_EXEC) && do_exec) {
> -               zerrnam("exec", "%s: restricted",
> -                       (char *) getdata(firstnode(args)));
> -               lastval = 1;
> -               if (forked)
> -                   _realexit();
> -               if (how & Z_TIMED)
> -                   shelltime(&shti, &chti, &then, 1);
> -               return;
>             }
>
>             /*
> @@ -3783,10 +3760,6 @@ execcmd_exec(Estate state, Execcmd_params eparams,
>                 fixfds(save);
>                 execerr();
>             }
> -           if (isset(RESTRICTED) && IS_WRITE_FILE(fn->type)) {
> -               zwarn("writing redirection not allowed in restricted mode");
> -               execerr();
> -           }
>             if (unset(EXECOPT))
>                 continue;
>             switch(fn->type) {
> @@ -4314,7 +4287,7 @@ execcmd_exec(Estate state, Execcmd_params eparams,
>             }
>             if (type == WC_SIMPLE || type == WC_TYPESET) {
>                 if (varspc) {
> -                   int addflags = ADDVAR_EXPORT|ADDVAR_RESTRICT;
> +                   int addflags = ADDVAR_EXPORT;
>                     if (forked)
>                         addflags |= ADDVAR_RESTORE;
>                     addvars(state, varspc, addflags);
> @@ -4463,8 +4436,7 @@ save_params(Estate state, Wordcode pc, LinkList *restore_p, LinkList *remove_p)
>                 tpm = (Param) zshcalloc(sizeof *tpm);
>                 tpm->node.nam = ztrdup(pm->node.nam);
>                 copyparam(tpm, pm, 0);
> -           } else if (!(pm->node.flags & PM_READONLY) &&
> -                      (unset(RESTRICTED) || !(pm->node.flags & PM_RESTRICTED))) {
> +           } else if (!(pm->node.flags & PM_READONLY)) {
>                 /*
>                  * In this case we're just saving parts of
>                  * the parameter in a temporary, so use heap allocation
> @@ -6113,9 +6085,8 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval)
>             /* take care of SUNKEYBOARDHACK but not of EMACS/VI */
>             if (funcsave->opts[SUNKEYBOARDHACK] != opts[SUNKEYBOARDHACK])
>                 keyboardhackchar = funcsave->opts[SUNKEYBOARDHACK] ? '`' : '\0';
> -           /* restore all shell options except PRIVILEGED and RESTRICTED */
> +           /* restore all shell options except PRIVILEGED */
>             funcsave->opts[PRIVILEGED] = opts[PRIVILEGED];
> -           funcsave->opts[RESTRICTED] = opts[RESTRICTED];
>             memcpy(opts, funcsave->opts, sizeof(opts));
>             emulation = funcsave->emulation;
>             if (init_typtab)
> diff --git a/Src/init.c b/Src/init.c
> index 20b8cc7fd..beb9b2c3c 100644
> --- a/Src/init.c
> +++ b/Src/init.c
> @@ -255,8 +255,6 @@ loop(int toplevel, int justonce)
>      return LOOP_OK;
>  }
>
> -static int restricted;
> -
>  /* original argv[0]. This is already metafied */
>  static char *argv0;
>
> @@ -494,8 +492,6 @@ parseopts(char *nam, char ***argvp, char *new_opts, char **cmdp,
>                 if (!(optno = optlookup(*argv))) {
>                     WARN_OPTION("no such option: %s", *argv);
>                     return 1;
> -               } else if (optno == RESTRICTED && toplevel) {
> -                   restricted = action;
>                 } else if ((optno == EMACSMODE || optno == VIMODE) && !toplevel) {
>                     WARN_OPTION("can't change option: %s", *argv);
>                 } else {
> @@ -524,8 +520,6 @@ parseopts(char *nam, char ***argvp, char *new_opts, char **cmdp,
>                 if (!(optno = optlookupc(**argv))) {
>                     WARN_OPTION("bad option: -%c", **argv);
>                     return 1;
> -               } else if (optno == RESTRICTED && toplevel) {
> -                   restricted = action;
>                 } else if ((optno == EMACSMODE || optno == VIMODE) &&
>                            !toplevel) {
>                     WARN_OPTION("can't change option: %s", *argv);
> @@ -1529,12 +1523,6 @@ run_init_scripts(void)
>  void
>  init_misc(char *cmd, char *zsh_name)
>  {
> -#ifndef RESTRICTED_R
> -    if ( restricted )
> -#else
> -    if (*zsh_name == 'r' || restricted)
> -#endif
> -       dosetopt(RESTRICTED, 1, 0, opts);
>      if (cmd) {
>         if (SHIN >= 10)
>             close(SHIN);
> diff --git a/Src/jobs.c b/Src/jobs.c
> index 4905ae925..94c0679b1 100644
> --- a/Src/jobs.c
> +++ b/Src/jobs.c
> @@ -2425,10 +2425,6 @@ bin_fg(char *name, char **argv, Options ops, int func)
>      if (OPT_ISSET(ops,'Z')) {
>         int len;
>
> -       if(isset(RESTRICTED)) {
> -           zwarnnam(name, "-Z is restricted");
> -           return 1;
> -       }
>         if(!argv[0] || argv[1]) {
>             zwarnnam(name, "-Z requires one argument");
>             return 1;
> diff --git a/Src/options.c b/Src/options.c
> index 8b13f0c5d..649c654ba 100644
> --- a/Src/options.c
> +++ b/Src/options.c
> @@ -240,7 +240,7 @@ static struct optname optns[] = {
>  {{NULL, "rcs",               OPT_ALL},                  RCS},
>  {{NULL, "recexact",          0},                        RECEXACT},
>  {{NULL, "rematchpcre",       0},                        REMATCHPCRE},
> -{{NULL, "restricted",        OPT_SPECIAL},              RESTRICTED},
> +{{NULL, "restricted",        0},                        RESTRICTED},
>  {{NULL, "rmstarsilent",              OPT_BOURNE},               RMSTARSILENT},
>  {{NULL, "rmstarwait",        0},                        RMSTARWAIT},
>  {{NULL, "sharehistory",              OPT_KSH},                  SHAREHISTORY},
> @@ -727,25 +727,6 @@ optlookupc(char c)
>      return optletters[c - FIRST_OPT];
>  }
>
> -/**/
> -static void
> -restrictparam(char *nam)
> -{
> -    Param pm = (Param) paramtab->getnode(paramtab, nam);
> -
> -    if (pm) {
> -       pm->node.flags |= PM_SPECIAL | PM_RESTRICTED;
> -       return;
> -    }
> -    createparam(nam, PM_SCALAR | PM_UNSET | PM_SPECIAL | PM_RESTRICTED);
> -}
> -
> -/* list of restricted parameters which are not otherwise special */
> -static char *rparams[] = {
> -    "SHELL", "HISTFILE", "LD_LIBRARY_PATH", "LD_AOUT_LIBRARY_PATH",
> -    "LD_PRELOAD", "LD_AOUT_PRELOAD", NULL
> -};
> -
>  /* Set or unset an option, as a result of user request.  The option *
>   * number may be negative, indicating that the sense is reversed    *
>   * from the usual meaning of the option.                            */
> @@ -760,16 +741,7 @@ dosetopt(int optno, int value, int force, char *new_opts)
>         optno = -optno;
>         value = !value;
>      }
> -    if (optno == RESTRICTED) {
> -       if (isset(RESTRICTED))
> -           return value ? 0 : -1;
> -       if (value) {
> -           char **s;
> -
> -           for (s = rparams; *s; s++)
> -               restrictparam(*s);
> -       }
> -    } else if(!force && optno == EXECOPT && !value && interact) {
> +    if (!force && optno == EXECOPT && !value && interact) {
>         /* cannot set noexec when interactive */
>         return -1;
>      } else if(!force && (optno == INTERACTIVE || optno == SHINSTDIN ||
> diff --git a/Src/params.c b/Src/params.c
> index 9d7fbbee1..7179dd793 100644
> --- a/Src/params.c
> +++ b/Src/params.c
> @@ -296,18 +296,18 @@ static initparam special_params[] ={
>  #define IPDEF1(A,B,C) {{NULL,A,PM_INTEGER|PM_SPECIAL|C},BR(NULL),GSU(B),10,0,NULL,NULL,NULL,0}
>  IPDEF1("#", pound_gsu, PM_READONLY_SPECIAL),
>  IPDEF1("ERRNO", errno_gsu, PM_UNSET),
> -IPDEF1("GID", gid_gsu, PM_DONTIMPORT | PM_RESTRICTED),
> -IPDEF1("EGID", egid_gsu, PM_DONTIMPORT | PM_RESTRICTED),
> -IPDEF1("HISTSIZE", histsize_gsu, PM_RESTRICTED),
> +IPDEF1("GID", gid_gsu, PM_DONTIMPORT),
> +IPDEF1("EGID", egid_gsu, PM_DONTIMPORT),
> +IPDEF1("HISTSIZE", histsize_gsu, 0),
>  IPDEF1("RANDOM", random_gsu, 0),
> -IPDEF1("SAVEHIST", savehist_gsu, PM_RESTRICTED),
> +IPDEF1("SAVEHIST", savehist_gsu, 0),
>  IPDEF1("SECONDS", intseconds_gsu, 0),
> -IPDEF1("UID", uid_gsu, PM_DONTIMPORT | PM_RESTRICTED),
> -IPDEF1("EUID", euid_gsu, PM_DONTIMPORT | PM_RESTRICTED),
> +IPDEF1("UID", uid_gsu, PM_DONTIMPORT),
> +IPDEF1("EUID", euid_gsu, PM_DONTIMPORT),
>  IPDEF1("TTYIDLE", ttyidle_gsu, PM_READONLY_SPECIAL),
>
>  #define IPDEF2(A,B,C) {{NULL,A,PM_SCALAR|PM_SPECIAL|C},BR(NULL),GSU(B),0,0,NULL,NULL,NULL,0}
> -IPDEF2("USERNAME", username_gsu, PM_DONTIMPORT|PM_RESTRICTED),
> +IPDEF2("USERNAME", username_gsu, PM_DONTIMPORT),
>  IPDEF2("-", dash_gsu, PM_READONLY_SPECIAL),
>  IPDEF2("histchars", histchars_gsu, PM_DONTIMPORT),
>  IPDEF2("HOME", home_gsu, PM_UNSET),
> @@ -315,7 +315,7 @@ IPDEF2("TERM", term_gsu, PM_UNSET),
>  IPDEF2("TERMINFO", terminfo_gsu, PM_UNSET),
>  IPDEF2("TERMINFO_DIRS", terminfodirs_gsu, PM_UNSET),
>  IPDEF2("WORDCHARS", wordchars_gsu, 0),
> -IPDEF2("IFS", ifs_gsu, PM_DONTIMPORT | PM_RESTRICTED),
> +IPDEF2("IFS", ifs_gsu, PM_DONTIMPORT),
>  IPDEF2("_", underscore_gsu, PM_DONTIMPORT),
>  IPDEF2("KEYBOARD_HACK", keyboard_hack_gsu, PM_DONTIMPORT),
>  IPDEF2("0", argzero_gsu, 0),
> @@ -396,12 +396,12 @@ IPDEF8("CDPATH", &cdpath, "cdpath", PM_TIED),
>  IPDEF8("FIGNORE", &fignore, "fignore", PM_TIED),
>  IPDEF8("FPATH", &fpath, "fpath", PM_TIED),
>  IPDEF8("MAILPATH", &mailpath, "mailpath", PM_TIED),
> -IPDEF8("PATH", &path, "path", PM_RESTRICTED|PM_TIED),
> +IPDEF8("PATH", &path, "path", PM_TIED),
>  IPDEF8("PSVAR", &psvar, "psvar", PM_TIED),
>  IPDEF8("ZSH_EVAL_CONTEXT", &zsh_eval_context, "zsh_eval_context", PM_READONLY_SPECIAL|PM_TIED),
>
>  /* MODULE_PATH is not imported for security reasons */
> -IPDEF8("MODULE_PATH", &module_path, "module_path", PM_DONTIMPORT|PM_RESTRICTED|PM_TIED),
> +IPDEF8("MODULE_PATH", &module_path, "module_path", PM_DONTIMPORT|PM_TIED),
>
>  #define IPDEF10(A,B) {{NULL,A,PM_ARRAY|PM_SPECIAL},BR(NULL),GSU(B),10,0,NULL,NULL,NULL,0}
>
> @@ -430,8 +430,8 @@ IPDEF9("psvar", &psvar, "PSVAR", PM_TIED),
>
>  IPDEF9("zsh_eval_context", &zsh_eval_context, "ZSH_EVAL_CONTEXT", PM_TIED|PM_READONLY_SPECIAL),
>
> -IPDEF9("module_path", &module_path, "MODULE_PATH", PM_TIED|PM_RESTRICTED),
> -IPDEF9("path", &path, "PATH", PM_TIED|PM_RESTRICTED),
> +IPDEF9("module_path", &module_path, "MODULE_PATH", PM_TIED),
> +IPDEF9("path", &path, "PATH", PM_TIED),
>
>  /* These are known to zsh alone. */
>
> @@ -449,12 +449,12 @@ IPDEF8("CDPATH", &cdpath, NULL, 0),
>  IPDEF8("FIGNORE", &fignore, NULL, 0),
>  IPDEF8("FPATH", &fpath, NULL, 0),
>  IPDEF8("MAILPATH", &mailpath, NULL, 0),
> -IPDEF8("PATH", &path, NULL, PM_RESTRICTED),
> +IPDEF8("PATH", &path, NULL, 0),
>  IPDEF8("PSVAR", &psvar, NULL, 0),
>  IPDEF8("ZSH_EVAL_CONTEXT", &zsh_eval_context, NULL, PM_READONLY_SPECIAL),
>
>  /* MODULE_PATH is not imported for security reasons */
> -IPDEF8("MODULE_PATH", &module_path, NULL, PM_DONTIMPORT|PM_RESTRICTED),
> +IPDEF8("MODULE_PATH", &module_path, NULL, PM_DONTIMPORT),
>
>  {{NULL,NULL,0},BR(NULL),NULL_GSU,0,0,NULL,NULL,NULL,0},
>  };
> @@ -1083,10 +1083,6 @@ createparam(char *name, int flags)
>                 zerr("read-only variable: %s", name);
>                 return NULL;
>             }
> -           if ((oldpm->node.flags & PM_RESTRICTED) && isset(RESTRICTED)) {
> -               zerr("%s: restricted", name);
> -               return NULL;
> -           }
>             if (!(oldpm->node.flags & PM_UNSET) ||
>                 (oldpm->node.flags & PM_SPECIAL) ||
>                 /* POSIXBUILTINS horror: we need to retain 'export' flags */
> @@ -2678,11 +2674,6 @@ assignstrvalue(Value v, char *val, int flags)
>         zsfree(val);
>         return;
>      }
> -    if ((v->pm->node.flags & PM_RESTRICTED) && isset(RESTRICTED)) {
> -       zerr("%s: restricted", v->pm->node.nam);
> -       zsfree(val);
> -       return;
> -    }
>      if ((v->pm->node.flags & PM_HASHED) &&
>         (v->scanflags & (SCANPM_MATCHMANY|SCANPM_ARRONLY))) {
>         zerr("%s: attempt to set slice of associative array", v->pm->node.nam);
> @@ -2847,10 +2838,6 @@ setnumvalue(Value v, mnumber val)
>         zerr("read-only variable: %s", v->pm->node.nam);
>         return;
>      }
> -    if ((v->pm->node.flags & PM_RESTRICTED) && isset(RESTRICTED)) {
> -       zerr("%s: restricted", v->pm->node.nam);
> -       return;
> -    }
>      switch (PM_TYPE(v->pm->node.flags)) {
>      case PM_SCALAR:
>      case PM_ARRAY:
> @@ -2888,11 +2875,6 @@ setarrvalue(Value v, char **val)
>         freearray(val);
>         return;
>      }
> -    if ((v->pm->node.flags & PM_RESTRICTED) && isset(RESTRICTED)) {
> -       zerr("%s: restricted", v->pm->node.nam);
> -       freearray(val);
> -       return;
> -    }
>      if (!(PM_TYPE(v->pm->node.flags) & (PM_ARRAY|PM_HASHED))) {
>         freearray(val);
>         zerr("%s: attempt to assign array value to non-array",
> @@ -3839,10 +3821,6 @@ unsetparam_pm(Param pm, int altflag, int exp)
>              pm->node.nam);
>         return 1;
>      }
> -    if ((pm->node.flags & PM_RESTRICTED) && isset(RESTRICTED)) {
> -       zerr("%s: restricted", pm->node.nam);
> -       return 1;
> -    }
>
>      if (pm->ename && !altflag)
>         altremove = ztrdup(pm->ename);
> diff --git a/Src/signals.c b/Src/signals.c
> index 2257f862f..ff9797f35 100644
> --- a/Src/signals.c
> +++ b/Src/signals.c
> @@ -451,7 +451,7 @@ zhandler(int sig)
>
>      case SIGINT:
>          if (!handletrap(SIGINT)) {
> -           if ((isset(PRIVILEGED) || isset(RESTRICTED)) &&
> +           if (isset(PRIVILEGED) &&
>                 isset(INTERACTIVE) && (noerrexit & NOERREXIT_SIGNAL))
>                 zexit(SIGINT, ZEXIT_SIGNAL);
>              errflag |= ERRFLAG_INT;
> diff --git a/Src/zsh.h b/Src/zsh.h
> index 5bda04e88..9fcbeb1cb 100644
> --- a/Src/zsh.h
> +++ b/Src/zsh.h
> @@ -1926,7 +1926,7 @@ struct tieddata {
>  #define PM_READONLY_SPECIAL (PM_SPECIAL|PM_READONLY|PM_RO_BY_DESIGN)
>  #define PM_DONTIMPORT  (1<<22) /* do not import this variable              */
>  #define PM_DECLARED    (1<<22) /* explicitly named with typeset            */
> -#define PM_RESTRICTED  (1<<23) /* cannot be changed in restricted mode     */
> +#define PM_RESTRICTED  (1<<23) /* only used in the param/private module    */
>  #define PM_UNSET       (1<<24) /* has null value                           */
>  #define PM_DEFAULTED   (PM_DECLARED|PM_UNSET)
>  #define PM_REMOVABLE   (1<<25) /* special can be removed from paramtab     */
> diff --git a/Test/E01options.ztst b/Test/E01options.ztst
> index 969bd42d5..dcb14e013 100644
> --- a/Test/E01options.ztst
> +++ b/Test/E01options.ztst
> @@ -1013,24 +1013,6 @@
>  >one'quoted'expression
>  >anotherquotedexpression
>
> -# too lazy to test jobs -Z and ARGV0.
> -  (setopt restricted; cd /)
> -  (setopt restricted; PATH=/bin:/usr/bin)
> -  (setopt restricted; /bin/ls)
> -  (setopt restricted; hash ls=/bin/ls)
> -  (setopt restricted; print ha >outputfile)
> -  (setopt restricted; exec ls)
> -  (setopt restricted; unsetopt restricted)
> -  :
> -0:RESTRICTED option
> -?(eval):cd:1: restricted
> -?(eval):2: PATH: restricted
> -?(eval):3: /bin/ls: restricted
> -?(eval):hash:4: restricted: /bin/ls
> -?(eval):5: writing redirection not allowed in restricted mode
> -?(eval):exec:6: ls: restricted
> -?(eval):unsetopt:7: can't change option: restricted
> -
>  # ' emacs deconfusion
>
>    fn() {
> diff --git a/configure.ac b/configure.ac
> index dee62dd5e..5002cca8b 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -248,20 +248,6 @@ AC_ARG_ENABLE(dynamic,
>  AS_HELP_STRING([--disable-dynamic],[turn off dynamically loaded binary modules]),
>  [dynamic="$enableval"], [dynamic=yes])
>
> -dnl Do you want to disable restricted on r* commands
> -ifdef([restricted-r],[undefine([restricted-r])])dnl
> -AH_TEMPLATE([RESTRICTED_R],
> -[Undefine this if you don't want to get a restricted shell
> - when zsh is exec'd with basename that starts with r.
> - By default this is defined.])
> -AC_ARG_ENABLE(restricted-r,
> -AS_HELP_STRING([--disable-restricted-r],[turn off r* invocation for restricted shell]),
> -[if test x$enableval = xyes; then
> -  AC_DEFINE(RESTRICTED_R)
> -fi],
> -AC_DEFINE(RESTRICTED_R)
> -)
> -
>  dnl Do you want to disable use of locale functions
>  AH_TEMPLATE([CONFIG_LOCALE],
>  [Undefine if you don't want local features.  By default this is defined.])




Messages sorted by: Reverse Date, Date, Thread, Author