SMACK Security and Legato
SMACK Overview
SMACK Simplified Mandatory Access Control Kernel allows an administrator to define labels, for resources within a system. Labels on objects are compared with the labels of a task that tries to access them. By default, access is only allowed if the labels match. There are also a set of Smack-reserved labels that follow a different set of rules, which allows most system objects and processes to be unaffected by Smack restrictions. SMACK is designed to secure users and processes which is why it is enabled within the Legato system.
Within Linux files, devices, and other special objects within the filesystem are given permission bits that govern how processes may access these files.
For example, listing the root directory of the current active Legato system:
$ /legato/systems/current $ ll drwxrwxr-x 2 root root 1.9K Sep 27 01:07 apps dr-x---r-x 19 root root 1.4K Sep 27 01:07 appsWriteable drwxrwxr-x 2 root root 2.5K Sep 17 22:44 bin drwxrwxr-x 2 root root 2.1K Sep 27 01:07 config -rw-r--r-- 1 root root 2 Sep 27 01:07 index -rw-rw-rw- 1 root root 37 Sep 27 01:07 info.properties drwxrwxr-x 2 root root 1.5K Sep 17 22:44 lib -rw-r--r-- 1 root root 0 Sep 27 01:07 modified drwxrwxr-x 3 root root 296 Sep 17 22:44 modules -rw-r--r-- 1 root root 4 Sep 27 01:07 status -rw-r--r-- 1 root root 68 Sep 27 01:07 version
The first column of the output shows the permission bits for each file. See this document for more details on how the standard file permissions work in Linux.
File permissions are not enough security for all different potential usages of a production Linux system and security requirements can vary between contexts; the Linux Kernel team implemented a system of plugable security modules, one of which is SMACK.
SMACK is layered on top of the existing security module. When a file is opened for reading, writing, or execution the standard file permission bits are always checked first. If that check passes, then the SMACK security module is queried for access. It is then up to that security module to provide a final allow/deny for that object.
SMACK works by allowing one to apply to files, processes, devices, and resources like sockets a label. When a process tries to open a file, SMACK will read the label of the process requesting the access. The label of the file or object being accessed is then also read. SMACK will then compare those two labels. If the labels match, access is granted. If the labels are different then SMACK iterate over a list of rules. If a rule is found that matches both labels and the access requested then the access is granted. Otherwise the access is denied, and the error is passed back to the requesting process.
While SMACK itself runs entirely within the Linux kernel, there are associated user-space tools and devices that allow one to inspect and change labels as well as update the rules that bind these labels together.
SMACK Labels
There are a number of labels built into SMACK, "_", "^", "*", "?", and "@".
Built in rules for these labels:
1
. All accesses by processes labelled "*" are denied. 2
. All read and execute requests, (no write,) for processes labelled, "^" are permitted. 3
. All read and execute requests, (no write,) on objects labelled, "_" are permitted, no matter what the process label. 4
. Any access requests, (read, write and execute,) on objects labelled, "*" no matter the process label are permitted. 5
. Any accesses on an object that has the same label as the process label are permitted. 6
. Any other accesses are denied, unless there is a user defined rule supplied at runtime.
SMACK labels on File System objects are stored as extended attributes, (xattr.) These extended attributes are a generic way to store extra information to be associated with a file. The labels known to SMACK are:
- security.SMACK64: The label for the file itself. If a file is being accessed then the access check is performed against the label stored in this attribute.
- security.SMACK64EXEC: When a process is started from a file, the label for the new process can be found in this attribute.
- security.SMACK64IPIN: If the object is a socket this label is used control incoming to the socket.
- security.SMACK64IPOUT: If the object is a socket this label is use to control access to the data being sent out from this device.
Getting and Setting Labels
It is possible to read SMACK labels for filesystem (FS) objects. If your process has permission, you can also change labels on FS objects.
For files and sockets and other objects that are directly represented in the file system you can use the Linux tool getfattr
to read a filesystem objects, "extended attributes."
For example I can run getfattr
on my helloWorld app to see the following lables:
# getfattr -dm- helloWorld/ file: helloWorld/ security.SMACK64="framework"
It is in these extended attributes that SMACK stores the label(s) for an object. For regular files they can only have the one label attribute named "security.SMACK64". If the object is a socket it can have three labels, security.SMACK64
, security.SMACK64IPIN
, and security.SMACK64IPOUT
.
In order to examine the labels of running processes you need to go to the process filesystem, under /proc.
For example, in order to display the label of the shell you are currently running in you can issue the following command:
cat /proc/$$/attr/current ; echo
Where the variable $
in the previous line is automatically set by the shell to the PID of the shell's process. If you wish to examine the labels of other processes you need to know their PID. One trick is to use the Linux command pidof
. You supply pidof
the name of a process.
For example, to get the label of the configTree you would issue the command:
cat /proc/`pidof helloWorld`/attr/current ; echo
- Note
- If there are multiple processes of the same name,
pidof
will return a list of PIDs and you may need some other way to determine the PID of the process you want.
If you're writing code to read the label of your own process you can use the self
symlink without needing to know the PID for your process. Simply open the file /proc/self/attr/current
.
You can also do this from the shell, but keep in mind, not all shell commands are built into the shell. Results may differ depending on how you structure your commands.
If for example you run:
cat /proc/self/attr/current ; echo
Instead of the previous:
cat /proc/$$/attr/current ; echo
You will end up with the label of the cat
process and not the shell process.
SMACK Capabilities
Processes can be given a set of capabilities and its the position of these capabilities that allow certain actions to be taken (i.e.; changing labels on files and processes or changing rules).
To modify labels and rules you must have the correct capabilities, by default in the Legato Linux system all process are run by the root user and automatically have this capability.
A good place to read more about SMACK and it's configuration is to check out it's official documentation.
SMACK onlycap
In standard operations, all processes run under the root user are given access to all SMACK labels and have all capabilities enabled. That is any process under root can do pretty much anything it wants with no trouble.
This can be a large security hole. If a process can escalate to running something under the root user, then that potentially malicious code can do anything it wants to the device.
To resolve this we've enabled SMACK onlycap. SMACK onlycap allows the system administrator to designate a single label with heightened privilege. Once this is in effect only the properly labeled processes may change labels and rules and all of the other SMACK rules are always in effect regardless of the user the process is running under.
The Legato makefile includes the option of turning onlycap support on. (Note that you need a Linux system image with the base support enabled.)
To build Legato with onlycap support enabled for the wp76
run:
make wp76xx DISABLE_SMACK_ONLYCAP=0
How SMACK is configured in Legato
The Legato Supervisor and Update Daemon is given the label, "admin". Onlycap is enabled on this label, thus only the supervisor and update daemon will be able to adjust labels and rules. Other framework daemons (serviceDirectory, configTree etc.) are given the SMACK label "framework".
All applications run under their own labels of the form "app.<app-name>". All unsandboxed apps are given rules to give them access that give them read/write access to the system.
SMACK rules are set so IPC bindings between apps work. Here's a code sample of rules to set if a client app needs to access a server app:
On the target, set the rules in the /legato/smack/load2
file.
'clientAppLabel' rw 'serverAppLabel' 'serverAppLabel' rw 'clientAppLabel'
Sandboxed directories are given labels corresponding to the app's access rights to those directory. Generally, an app only has read and execute permission to its sandboxes /bin directory.
Example properties:
owner = root group = root DAC permissions = ------r-x SMACK label = 'AppLabelrx'
The Supervisor also sets up the SMACK rule so the app has the proper access to the directory:
On the target, set the rules in the /legato/smack/load2
file.
'AppLabel' rx 'AppLabelrx'
App's directories are given different labels from the app itself so that if an IPC binding is present. The remote app has access to the local app but doesn't have direct access to the local app's files.
All bundled files within an app's sandbox are given the app's SMACK label. This supports passing file descriptors from one app to another. However, the file descriptor can't be passed onto a third app.
Legato also includes an assistance API to help with working with SMACK, see smack.h for more details.
Limitations
Extended attributes used to store the SMACK label are available on all file systems we currently use with one key feature is missing: when a new file is created, the file should inherit the SMACK label of the creator. Because this feature is missing, our current implementation of SMACK has the following limitations:
- Mqueue file system will always set new files to "_" label. This means we can't control access between apps that use MQueues.
- Tmpfs always sets new files to "*" label. This means we can't totally control access to files created in sandboxes because sandboxes use tmpfs. It's only an issue when file descriptors for the created files are passed over IPC to another app. The other app can then pass that fd onto a third app and so on.
- QMI sockets are currently set to "*" because some apps need to write to them. Ideally, the QMI socket file would be given a label such as "qmi" and a rule would be created to only allow access to the app that requires it. However, there currently isn't a way to specify this in the xdef file.
Troubleshooting
If you encounter problems with SMACK permissions while developing your apps you can enable SMACK auditing. To do this you need to change Kernel build flags and rebuild your Linux image.
In the Yocto wp76 source tree open the file:
kernel/arch/arm/configs/mdm9607_defconfig
Make sure that the following flags are set:
CONFIG_SECURITY_SMACK_BRINGUP=y CONFIG_AUDIT=y CONFIG_AUDITSYSCALL=y
Once done, save/rebuild/install the Linux image.
To enable logging for an app or label of your choice, write the label that's having troubles to the special device file unconfined, for example if your app is named, "myTestApp". You can run the command in your shell:
echo "app.myTestApp" > /legato/smack/unconfined
This will bypass all SMACK rules for any accesses for this label, but if the rule would fail in normal operation the SMACK subsystem will now log the access request and the reason for the failure.
- Note
- You can only install one label at a time.
Copyright (C) Sierra Wireless Inc.