Log in

No account? Create an account

Previous Entry Share Next Entry
Introducing the SELinux Sandbox
The other day some of my colleagues and I were discussing a recent request for the Linux Kernel to add "security sandbox" functionality.  We talked about how we could do this with SELinux.  The discussions brought up an old Bug report of my about writing policy for the "little things".  SELinux does a great job of confining System Services, but what about applications executed by users.  The bug report talked about confining grep, awk, ls ...  The idea was couldn't we stop the grep or the mv command from suddenly opening up a network connection and copying off my /etc/shadow file to parts unknown.  

Could we write an SELinux policy that allows users to build scripts to process untrusted content into some output that they could safely use.

cat /tmp/UNTRUSTEDCONTENT | sandbox /sbin/filter.sh > /tmp/SEMITRUSTEDCONTENT

Another possible use case would be to tie sandbox into GRID jobs, or Condor.   I could image an administrator saying that I will allow a grid job to run on my machine but I want SELinux to sandbox the job and make sure it causes no harm to my system, or from my system.  I do not want GRID jobs becoming Spam Bots or somehow attacking the rest of my system.  I definitely do not want them touching my homedir, since that is where firefox stores my credit card data.

I decided to write a policy called sandbox, it took me approximately 10 button clicks using system-config-selinux/polgengui in F11.  I will show you how I did this later in the blog, if you are interested.  You could use runcon to cause unconfined_t user domain to transition to the sandbox_t domain, but I decided to build  a new tool called /usr/bin/sandbox that would do this for you.

The tool and policy are currently available in selinux-policy-3.6.12-41.fc11 and policycoreutils-2.0.62-12.6.fc11.  My current intention with sandbox is not to handle X Apps, since these apps want to write all over the home directory ~/.gconf, ~/gnome., ~/.config ... and all over /tmp, along with use privs to talk to the X Server.  I have some ideas on this for the future that I hope to experiment with.

So what were my security goals in writing sandbox.  
  • Has to be able to execute any binary on the system in a domain called sandbox_t. 
    • Since the goal here is to make a general purpose tool that anyone could use in a script, I did not want to limit the user to a particular app.
  • Can not "Open or Create any files on the system". 
    • Later we added a sandbox_file_t type that sandbox apps can Manage, files, directories, sock_files, fifo_files
    • sandbox_file_t is only currently created if you execute sandbox as root, with the -M flag, this creates a temporary file system mount labeled sandbox_file_t under /mnt
  • Can not use the network. 
  • Should only be able to read a small amount of the system
    • Sandbox_t  needs to be able to read the executables, in order to execute them, we might experiment with using fexece, although there are currently no python bindings.
    • sandbox_t domain to use shared libraries, so sandbox_t can read all libraries on the system.
    • sandbox_t can use any open file descriptors passed to it by the shell, or any other app that would be able to execute the sandbox domain.
      • But it remember it CANNOT OPEN or CREATE any file.
    • The sandbox command can take a --type (-t) qualifier to allow it to run the job with an alternative domain.  So you could write policy to only run sandbox's with out shared libraries, or you could run a sandbox that is able to use one or two network ports.
  • sandbox command has a --mount (-m)  option.  This will mount a tmpfs file system under /mnt, labeled sandbox_file_t, then it cd to  this directory so the sandboxed apps can write to their current working directory.
  • Multiple sandboxes could be running at the same time so we want to make sure they can not interact together, so I added "mcs" protection to them.  Each sandbox runs with a slightly different MCS label meaning that one process can not interfere with another.
  • Sandbox is allowed to write to the terminal, since users would expect this.
One test I have run with it is

> sandbox id -Z

This command shows that sandbox ran the id command under the sandbox_t domain and chose the MCS label s-:c87,c905

If I wanted to create a file of users on my system from the /etc/passwd file, I could try
> sandbox cut -d: -f1 /etc/passwd > /tmp/users
/bin/cut: /etc/passwd: Permission denied

Which shows the sandbox domain is not allowed to open /etc/passwd

But I can execute
> cat /etc/passwd | sandbox cut -d: -f1 > /tmp/users

But if I wanted to use sandbox to read random locations on the system,
> sandbox ls -lZ /tmp
/bin/ls: cannot open directory /tmp: Permission denied
[Exit 2]

