Re: Exec pledges
> I wrote some patches to allow pledging across execs. > Currently, the exec pledge passes down the process tree. > > The initial version simply inherited the current pledge when > execing with the `pledge("rexec")` promise, but after > discussing with Theo at EuroBSD, a better design was > suggested. Because directory pledges are going to be their > own system call, we can repurpose the second argument of > pledge as the "exec pledge". I have a more substantial version of this change, but I am still iterating the design by studying impact throughout the tree. Not ready to share widely yet.
Re: Exec pledges
On Sun, Oct 08, 2017 at 02:43:48AM -0700, Ori Bernstein wrote: > And pax, because I can > > > > > diff --git bin/pax/ar_io.c bin/pax/ar_io.c > index 40a6492405e..ce53a9ae51b 100644 > --- bin/pax/ar_io.c > +++ bin/pax/ar_io.c > @@ -1281,6 +1281,11 @@ ar_start_gzip(int fd, const char *path, int wr) > /* System compressors are more likely to use pledge(2) */ > putenv("PATH=/usr/bin:/usr/local/bin"); > > + /* Restrict them to sane pledges */ > + if (pledge(NULL, "stdio rpath wpath cpath fattr chown " > + "prot_exec") == -1) > + err(1, "pledge"); > + The pledge(2) arguments are passed in the wrong order here I think. pledge(NULL, ...) to pledge(..., NULL). > if (execlp(path, path, gzip_flags, (char *)NULL) < 0) > err(1, "could not exec %s", path); > /* NOTREACHED */ > -- Kind regards, Hiltjo
Re: Exec pledges
And pax, because I can diff --git bin/pax/ar_io.c bin/pax/ar_io.c index 40a6492405e..ce53a9ae51b 100644 --- bin/pax/ar_io.c +++ bin/pax/ar_io.c @@ -1281,6 +1281,11 @@ ar_start_gzip(int fd, const char *path, int wr) /* System compressors are more likely to use pledge(2) */ putenv("PATH=/usr/bin:/usr/local/bin"); + /* Restrict them to sane pledges */ + if (pledge(NULL, "stdio rpath wpath cpath fattr chown " + "prot_exec") == -1) + err(1, "pledge"); + if (execlp(path, path, gzip_flags, (char *)NULL) < 0) err(1, "could not exec %s", path); /* NOTREACHED */
Re: Exec pledges
Slowcgi. Because if someone could fool it into running the wrong binary, the outcome may be suboptimal. diff --git usr.sbin/slowcgi/slowcgi.8 usr.sbin/slowcgi/slowcgi.8 index d3ab4030bed..f8f07630204 100644 --- usr.sbin/slowcgi/slowcgi.8 +++ usr.sbin/slowcgi/slowcgi.8 @@ -24,6 +24,7 @@ .Nm .Op Fl d .Op Fl p Ar path +.Op Fl P Ar pledge .Op Fl s Ar socket .Op Fl u Ar user .Sh DESCRIPTION @@ -72,6 +73,9 @@ A of .Pa / effectively disables the chroot. +.It Fl P Ar pledge +Restrict all spawned processes to the pledge +.Ar pledge . .It Fl s Ar socket Create and bind to alternative local socket at .Ar socket . diff --git usr.sbin/slowcgi/slowcgi.c usr.sbin/slowcgi/slowcgi.c index a9a90b2db1f..16cfbd1b80a 100644 --- usr.sbin/slowcgi/slowcgi.c +++ usr.sbin/slowcgi/slowcgi.c @@ -275,6 +275,7 @@ main(int argc, char *argv[]) struct passwd *pw; struct stat sb; int c, fd; + const char *execpledge = NULL; const char *chrootpath = NULL; const char *slowcgi_user = SLOWCGI_USER; @@ -303,6 +304,9 @@ main(int argc, char *argv[]) case 'p': chrootpath = optarg; break; + case 'P': + execpledge = optarg; + break; case 's': fcgi_socket = optarg; break; @@ -353,7 +357,7 @@ main(int argc, char *argv[]) setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) lerr(1, "unable to revoke privs"); - if (pledge("stdio rpath unix proc exec", NULL) == -1) + if (pledge("stdio rpath unix proc exec", execpledge) == -1) lerr(1, "pledge"); SLIST_INIT(_proc.requests);
Re: Exec pledges
This is my pledge(1). There are many like it, but this one is mine. When directory pledges land, this should also get support for them. Usage example: pledge stdio echo hello world More complicated, with enough pledges to run awk: pledge "stdio rpath wpath cpath proc exec prot_exec" \ awk 'BEGIN {print "hi"}' diff --git usr.bin/Makefile usr.bin/Makefile index f428c790fe7..d4c506bc918 100644 --- usr.bin/Makefile +++ usr.bin/Makefile @@ -18,7 +18,7 @@ SUBDIR= apply arch at aucat audioctl awk banner \ midiplay mixerctl mkdep mklocale mktemp nc netstat \ newsyslog \ nfsstat nice nm nl nohup openssl pagesize passwd paste patch pctr \ - pkg-config pkill \ + pkg-config pkill pledge \ pr printenv printf quota radioctl rcs rdist rdistd \ readlink renice rev rpcgen rpcinfo rs rup rusers rwall \ sdiff script sed sendbug shar showmount signify skey \ diff --git usr.bin/pledge/Makefile usr.bin/pledge/Makefile new file mode 100644 index 000..cdcccf1af61 --- /dev/null +++ usr.bin/pledge/Makefile @@ -0,0 +1,6 @@ +# $OpenBSD$ + +PROG= pledge +CFLAGS+= -Wall -Werror + +.include diff --git usr.bin/pledge/pledge.1 usr.bin/pledge/pledge.1 new file mode 100644 index 000..e049277fdff --- /dev/null +++ usr.bin/pledge/pledge.1 @@ -0,0 +1,44 @@ +.\" $OpenBSD$ +.\" +.\"Copyright (c) 2017 Ori Bernstein+.\" +.\"Permission to use, copy, modify, and distribute this software for any +.\"purpose with or without fee is hereby granted, provided that the above +.\"copyright notice and this permission notice appear in all copies. +.\" +.\"THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +.\"WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\"MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +.\"ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\"WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\"ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +.\"OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.Dd $Mdocdate: September 4 2017 $ +.Dt PLEDGE 1 +.Os +.Sh NAME +.Nm pledge +.Nd execute commands under a pledge promise +.Sh SYNOPSIS +.Nm pledge +.Ar promise +.Ar command... +.Sh DESCRIPTION +The +.Nm pledge +utility executes the given command with the provided pledge +restrictions. The first argument specifies the +.Ar promise +that the +.Ar command +will be run under. +.Sh HISTORY +The +.Nm +command first appeared in +.Ox 6.2 . +.Sh BUGS +This program does not support directory pledges. +.Sh AUTHORS +.An Ori Bernstein Aq Mt o...@eigenstate.org + diff --git usr.bin/pledge/pledge.c usr.bin/pledge/pledge.c new file mode 100644 index 000..0431df7c7de --- /dev/null +++ usr.bin/pledge/pledge.c @@ -0,0 +1,15 @@ +#include +#include +#include + +int +main(int argc, char **argv) +{ + if (argc < 2) + errx(1, "%s pledge cmd...\n", argv[0]); + if (pledge("stdio exec", argv[1]) == -1) + err(1, "pledge"); + if (execvp(argv[2], [2]) == -1) + err(1, "exec"); + return 0; +}
Exec pledges
I wrote some patches to allow pledging across execs. Currently, the exec pledge passes down the process tree. The initial version simply inherited the current pledge when execing with the `pledge("rexec")` promise, but after discussing with Theo at EuroBSD, a better design was suggested. Because directory pledges are going to be their own system call, we can repurpose the second argument of pledge as the "exec pledge". My use is for sandboxing a bad idea, where arbitrary users can submit code to a sandbox for my pet language, sitting on my website, which gets compiled and run. In the base system, it seems like many programs with pledge("exec") invoke arbitrary binaries on behalf of the user, but there are others (eg, pax) that expect specfic behavior from what they exec. This also could have broader uses -- for example, pledging entire shell scripts. It also helps mitigate the case where an attacker might fool us into exec()ing the wrong binary. This is split into four patches: - Adding kernel+libc support and docs. This changes the signature of pledge, but because everything calls plege("promises", NULL), things keep working. - Add a pledge(1) binary + docs. This allows enforcing arbitrary pledges for a process tree. The minimal pledge for dynamically linked executables is a bit broad ("stdio rpath prot_exec"), due to ld.so, but this is still usefully restrictive. For statically linked executables, we do even better. 'pledge stdio echo hi' works just fine. - The third patch adds the ability to pledge programs running under slowcgi. - The fourth patch exec-pledges pax. I'm not sure I got the pledges right, so more careful review would be appreciated. I grabbed the pledges from compress, which seem to be a superset of the bzip2 pledges. Regress tests would be good to add. I haven't done the work yet, but it's mostly a matter of figuring out how to arrange the makefiles to produce a binary that can be exec'ed. The examples I see all seem to just produce one regress binary. In an appropriate turn of events, this patch was written while sitting in a capsicum talk at EuroBSD. diff --git include/unistd.h include/unistd.h index ffec1538f44..1faf2543f3d 100644 --- include/unistd.h +++ include/unistd.h @@ -522,7 +522,7 @@ int strtofflags(char **, u_int32_t *, u_int32_t *); int swapctl(int cmd, const void *arg, int misc); int syscall(int, ...); int getentropy(void *, size_t); -int pledge(const char *, const char **); +int pledge(const char *, const char *); pid_t __tfork_thread(const struct __tfork *, size_t, void (*)(void *), void *); #endif /* __BSD_VISIBLE */ diff --git lib/libc/sys/pledge.2 lib/libc/sys/pledge.2 index 89884352500..9bfedc3d14b 100644 --- lib/libc/sys/pledge.2 +++ lib/libc/sys/pledge.2 @@ -23,7 +23,7 @@ .Sh SYNOPSIS .In unistd.h .Ft int -.Fn pledge "const char *promises" "const char *paths[]" +.Fn pledge "const char *promises" "const char *execpromises" .Sh DESCRIPTION The current process is forced into a restricted-service operating mode. A few subsets are available, roughly described as computation, memory @@ -31,9 +31,16 @@ management, read-write operations on file descriptors, opening of files, networking. In general, these modes were selected by studying the operation of many programs using libc and other such interfaces, and setting -.Ar promises -or -.Ar paths . +.Ar promises. +.Pp +Specifying +.Ar execpromises +allow the programmer to set the default pledge set for all future +processes process that are execed. This is allows for inheriting +.Fn fork +and +.Fn exec +calls. .Pp Use of .Fn pledge @@ -70,7 +77,7 @@ Passing to .Fa promises or -.Fa paths +.Fa execpromises specifies to not change the current value. .Pp Some system calls, when allowed, have restrictions applied to them: @@ -143,9 +150,7 @@ support: system sensor readings. .Pp .It Fn pledge -Can only reduce permissions; can only set a list of -.Pa paths -once. +Can only reduce permissions. .El .Pp The @@ -467,8 +472,8 @@ Allows a process to call Coupled with the .Va proc promise, this allows a process to fork and execute another program. -The new program starts running without pledge active and hopefully -makes a new +The new program starts running with the requested exec pledges active +and hopefully makes a new .Fn pledge . .It Va prot_exec Allows the use of @@ -556,10 +561,6 @@ Allow operation for statistics collection from a bpf device. .El .Pp -A whitelist of permitted paths may be provided in -.Ar paths . -All other paths will return -.Er ENOENT . At least one promise is required to be pledged in order to activate a whitelist. .Sh RETURN VALUES .Rv -std diff --git regress/sys/kern/pledge/generic/manager.c regress/sys/kern/pledge/generic/manager.c index 451a3ecc088..e6af6b3d69e 100644 --- regress/sys/ke