Security/Tizen 2.X Smack Developer Guide

From Tizen Wiki
Jump to: navigation, search

Defining labels and rules

Manifest for declaring Smack labels and rules

Manifest defines domain and declares rules for rpm packages. If there is no manifest in the package, all files will be labeled as default which is "_". Following link explains manifest file in detail.
Application|Installation and Manifest

Tip: Developer can assign label for group of files by using wild card, '*'. This can be used for same sense we use wildcard for file operation in command line tools.

Note

Note: Recursion is not supported


Following examples show typical mistakes mistakes and the correct usage.

 <assign>
    <filesystem path="/usr/lib/*" label="System" />    (O) -> * is declared in the end of path (means all files in /usr/lib directory)
    <filesystem path="/usr/lib/*.so" label="System"/>  (X) -> * is declared in front of extension type; .so (cannot cover all files of same file extension)
    <filesystem path="/usr/lib/*/*/*" label="System"/> (X) -> * is declared three times (cannot cover all files recursively)
 </assign>

Installing rule file without using manifest

Even though we don't recommend to apply, it is possible to drop Smack rule file into /etc/smack/accesses.d directory directly.

Note

Note: Smack rule file does not support comment feature. Smack rule will not be loaded properly if any incorrect formatted Smack rule file exists.


Smack Label

Inheriting identity and permission from the parent process is a natural access control policy for Unix based operating system. Smack also behaves same so there are a few ways to labeling files and processes.

When a process is being executed by exec() family, the label of the launched process inherits the label of the parent process.

 Process A ---------[exec()]---------> execution file  ----[inherit label A]----> process B
 (Label : A)                        (without exec label)                         (Label : A)

If you want to override the inheritance of the process label, you should use exec label.

 Process A ---------[exec()]---------> execution file  ---[set exec label, B]---> process B
 (Label : A)                        (with execution label; B)                    (Label : B)

Linking a shared library is not an execution process. Only read permission is required to link the library.

 Process A ----------[link]-----------> library file  ---------------------> process A
 (Label : A)                                                                (Label : A)

When a file is created by a process, Smack label of the file is inherited from the process.

 Process A ---------[create]---------> file
 (Label : A)                       (Label : A)

When a file is created under a certain directory which has transmute on and process has transmute rule to the label of the directory, then Smack label of the created file is same as the directory.

 sh-4.1# chsmack /opt/home/app
 /opt/home/app access="system::homedir" transmute="TRUE"
 
 sh-4.1# cat /sys/fs/smackfs/load2 | grep A | grep system::homedir
   A system::homedir rwxat
 Process A ---------[create]---------> file under /opt/home/app
 (Label : A)                           (Label: system::homedir)

Warning to use exec label

Exec label is useful for setting process label regardless who invokes the process. On the other hand it requires careful design to prevent privilege escalation. If your module provides to execute arbitrary executable, you have to consider this security issue.
Here is an example and prevention method.

There is an executable file /usr/bin/dbus-launch, which executes arbitrary executable files, the example Smack label is shown below.

sh-4.1# chsmack /usr/bin/dbus-launch
access="dbus" execute="dbus"

Since dbus-launch can execute any exutable, it can execute a shell process with example option below.

dbus-launch --sh-syntax /bin/sh

You can notice that dbus-launch's exec label is "dbus", so a process which is executed by dbus-launch can be labeled as dbus if the executable file does not have exec label. An example with sdb shell is shown below.

    sdbd ----------[execute]-----------> dbus-launch  -------------------------------> sh
(Label : sdbd)                                                                   (Label : dbus)

After this attack, you can acquire a shell in the dbus sandbox with dbus privilege. This is very serious because dbus has rwx rules between all applications, so you will get the access permissions to all the applications.

To prevent this attack, you have to remove exec label from the dbus-launch by Smack manifest like below.

<filesystem path="/usr/bin/dbus-launch" label="_" exec_label="none" />

After the fix, the attack cannot succeed shown as below.

sh-4.1# chsmack /usr/bin/dbus-launch
access="dbus"

    sdbd ----------[exec()]-----------> dbus-launch  ------[inherit label sdbd]-----> sh
(Label : sdbd)                   (without execution label)                       (Label : sdbd)

Rule definition

You should know about all the accesses performed by your module. Here is a list of the access types.

Operation Access type
Open file for read r
Open file for create and write w
Enter into directory / execute a executable file x
Open file for append a
Lock file to make other process cannot access it l
Access directory with transmuted option t

Statements below represent typical access rules.

If process wants to open the file with read and write mode, then define rw.
If process wants to enter into directory, then define execute(x).
If process wants to read database file, then define read and lock(rl). In case of read and write, define read and write(rw).
If process wants to create file in transmuted directory, then define write and transmute(wt).

Defining rule for predefined label is not allowed that the predefined labels imply Smack policy by themselves.

Note

Note: Adding t rule for * is allowed.


Package installation and rule setting

After setting up labels and rules in manifest file, you should build and install the package for test. rpm installer parses and applies the manifest file during installation. Only building the package does not guarantee the validity of the manifest file. rpm-installer creats a Smack rule file in /etc/smack/accesses.d/ directory that the file name is the same as the package name.

Smack rule loading

