Here is a demonstration diff using pledge execpromises in crontab,
regarding the running of $EDITOR.

I hacked it together in 20 minutes, so it may have bugs.

First off an aside -- something which stands in the way a little and
needs to be fixed.  Most folk don't use $EDITOR or $VISUAL and accept
the vi default, but others use them even, and some others are even crazier
and pass options resulting in constructs like "emacs -nw".  20 years ago
the pattern in most software was to execve the variable without expansion,
but since a few programs (and well, scripts) could handle expansion
this was considered inconsistant and there was a move towards using system()
or manual execve of { "sh", "-c", editor, file }

Once that is done, we can set a pledge for the (unaware) editor.

I'm setting "stdio rpath wpath cpath getpw tty error".

Now when I crontab -e, my editor cannot start a subshell. It cannot
use the builtin networking functionality.  It can still access the
filesystem (but pledgepaths is being worked on..)

Now is the time for me to discuss the "error" pledge.  Previously
pledge violations would always result in a fatal head shot.  "error"
indicates we are willing to accept errors, and we trust this software
to be checking it's errors.  

Trust.
emacs.
checking errors.
software that always checks errors.
right.

So be careful out there.  Don't use "error" unless you understand the
ramifications.  I'm not certain I fully understand them either yet.

Index: crontab.c
===================================================================
RCS file: /cvs/src/usr.sbin/cron/crontab.c,v
retrieving revision 1.92
diff -u -p -u -r1.92 crontab.c
--- crontab.c   11 Jan 2016 14:23:50 -0000      1.92
+++ crontab.c   12 Dec 2017 04:39:17 -0000
@@ -532,6 +532,8 @@ done:
        return (error);
 }
 
+#define nitems(_a)     (sizeof((_a)) / sizeof((_a)[0]))
+
 /*
  * Execute an editor on the specified pathname, which is interpreted
  * from the shell.  This means flags may be included.
@@ -541,7 +543,7 @@ done:
 int
 editit(const char *pathname)
 {
-       char *argp[] = {"sh", "-c", NULL, NULL}, *ed, *p;
+       char *argv[100] = {NULL}, **ap, *ed, *oed, *p;
        sig_t sighup, sigint, sigquit, sigchld;
        pid_t pid;
        int saved_errno, st, ret = -1;
@@ -551,9 +553,21 @@ editit(const char *pathname)
                ed = getenv("EDITOR");
        if (ed == NULL || ed[0] == '\0')
                ed = _PATH_VI;
-       if (asprintf(&p, "%s %s", ed, pathname) == -1)
+
+       oed = ed = strdup(ed);
+       fprintf(stderr, "ed=%s\n", ed);
+       for (ap = argv;
+           ap < &argv[nitems(argv) - 1] && (*ap = strsep(&ed, " \t")) != NULL; 
) {
+               fprintf(stderr, "ap = %s\n", *ap);
+               if (**ap != '\0')
+                       ap++;
+       }
+       if (ap >= &argv[nitems(argv) - 2]) {
+               free(oed);
                return (-1);
-       argp[2] = p;
+       }
+       *ap++ = (char *)pathname;
+       *ap = NULL;
 
        sighup = signal(SIGHUP, SIG_IGN);
        sigint = signal(SIGINT, SIG_IGN);
@@ -565,10 +579,15 @@ editit(const char *pathname)
                /* Drop setgid and exec the command. */
                if (setgid(user_gid) == -1) {
                        warn("unable to set gid to %u", user_gid);
-               } else {
-                       execv(_PATH_BSHELL, argp);
-                       warn("unable to execute %s", _PATH_BSHELL);
+                       _exit(127);
+               }
+               if (pledge(NULL,
+                   "stdio rpath wpath cpath getpw tty error") == -1) {
+                       warn("pledge");
+                       _exit(127);
                }
+               execvp(argv[0], argv);
+               warn("unable to execute %s", argv[0]);
                _exit(127);
        }
        while (waitpid(pid, &st, 0) == -1)
@@ -580,6 +599,7 @@ editit(const char *pathname)
                ret = WEXITSTATUS(st);
 
  fail:
+       free(oed);
        saved_errno = errno;
        (void)signal(SIGHUP, sighup);
        (void)signal(SIGINT, sigint);

Reply via email to