Premium App data protection in RDK using AppArmor

Introduction

While RDK6 will be moving to containers to host the Premium Apps, running the Premium Apps with their own User instead of running as root is also a valid option, if its data can be protected.

While setting the permissions strictly to allow only the Premium App user to access its data, Linux permissions are based on DAC (Discretionary Access Control) policy, and therefore any application running as root, or any user logged in as root – through ssh or console – can circumvent the protection and access those data.

With a MAC (Mandatory Access Control) policy, this is preventable, therefore guaranteeing a much better level of security and confidentiality.

There are several MAC frameworks available for Linux, like SELinux or AppArmor. In the case of RDK, AppArmor was selected as the MAC framework of choice.

AppArmor and RDK

AppArmor configuration files for RDK

Default profile

Let’s examine the default profile first. It allows access to most things, then it denies access to the specific paths that should be protected from everyone except the Premium App User.

# Default profile based on the one in meta-cmf-video, with changes to deny access to AmazonPrime/Youtube data
# Herve Jourdain, 2023/07/13
profile default /** flags=(attach_disconnected){
  capability,
  network,
  mount,
  remount,
  umount,
  pivot_root,
  ptrace,
  signal,
  dbus,
  unix,
  /{,**} mrwlk,    # Allows all file access apart from execute permissions
  /{,**} pix,
  change_profile -> **,
  # Deny some sensitive files of /sys
  deny /sys/f[^s]*/** wklx,
  deny /sys/fs/[^c]*/** wklx,
  deny /sys/fs/c[^g]*/** wklx,
  deny /sys/fs/cg[^r]*/** wklx,
  deny /sys/firmware/** wklx,
  # Deny some sensitive files from /proc fs.
  ## Deny write for all files directly in /proc (not in a subdir)
  ## This can be tested by trying to write to /proc/boottime (rejected if it works as expected)
  deny /proc/* w,   
  # deny write to files not in /proc/<number>/** or /proc/sys/**
  deny /proc/{[^1-9],[^1-9][^0-9],[^1-9s][^0-9y][^0-9s],[^1-9][^0-9][^0-9][^0-9/]*}/** w,
  deny /proc/sys/kernel/{?,??,[^s][^h][^m]**} w,  # deny everything except shm* in /proc/sys/kernel/
  deny /proc/sysrq-trigger rwklx,
  deny /proc/kcore rwklx,   
  # deny access to the data files for AmazonPrime/Youtube
  deny /opt/amazonPrime/{,**} rw,
  deny /opt/persistent/rdkservices/Cobalt-0/{,**} rw,
}

As you can see, access to the data for Amazon Prime Video and Youtube has been denied, therefore protecting them from unauthorized access, even by a user with root privilege.

It’s easy to verify, if you log as root via ssh or a console, and try to do:
ls -al /opt/amazonPrime
You will get a Permission denied error!

usr.bin.WPEFramework profile

Let’s now examine the usr.bin.WPEFramework profile, which is at the heart of all applications in RDK, Premium or not.

Now that we have established that no one has access to the Premium Apps data by default, we need to enable access to those data by the Premium Apps Users themselves. However, since there is only 1 profile for WPEFramework and all the apps it launches, how do we prevent the other apps launched by WPEFramework, or WPEFramework itself, to have access to the data from the other apps?

The solution lies in the use of the “owner” keyword, which allows only the User designated as the owner of the files to access those files!

# Manual profile for the AcceleratorUi/AmazonPrime/Youtube/Metrological apps, Herve Jourdain, 2023/07/13
profile usr.bin.WPEFramework /usr/bin/WPEFramework {
    #include "/etc/apparmor.d/inc/soc"
    #include "/etc/apparmor.d/inc/oem"

    signal,
    ptrace,
    capability kill net_admin dac_override dac_read_search setgid setuid sys_admin sys_nice,

    /version.txt r,

    /application/{,**} rmix,

    /{,usr/}bin/{,**} rmix,

    /certificate/{,**} rw,

    /config/{,**} rw,

    /dev/urandom r,
    /dev/tty rw,
    /dev/input/{,**} r,
    /dev/null r,
    /dev/ r,

    /etc/{,**} rm,

    /lib/{,**} rm,

    /proc/cmdline r,
    /proc/cpuinfo r,
    /proc/meminfo r,
    /proc/stat r,
    /proc/sys/kernel/ngroups_max r,
    /proc/sys/kernel/osrelease r,
    /proc/sys/vm/overcommit_memory r,
    /proc/*/auxv r,
    /proc/*/cmdline r,
    /proc/*/fd/ r,
    /proc/*/mounts r,
    /proc/*/maps r,
    /proc/*/net/{,*} r,
    /proc/*/stat r,
    /proc/*/statm r,
    /proc/*/status r,
    /proc/*/task/ r,
    /proc/*/task/*/comm rw,
    /proc/ r,

    /run/{,**} rwmixlk,

    /sys/class/{,**} r,
    /sys/bus/{,**} r,
    /sys/devices/{,**} r,

    /tmp/{,**} rwmixlk,

    /usr/{,*} r,

    /usr/fonts/{,**} r,

    /usr/images/{,**} r,

    /usr/lib/{,**} rm,

    /usr/libexec/{,**} rmix,

    /usr/lua/{,**} rm,

    /usr/sbin/{,**} rmix,

    /usr/share/{,**} rm,

    /usr/shaders/{,**} rm,

    /var/{,**} rl,

    /opt/minidumps/{,**} rw,
    /opt/persistent/{,*} rw,
    /opt/persistent/ds/{,**} rw,
    /opt/persistent/rdkservices/ rw,
    /opt/persistent/rdkservices/HtmlApp/{,**} rwk,
    /opt/persistent/rdkservices/LightningApp/{,**} rwk,
    /opt/persistent/rdkservices/PluginHost/{,**} rwk,
    /opt/persistent/rdkservices/ResidentApp/{,**} mrwixlk,
    /opt/QT/{,**} rwk,
    /opt/secure/{,**} rwk,
    /opt/{,*} rw,
    /opt/www/{,**} rw,
    /home/root/{,**} rw,
    /tsb/{,**} rw,

    # Protect AmazonPrime and Youtube data with "owner"
    owner /opt/amazonPrime/{,**} rw,
    owner /opt/persistent/rdkservices/Cobalt-0/{,**} rwk,

    # Binaries that should be switched to their own profile (or the default profile)
    # Use pix for execution, instead of ix
    /usr/local/rdkTVClient r,
    /usr/local/rdkTVClient pix,
    /usr/local/rdkUpdater_rdk r,
    /usr/local/rdkUpdater_rdk pix,
}

Every binary started from this profile will be started with this profile as well, due to the use of ix for the execution permissions, instead of pix.

If some binaries need to be started in their own profile, we need to add exceptions for them, and give them pix execution permissions.

You may also like...

Popular Posts

Leave a Reply

Your email address will not be published. Required fields are marked *