tame(1), like nice(1) but for permissions

2015-07-20 Thread Jeremy Evans
I'm not sure if this makes sense, since tame(2) was designed to operate
on processes after they have already been initialized, and this would
set the allowed operations before initializing the process.

It's a fairly simple change to get the basics working as shown here,
but it's currently not very useful as more complex programs generally
can't start even if given all current tame(2) permissions.

I mostly did this to get more experience working in the kernel, not
because I think it is a good idea, but I welcome feedback all the same.

First the manual, followed by the code, then the kernel and tame(2)
manpage diff.

Thanks,
Jeremy

   TAME(1) General Commands ManualTAME(1) 

   NAME

   tame - restrict system operations for process

   SYNOPSIS

   tame [-aCcdghIiRSptuw] utility [argument ...]  

   DESCRIPTION

   tame restricts system operations using the tame(2) system call, then
   executes the utility with the given arguments. If the utility attempts to
   perform an operation which was not permitted, it will be killed by the
   system with SIGKILL.
   By default, tame restricts almost all system operations for the executed
   process, allowing only the execution of processes (TAME_EXEC), use of
   stdio (TAME_STDIO), and reading the file system (TAME_RPATH). All flags
   with the exception of -h, -R, and -S allow additional system operations.
   The options that allow additional system operations are as follows, with
   the tame(2) option that they enable:

   -a
   TAME_ABORT

   -C
   TAME_CMSG

   -c
   TAME_CPATH

   -d
   TAME_DNS

   -g
   TAME_GETPW

   -I
   TAME_IOCTL

   -i
   TAME_INET

   -p
   TAME_PROC

   -t
   TAME_TMPPATH

   -u
   TAME_UNIX

   -w
   TAME_WPATH

   The following options restrict system operations that are allowed by
   default:

   -R
   TAME_RW

   -r
   TAME_RPATH

   The -h option displays the usage.
   If the -r option is used, utilty must be the full path to the utility,
   tame will no longer search the PATH to find it, as it will have already
   restricted the permissions that would allow that.

   EXIT STATUS

   The tame utility exits with one of the following values:

   125
   An error occurred.

   126
   The utility was not found or could not be invoked.

   Otherwise, the exit status of tame shall be that of utility.

   EXAMPLES

   Only allow overwriting files that already exist, do not allow creating new
   files:

 $ tame -w cp from to

   SEE ALSO

   tame(2)

   HISTORY

   The tame() system call appeared in OpenBSD 5.8.

   $Mdocdate: $ OpenBSD 5.8   

tame.c:

/*  $OpenBSD: $ */

/*
 * Copyright (c) 2015 Jeremy Evans jer...@openbsd.org
 *
 * 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.
 */

#include err.h
#include stdio.h
#include stdlib.h
#include sys/tame.h
#include unistd.h

__dead void usage(int);