I think this is a very powerful concept and could be used to confine random scripts that handle untrusted data, without the admin needing to write much policy.  You can play around with the tool and see what you think, although it will generate lots of AVC messages.

Creating the Sandbox policy.

I ran system-config-selinux, I selected Policy Modules and clicked on New.  When I got to the "Select type of the application/user role to be confined, I selected user application.  Sandbox can be run by administrators or normal users so this made sense.

I called the policy sandbox, I lied about an executable /sbin/sandbox and then

Finally I told the tool to transition from unconfined_u user role

I just clicked to the end and installed the policy using the generated sandbox.sh

I could then use the runcon command to run a random binary as sandbox_t.

Now I went in an started editing the policy, I removed the "permissive sandbox_t" line which the gui tool adds automatically.  I also remove files_read_etc_files.    To make it more tightly locked down,

I added


to allow sandbox_t to use any file on the file system that is handed to the process.

I also added sandbox_file_t type and allows sandbox_t to manage this type.

Say you wanted to create a sandbox domain that can just connect to port 25, you could go through the same steps and when you get to the network connection section you can add the ability to connect to this port.


  • 1
Do you intend to make this a separate package, or merge it into some existing selinux rpm?

Sandbox is in policycoreutils-2.0.62-12.6.fc11.
Policy is in selinux-policy-3.6.12-41.fc11

I also played with MLS levels and "worker-controller" for this...

When I played with SELinux (a while back) I tried something similar...

One approach I looked at was using to use a pipe between two processes, one running in unconfined_t providing services to the "main program" which was in a sandbox restricted to only talking to its parent. This was flawed as effectively I would end up rewriting vast chunks of the user/kernel interface, and piping it between processes.

The other approach I tried, which fits in better with how SELinux works, was to use the MLS security levels. Basically, base system files like libc and other standard libraries can be labelled s0, the "less used" libraries s1, and finally non-operating system files (home directory) would be s2 and above. Programs running in an s3-s3 security context then can read and write user files, running in s1-s1 and below could only see standard system libraries.

Ultimately though, the SELinux model is just not particularly friendly for anyone who isn't building a box from scratch using a system-wide policy. A more accessible model would be the Java sandbox model of "here is a list of files and network locations that my program is expecting to access"...

Still, a few general purpose sandbox types in SELinux wouldn't be a bad idea...

Re: I also played with MLS levels and "worker-controller" for this...

May I know more on MLS level and "worker-controller" ,Is it BLP access policy

Re: I also played with MLS levels and "worker-controller" for this...

You are better off asking questions like this on the

SELinux Developers Mail List


It might be worthwhile to do a simple screencast video (with istanbul or other screen recorder app) of a couple of polgengui usage scenarios that you think people will commonly want to perform. The goal being making people more comfortable working with selinux via the guis.

preventing file reads

in your case how can one prevent unconfined users, root etc. from reading
a file created by the sandbox_t domain?

i was hoping something like the following would work(but it does not):
neverallow {domain -mysandbox_t} mysandbox_rw_t:file *;


Re: preventing file reads

Well the idea is sandbox_t domain is not able to create any files. it is only able to read/write open files handed to the sandbox. Trying to prevent unconfined users from reading sandbox files is not the goal. If you want to have confined users then you need to set those up on your system. I have written previously on how to do this.

Another idea would be to allow you to specify a list of files or directories that were copied into the sandbox filesystem after it was created. And maybe a list of file descriptors you wanted set to particular sockets.

And, of course, ideally you would like to just be able to vet every single access a program tried to make. But that's beyond the scope of what SELinux can do.

Introducing the SELinux Sandbox

User jasper22 referenced to your post from Introducing the SELinux Sandbox saying: [...] passwd > /tmp/users /bin/cut: /etc/passwd: Permission denied Read more: Dan Walsh's Blog [...]

what about limiting memory allocation?

Great article, this might be exactly what I need! I was wondering whether it would be possible to limit the memory each sandboxed process is allowed to allocate.

Re: what about limiting memory allocation?

We have experimented with cgroup integration, but the last time we played with it Firefox would crash for strange reasons.

-C qualifier is still there and you can play with it.

Re: what about limiting memory allocation?

Make that "-c"

  • 1