TrustedBSD – Mandatory Access Control

We create open-source because we love it, and we share our finding so everyone else can benefit as well.


TrustedBSD – Mandatory Access Control

The BSD Extended module helps us protect every aspect of FreeBSD’s environment. With Mandatory Access Control, we are able to set explicit permissions on what a user can do, see, and control. What separates this from the usual permissions, is that we can set limit a user or group based on the resource being accessed. Now that’s secure! Of course, let us not get ahead of ourselves. First, we must get the feel of this, and a moderate understanding of how it works before we can really start using it.

The Basics of TrustedBSD MAC

First off, we need to make sure that we have a kernel with the MAC option compiled in. Simply add “options MAC”, and recompile your kernel. Once you have booted off the new kernel, load the BSD Extended module `kldload mac_bsdextended` (the reason we do not compile the module into the kernel itself, is that we can actually lock ourselves out of the system regardless of pure root access).

The tool we will be familiarizing ourselves with will be ugidfw. If you have used ipfw for any decent amount of time, then you will feel very comfortable with this tool. Instead of altering network traffic, we will be altering user/group traffic (If you haven’t used ipfw before, don’t fret, we will be covering the tool enough for any user to understand).


The first thing we’re going to do, is use the ‘list’ argument.

# ugidfw list
0 slots, 0 rules

We don’t have any rules set, but as we progress we can start to see what is being enforced. There are two ways to add a rule to the rule set:

  • ugidfw add
  • ugidfw set rulenum

Add simply adds the rule to the rule set giving it the next highest priority available in the set. Set will set the rule with a specific priority. Since the firewall uses a fall-through method the rules are applied in succession, moving down the list. If you only use add, you may find yourself re-ordering your entire rule set. Even with that in mind, you probably cannot make the perfect rule set without first making some mistakes. When that happens, you’ll want to remove rules.

Removing a rule is very simple, using ugidfw’s remove followed by the rule number. Let’s actually look at how to add rules and apply them:

# ugidfw set 10 subject uid 1000:2000 ! gid 1000 jailid 2 object filesys /usr/ uid_of_subject type rd mode rwx

Since this is a lot to take in, we’ll break it down piece by piece. You’ll soon realize that it really isn’t as bad as it looks. We first set the rule number to 10, then the next part identifies the settings for the subject, in other words the user or group we are applying the rule to. We also give it the user’s uid. In this particular case we gave it a scope of user ids, starting with the lowest to the highest. We also specified that the rule apply to users not in group 1000, meaning our rule applies to user 1000 through 2000, as long as they are not in group 1000. The last part of our subject criteria is the jailid. This tells the system what jail to apply this rule to.

In the 2nd half of our rule, we are allowing or disallowing the object to access. Since we must use mount points we specify the mount point /etc . If we give it something specific to control, we specify how we want to control it. In this case, we first use the theuid_of_subject argument. This tells the system that the subject (the uid) must match the owner of what we are controlling. If the owner happens to be user 1000-2000, they still match the rule, applying the level of access set in the rule.

Access Levels

There are access levels you can give with this argument (per UGIDFW(8)):

a any file type
r a regular file
d a directory
b a block special device
c a character special device
l a symbolic link
s a unix domain socket
p a named pipe (FIFO)

You can see that we only gave access to regular files and directories. We also tell the rule what permission we want to set for the subject. These are very similar to the system permissions, but with a few more options:

a administrative operations
r read access
s access to file attributes
w write access
x execute access
n none

In this rule we gave the subject the basic permissions: read, write, and execute.

TrustedBSD MAC it in Real-World Situations

I’ve made a new user named MacUser with the uid 1002, and the gid 1002 respectively.

Since we can limit a user to what they can or cannot do on each mount point. With TrustBSD’s MAC is a great example of why its beneficial to use multiple partitions. On a NAS, we could restrict users from accessing anything but the files in their network share.

> ls /
COPYRIGHT compat lib rescue usr

# ugidfw set 20 subject uid 1002 object ! filesys /home type rd mode n
# ugidfw set 30 subject uid 1002 object filesys /usr type rd mode rxs

> ls /
ls: dev: Permission denied

With the above we limited the user access to /home. Then we added access to /usr so that they could use basic commands, like ls.

What if we wanted to limit users to their own documents, where they couldn’t traverse other user’s folders? We could do something like this:

> ls -l /home
total 4
drwxr-xr-x 3 MacUser MacUser 512 Jul 4 17:20 MacUser
drwxr-xr-x 29 Syn Syn 1536 Jul 4 16:25 Syn

# ugidfw set 10 subject uid Syn:MacUser object uid Syn:MacUser filesystem /home ! uid_of_subject mode n

user Syn

> ls -l /home
ls: MacUser: Permission denied
total 2
drwxr-xr-x 29 Syn Syn 1536 Jul 4 16:25 Sy

Doing this restricts access to home directories, except to the actual owners. The names are still being used in numerical order just as if we used numbers, using a scope of users. So if there is a file or directory in /home where the owner was Syn through MacUser, and allowed them access to their own folder, but disallowing anyone else outside of the scope access.

For any of you that are familiar with UNIX Domain Sockets or FIFO Pipes, keep in mind you can also restrict these as well in the type field (I will refrain from explaining this only for the reason that the the tutorial would require experience in the C language).

What about the daemon users? Take a look at /etc/rc.bsdextended, and you’ll find each one is set to have rwxs on the entire system by default. You will also notice that all the users >= 1001 are untouched, and everyone else not mentioned is given an explicit rule to have access to nothing at all.

Final Thoughts

Remember that the TrustedBSD module is an overlay to the base permission system. If a folder doesn’t allow someone to write to a folder, you cannot explicitly force write access through the BSD Extended module.

Now that you have a better understanding of how to use this module, you can utilize the the power of this amazing module. While we only skimmed the surface, we cover even more in TrustedBSD : Mandatory Access Control (Part 2) – Processes and TrustedBSD : MAC BIBA – Part 3.

No Comments

Add your comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.