int
main(int argc, char *argv[])
{
char ch;
char *file;
/* TAME_RPATH needed to find process to execute
 * TAME_EXEC needed to execute the process
 * TAME_STDIO needed by almost all processes
 */
int tame_flags = TAME_RPATH | TAME_STDIO | TAME_EXEC;

while ((ch = getopt(argc, argv, aCcdghIiRrptuw)) != -1)
switch (ch) {
case 'a':
tame_flags |= TAME_ABORT;
break;
case 'C':
tame_flags |= TAME_CMSG;
break;
case 'c':
tame_flags |= TAME_CPATH;
break;
case 'd':
tame_flags |= TAME_DNS;
break;
case 'g':
tame_flags |= TAME_GETPW;
break;
case 'I':
tame_flags |= TAME_IOCTL;
break;
case 'i':
tame_flags |= TAME_INET;
break;
case 'p':
tame_flags |= TAME_PROC;
break;
  

Re: tame(1), like nice(1) but for permissions

2015-07-20 Thread Nicholas Marriott
Hi

I'm not sure I can think of many uses for this, tame is not something
you are intended to just apply blindly, do you have any use cases?

I think the -aCcdghIiRSptuw approach is a bad idea and it would be
better to do it with named flags like -o abort,cmsg,cpath. Maybe take a
look at getsubopt(3), although I don't know if that API is in vogue
anymore.

Also adding TAME_EXEC seems like a different change entirely?


On Mon, Jul 20, 2015 at 01:00:00AM -0700, Jeremy Evans wrote:
 I'm not sure if this makes sense, since tame(2) was designed to operate
 on processes after they have already been initialized, and this would
 set the allowed operations before initializing the process.
 
 It's a fairly simple change to get the basics working as shown here,
 but it's currently not very useful as more complex programs generally
 can't start even if given all current tame(2) permissions.
 
 I mostly did this to get more experience working in the kernel, not
 because I think it is a good idea, but I welcome feedback all the same.
 
 First the manual, followed by the code, then the kernel and tame(2)
 manpage diff.
 
 Thanks,
 Jeremy
 
TAME(1) General Commands ManualTAME(1) 
 
NAME
 
tame - restrict system operations for process
 
SYNOPSIS
 
tame [-aCcdghIiRSptuw] utility [argument ...]  
 
DESCRIPTION
 
tame restricts system operations using the tame(2) system call, then
executes the utility with the given arguments. If the utility attempts to
perform an operation which was not permitted, it will be killed by the
system with SIGKILL.
By default, tame restricts almost all system operations for the executed
process, allowing only the execution of processes (TAME_EXEC), use of
stdio (TAME_STDIO), and reading the file system (TAME_RPATH). All flags
with the exception of -h, -R, and -S allow additional system operations.
The options that allow additional system operations are as follows, with
the tame(2) option that they enable:
 
-a
TAME_ABORT
 
-C
TAME_CMSG
 
-c
TAME_CPATH
 
-d
TAME_DNS
 
-g
TAME_GETPW
 
-I
TAME_IOCTL
 
-i
TAME_INET
 
-p
TAME_PROC
 
-t
TAME_TMPPATH
 
-u
TAME_UNIX
 
-w
TAME_WPATH
 
The following options restrict system operations that are allowed by
default:
 
-R
TAME_RW
 
-r
TAME_RPATH
 
The -h option displays the usage.
If the -r option is used, utilty must be the full path to the utility,
tame will no longer search the PATH to find it, as it will have already
restricted the permissions that would allow that.
 
EXIT STATUS
 
The tame utility exits with one of the following values:
 
125
An error occurred.
 
126
The utility was not found or could not be invoked.
 
Otherwise, the exit status of tame shall be that of utility.
 
EXAMPLES
 
Only allow overwriting files that already exist, do not allow creating new
files:
 
  $ tame -w cp from to
 
SEE ALSO
 
tame(2)
 
HISTORY
 
The tame() system call appeared in OpenBSD 5.8.
 
$Mdocdate: $ OpenBSD 5.8   
 
 tame.c:
 
 /*$OpenBSD: $ */
 
 /*
  * Copyright (c) 2015 Jeremy Evans jer...@openbsd.org
  *
  * 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.
  */
 
 #include err.h
 #include stdio.h
 #include stdlib.h
 #include sys/tame.h
 #include unistd.h
 
 __dead void usage(int);
 
 int
 main(int argc, char *argv[])
 {
   char ch;
   char *file;
   /* TAME_RPATH needed to find process to execute
* TAME_EXEC needed to execute the process
* TAME_STDIO needed by almost all processes
*/
   int tame_flags = TAME_RPATH | TAME_STDIO | TAME_EXEC;
 
   while ((ch = getopt(argc, argv, aCcdghIiRrptuw)) != -1)
   switch (ch) {
   case 'a':
   tame_flags |= TAME_ABORT;
   break;
   case 'C':
   tame_flags |= TAME_CMSG;
   break;
   case 'c':
   

Re: tame(1), like nice(1) but for permissions

2015-07-20 Thread Marc Espie
On Mon, Jul 20, 2015 at 10:41:08AM -0600, Theo de Raadt wrote:
  On Mon, Jul 20, 2015 at 12:04:43PM -0400, Ted Unangst wrote:
   chroot is probably the best comparision. yes, we provide a chroot(1), but
  There is no chroot(1). :p
  
   practically nothing uses it. everything is instead calling chroot(2) on 
   its
   own. the things that do use chroot(1) are doing so for specialized 
   namespace
   reasons, not for sandboxing.
  
  I have a huge counter-example: dpb.
  Specifically, chroot(8) does the nice usercontext thingies that would be
  cumbersome to do from perl.
 
 chroot was only used as a partial example.
 
 I have the same concerns with tame(1).
 
 First, it is very premature.  Secondly, TAME_EXEC is a very nasty semantic.
 
 Most importantly the purpose of tame is to allow a programmer to seperate
 their initial-setup from the main-loop processing.  By tagging the unix
 feature-set into a simple effect classifications, it also guides the
 programming of general purpose unix tools, guiding them towards privdrop,
 privsep; or if they have no specific priv-slit happening, at minimum it
 constraints most to files-only or network-only behaviours.
 
 From the outside, a regular user is not going to know the system features
 and semantics that a program uses, not in a detailed fashion.
 
 tame -a firefox doesn't work.  Is tame broken?
 
 We don't need that kind of grief.
 
 
Sorry, should have made things clearer. I just meant that chroot was 
a bad comparison. I can't see any sane use of a tame(1) at the
moment.



Re: tame(1), like nice(1) but for permissions

2015-07-20 Thread Jeremy Evans
On 07/20 09:36, Nicholas Marriott wrote:
 Hi
 
 I'm not sure I can think of many uses for this, tame is not something
 you are intended to just apply blindly, do you have any use cases?

Well, there is the example in the man page. :) But no, currently it's
not very useful, as more complex programs such as sh(1) or perl(1) won't
start even if given all current tame(2) permissions.  For this to be
useful, you'd need to give TAME_EXEC additional permissions such that
you could do `tame -tp sh`, and get a sh that could execute processes,
but not write to the file system or do network access.

And like I said originally, I'm not sure this is a good idea.  It was
just a way for me to get more kernel experience.

 I think the -aCcdghIiRSptuw approach is a bad idea and it would be
 better to do it with named flags like -o abort,cmsg,cpath. Maybe take a
 look at getsubopt(3), although I don't know if that API is in vogue
 anymore.

If this is worthy of more work, the command line options can certainly
be changed.  I just used getopt(3) since it seemed like the easiest
way to handle it.
 
 Also adding TAME_EXEC seems like a different change entirely?

Without TAME_EXEC, you can't call execve(2) to create another process.
There currently isn't a tame(2) permission that allows execing, one had
to be added.

Thanks,
Jeremy



Re: tame(1), like nice(1) but for permissions

2015-07-20 Thread Theo de Raadt
 Sorry, should have made things clearer. I just meant that chroot was 
 a bad comparison. I can't see any sane use of a tame(1) at the
 moment.

No, no no, Ted's comments are completely valid.

You cannot replace the narrow chroot calls in the privsep daemons with
chroot(8) run externally.

Any attempts to do so would degrade security.  Same here with tame.

Same with your pkg building tools.



Re: tame(1), like nice(1) but for permissions

2015-07-20 Thread Ted Unangst
Jeremy Evans wrote:
 
 If this is worthy of more work, the command line options can certainly
 be changed.  I just used getopt(3) since it seemed like the easiest
 way to handle it.

I talked with theo about this some. I'd say it's probably too early, and may
lead us down a weird path, where tame has to record all sorts of state and
watch for certain milestones to be reached. that logic is better kept in the
program.

currently, the tame model is that you modify the program as necessary to work
best with tame. if you're doing that, add the tame calls you want.

as you noticed, programs not expecting to work with tame require very
permissive options and may not work even so.

chroot is probably the best comparision. yes, we provide a chroot(1), but
practically nothing uses it. everything is instead calling chroot(2) on its
own. the things that do use chroot(1) are doing so for specialized namespace
reasons, not for sandboxing.



Re: tame(1), like nice(1) but for permissions

2015-07-20 Thread Theo de Raadt
 On Mon, Jul 20, 2015 at 12:04:43PM -0400, Ted Unangst wrote:
  chroot is probably the best comparision. yes, we provide a chroot(1), but
 There is no chroot(1). :p
 
  practically nothing uses it. everything is instead calling chroot(2) on its
  own. the things that do use chroot(1) are doing so for specialized namespace
  reasons, not for sandboxing.
 
 I have a huge counter-example: dpb.
 Specifically, chroot(8) does the nice usercontext thingies that would be
 cumbersome to do from perl.

chroot was only used as a partial example.

I have the same concerns with tame(1).

First, it is very premature.  Secondly, TAME_EXEC is a very nasty semantic.

Most importantly the purpose of tame is to allow a programmer to seperate
their initial-setup from the main-loop processing.  By tagging the unix
feature-set into a simple effect classifications, it also guides the
programming of general purpose unix tools, guiding them towards privdrop,
privsep; or if they have no specific priv-slit happening, at minimum it
constraints most to files-only or network-only behaviours.

From the outside, a regular user is not going to know the system features
and semantics that a program uses, not in a detailed fashion.

tame -a firefox doesn't work.  Is tame broken?

We don't need that kind of grief.





Re: tame(1), like nice(1) but for permissions

2015-07-20 Thread Marc Espie
On Mon, Jul 20, 2015 at 12:04:43PM -0400, Ted Unangst wrote:
 chroot is probably the best comparision. yes, we provide a chroot(1), but
There is no chroot(1). :p

 practically nothing uses it. everything is instead calling chroot(2) on its
 own. the things that do use chroot(1) are doing so for specialized namespace
 reasons, not for sandboxing.

I have a huge counter-example: dpb.
Specifically, chroot(8) does the nice usercontext thingies that would be
cumbersome to do from perl.