Secure ROS with AppArmor

### Overview

<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/ba/AppArmor_logo.svg/800px-AppArmor_logo.svg.png" width="100"> <img src="https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcR9lAfz7TkkEf9-HkL5O83urs7-oEUhm849w1xoQQFg-BPfLzYK&usqp=CAU" width="100">

ROS2(Robot Operating System 2) Security has access control via [AppArmor](https://gitlab.com/apparmor/apparmor/-/wikis/home), it is built on top of [Linux Security MNodules](https://en.wikipedia.org/wiki/Linux_Security_Modules), available on Linux 2.6.36.

- [Linux Apparmor Source Code](https://github.com/torvalds/linux/tree/master/security/apparmor)

Here describes the following,

- Background
- [Linux Security Modules](https://en.wikipedia.org/wiki/Linux_Security_Modules)
- AppArmor Tutorial

### Background

UNIX controls permission via user, group and so on as legacy access control. for specific access granted control we used to use root, but root is wide-open permission can access on anything. there was use case, user wants to have certain access permission but not root privileged access permission for security. against this situation, AppArmor or SELinux has been developed.

for my experience,

- SELinux is way more complicated to use, system perspective.
- AppArmor is easier to enable, application perspective.

also these are dependent on use cases, and precisely what you want to protect.

### [Linux Security Modules](https://en.wikipedia.org/wiki/Linux_Security_Modules)

LSM is Linux Kernel security framework. It is provided not only to AppArmor but also SELinux as base security framework in Linux. It is not loadable module, it is statically build with the following configuration.

```
>cat /boot/config-5.3.0-51-generic | grep CONFIG_LSM
CONFIG_LSM_MMAP_MIN_ADDR=0
CONFIG_LSM="yama,integrity,apparmor"
```

as implementation, refer to around https://github.com/torvalds/linux/blob/master/security/apparmor/lsm.c

```
e.g)
static void apparmor_cred_free(struct cred *cred)
{
	aa_put_label(cred_label(cred));
	set_cred_label(cred, NULL);
}
```

These are dedicated AppArmor static functions will be registered as LSM hook callback. LSM provides generic interface to connect backend callbacks which are AppArmor implementation which set label and restrict the access from the application based on profile.

### AppArmor Tutorial

LSM provides limitation and constrain to access based on the user specified profile. So that is user's responsibility to set appropriate access profile.

AppArmor has two modes,

1. Complain
   Access will be checked, but not actually blocked. (such as SELinux permissive mode.)
2. Enforce
   Access will be checked and blocked if not with access permission.

command line tool is available to check current status,

```
# aa-status 
apparmor module is loaded.
42 profiles are loaded.
39 profiles are in enforce mode.
...<snip>
```

profile files are store in /etc/apparmor.d

```
# ls -F /etc/apparmor.d/
abstractions/    sbin.dhclient    usr.lib.libreoffice.program.oosplash     usr.sbin.cups-browsed
cache/           tunables/        usr.lib.libreoffice.program.senddoc      usr.sbin.cupsd
disable/         usr.bin.evince   usr.lib.libreoffice.program.soffice.bin  usr.sbin.ippusbxd
force-complain/  usr.bin.firefox  usr.lib.libreoffice.program.xpdfimport   usr.sbin.rsyslogd
local/           usr.bin.man      usr.lib.snapd.snap-confine.real          usr.sbin.tcpdump
```

let's see what inside of profile,

```
# ls /etc/apparmor.d/usr.bin.man
/etc/apparmor.d/usr.bin.man
```

this profile applied to /usr/bin/man

```
# cat /etc/apparmor.d/usr.bin.test
#include <tunables/global>

profile test /usr/lib/test/test_binary {
    #include <abstractions/base>

    # Main libraries and plugins
    /usr/share/TEST/** r,
    /usr/lib/TEST/** rm,

    # Configuration files and logs
    @{HOME}/.config/ r,
    @{HOME}/.config/TEST/** rw,
}
```

- `r`: read 
- `w`: write
- `m`: memory map executable
- `x`: executable
- `@`: environmental variables, declared in /etc/apparmor.d/abstractions/ or /etc/apparmor.d/tunables/

http://manpages.ubuntu.com/manpages/xenial/man5/apparmor.d.5.html

AppArmor will parse the profile into binary format when loading, so it takes time to be effective. This means boot time will be longer than usual sometimes, so it can cache the binary profile data in the file system.

```
# cat /etc/apparmor/parser.conf
# parser.conf is a global AppArmor config file for the apparmor_parser
#
...<snip>
## Turn creating/updating of the cache on by default
#write-cache
```

uncomment above `write-cache` line to make it faster to boot up, also if you want you can add `cache-loc=/path/to/location` to store the cached data.

### Reference

- https://ubuntu.com/tutorials/beginning-apparmor-profile-development#1-overview
- https://gitlab.com/apparmor/apparmor/-/wikis/home
- https://wiki.archlinux.jp/index.php/AppArmor