During boot, Smack rules are loaded by 2 systemd services.
First, /usr/lib/systemd/system/smack.service which is for platform modules.

 [Service]
 Type=oneshot
 ExecStart=/usr/bin/smackload-fast
 ExecStop=/usr/bin/smackctl clear
 RemainAfterExit=yes
 
 [Install]
 WantedBy=basic.target
  • smackload-fast is a command line utility for loading all Smack rule files in /etc/smack/accesses.d/
  • smackctl clear is a command line utility for clearing all Smack rules in the kernel memory

Second /usr/lib/systemd/system/smack-rules.service which is for applications. These rules are assigned during application installation by the rule templates in smack-privilege-config.

 [Unit]
 Description=Smack rules loading
 ConditionSecurity=smack
 Before=starter.service
 
 [Service]
 Type=oneshot
 ExecStart = /bin/bash -c '/usr/bin/sqlite3 /opt/dbspace/.rules-db.db3 < /usr/share/privilege-control/db/load-rules-db.sql | /usr/bin/smack_rules_buffer > /smack/change-rule'
 
 [Install]
 WantedBy=multi-user.target
  • /opt/dbspace/.rules-db.db3 describes all Smack rules for applications.

Smack test

This section describes how developer should check and test Smack related issues.

Smack denial message

When you test your module you may face access denial by Smack policy at any time. In that case, checking Smack denial message is beneficial for the development.


Note

Note: This section only describes denial message of kernel space. Denial message of user space is described in Security server and D-bus Smack

If the process does not have adequate Smack rules, the process is not allowed to access some of the resources and denial of the access is printed on the kernel ring buffer, so you can read the log by running command below.

 sh-4.1# dmesg  | grep SMACK

Note

Note: dmesg is only allowed to root user. Developer should change user to root.


Denial message shows much information about the event, subject, object and access type as well as PID, commandline, and object name such as inode or IP address.

 type=1400 audit(9.800:7): lsm=SMACK fn=smack_inode_permission action=denied mode=enforcing subject="xorg" object="system::homedir" requested=x pid=2456 comm="xrdb" name="app" dev="mmcblk0p22" ino=966

Message above shows that xrdb process tried to access a file ( or a directory) named as "app" with execute mode. Process ID of xrdb is 2456 and inode of app is 966. At first, you should make sure the event is performed by your module. If those information is correct, then you are missing a following rule.

 xorg system::homedir x

Based on the denials you can predict and verify all the possible accesses performed by yout module.

You can load Smack rules temporarily with a command line utility shown below. Smack rules loaded with this command is only valid in kernel memory, so you will loose all the rules after reboot.

 sh-4.1# echo "[subject_label] [object_label] [access_type]" | smackload

OR

 sh-4.1# echo "[subject_label] [object_label] [access_type]" > /sys/fs/smackfs/load2

After adding a rule, you can verify whether the rule is loaded loaded properly by checking texts in /sys/fs/smackfs/load2 by well known command line utility below.

 sh-4.1# cat /sys/fs/smackfs/load2 | grep [subject_label] | grep [object_label]

Label manipulation

If you want to check or change Smack labels for test, there are a few ways to described in this section.

Smack provides command("chsmack") for checking and setting label of file. By the way you need CAP_MAD_ADMIN (simply root) to gain permission to change a Smack label.

Show the label of a file

 chsmack /bin/echo

After executing chsmack, result shows like below.

 access="_"

Set a label of a file

 chsmack -a "*" /bin/echo

Set an execute label of a file (in case of executable file)

 chsmack -e "System" /bin/echo

Remove the execution label of a file

 chsmack -e "" /bin/echo

Set transmute option to a directory

 chsmack -t /opt/home/app

To check a process label, you can simply read a file in /proc file system.

 cat /proc/[PID]/attr/current

To change a process label, you can write your own label into the file in /proc file system.

 echo "testlabel" > /proc/self/attr/current

Note

Note: Changing process Smack label by command line utility is only allowed to a privileged (CAP_MAC_ADMIN, simply root) user and self only.


Ptrace control

When you want to debug applications by attaching ptrace in a Tizen platform, you should gain proper privilege to perform. Smack originally checks Smack rules for attaching ptrace that mutual RW rule is required. But there is a potential weakness to the debugging enviroement because of many RW rules exists, we extended the security check on ptrace and patched it into kernel.

There are three kinds of rules; Default, Exact, Draconian.

 @security/smack/smack.h
 ------------------------
 #define Smack_PTRACE_DEFAULT	0
 #define Smack_PTRACE_EXACT	1
 #define Smack_PTRACE_DRACONIAN	2
 #define Smack_PTRACE_MAX	Smack_PTRACE_DRACONIAN

Default is similar to normal Smack policy based on access Smack rules.In case of PTRACE_READ operation, a subject needs to have a read access on object. For PTRACE_ATTACH operation, a read-write access is required.
Exact limits PTRACE_ATTACH. Only case that subject's and object's labels are equal allows attach. This limit can be overriden with capability; CAP_SYS_PTRACE.
Draconian is similar to exact rule, however, it can not be overriden with CAP_SYS_PTRACE.

If you have CAP_MAC_ADMIN capability(simply root), you can manipulate configuration file in /sys/fs/smackfs/ptrace. Values are 0(Default), 1(Exact) or 2(Draconian).

  # echo "0" > /sys/fs/smackfs/ptrace

In Tizen 2.X, we setup /sys/fs/smackfs/ptrace to "1" (Exact) during boot time. Therefore ptracing arbitrary process is not allowed. Please refer to debugging enviroement.