User:Tedd/B2G Supervisor
In FirefoxOS (Boot2Gecko), the main system process, b2g, is running as root user. b2g is exposed to a lot of input that is controlled by a potential attacker, which makes it a good target to escalate to root privileges. Therefore it is desired to have b2g run with non-root privileges (see b2g-no-root). This document should give an overview about potential threats, status of the supervisor development and future work.
Contents
Threats
One of the main questions is, what do we gain by running b2g as non-root user? Here some examples of potential threats of a malicious root user:
- load kernel modules (install a rootkit)
- overclock CPU (physically break the phone)
- modifications that survive a factory reset (for example Cerberus for Android)
- larger attack surface on the kernel
Design
IPC
The supervisor process doesn't share an IPDL connection with b2g, like the app processes and b2g do. Instead it relies on a custom IPC implementation, which suits the needed functionality. For the acutal socket operations, recvmsg() and sendmsg() are used, this gives us the option to transfer file descriptors across the IPC channel.
Message
Messages that are being send across the channel need to have the following format:
#define SV_MESSAGE_MAX_FDS 0x7 ... struct SvMessage { struct SvMessageHeader header; int32_t fds[SV_MESSAGE_MAX_FDS]; char data[0]; };
The header is defined as follows:
struct SvMessageHeader { uint32_t magic; uint32_t id; uint32_t nfds; uint32_t size; uint32_t type; uint32_t opt; };
Message fields:
- header: message header, described below
- fds: integer array that contains up to SV_MESSAGE_MAX_FDS file descriptors
- data: optional sized field that contains additional data of any kind
Header fields:
- magic: static value to identify the beginning of a message
- id: random value, used to acknowledge a packet by including it in the response message
- nfds: number of file descriptors that come with the message
- size: size of the data in the actual message
- type: describes the message kind (more detail later on)
- opt: optional field, is specific to the type
types and opts
Currently the following types along with opt values are supported:
type | opt | comment |
---|---|---|
SV_TYPE_ERROR | SV_ERROR_OK | the operation was completed without any error |
SV_ERROR_MISSING | the message is missing some data for the operation | |
SV_ERROR_INVALID | the message contains invalid data (e.g. wrong number of file descriptors) | |
SV_ERROR_FAILED | the operation has failed | |
SV_ERROR_DENIED | the operation is not allowed | |
SV_ERROR_MEMORY | the operations requires to much memory | |
SV_TYPE_CMD | SV_CMD_WIFI | executes a command regarding wifi |
SV_CMD_REBOOT | executes reboot(...) with whitelisted parameters | |
SV_CMD_SETPRIO | executes setpriority() of given PID/TID, excludes supervisor PID |
Whitelists
List of currently maintained whitelists in the supervisor
Reboot
Allowd values for the reboot() argument
Value | Notes |
---|---|
RB_AUTOBOOT | for restarting the system |
RB_POWER_OFF | for shutting down the system |
Blacklists
List of currently maintained blacklists in the supervisor
setpriority
prohibited PID values for setpriority()
Value | Notes |
---|---|
0 | would change priority of supervisor |
`pidof supervisor` | same as pid = 0 |
Development
b2g has been running with root privileges from the beginning, so developers didn't pay much attention to what they do that requires root permissions. Currently, we drop the privileges of b2g to system and see what doesn't work.
Changes
This section will cover the changes that have been made so far, to the system as well as to the code.
Filesystem
Some directories or files require system as their owner, so that b2g can access them:
Path | Owner | Group | Source code location |
---|---|---|---|
/data/b2g/ | system | root | B2G/system/core/include/private/android_filesystem_config.h |
/data/local/ | system | root | B2G/system/core/rootdir/init.rc |
/system/b2g/ | system | root | B2G/system/core/include/private/android_filesystem_config.h |
This has been added to the filesystem
Path | Permission | Owner | Group | Source code |
---|---|---|---|---|
/system/b2g/supervisor | -r-x------ | root | root | B2G/system/core/include/private/android_filesystem_config.h |
Code
Some things can only be changed during runtime by the program. We need to call setgroups() before lowering our privileges to system, since on Android we can't add the system user to groups by default. After we added ourself to the right groups, we need to call setresuid() to drop all our privileges to system (this includes the EUID, if it isn't dropped as well, we could recover root privileges). We need to add ourself to the following groups (defined in: B2G/system/core/include/private/android_filesystem_config.h).
Group | Reason | Note |
---|---|---|
AID_SYSTEM | allows access to filesystem with system as group | |
AID_MOUNT | allows access to /dev/socket/vold (volume deamon) | check for potential risk |
AID_INPUT | allows access to /dev/input/* | check for potential risk |
AID_SHELL | allows access to files by this group | |
AID_INET | allows calling socket() | |
AID_NET_BT | allows creating bluetooth sockets | |
AID_NET_ADMIN | allows calling setsockopt() |
Changes to existing code might also be necessary, all changes are maintained in the following list, along with the reason.
Location | Change | Reason | Comment |
---|---|---|---|
marionettecomponent.js | change 666 to 6666 | bind() on port < 1024 requires root | port 666 is an arbitrary choice, free to change |
Remoting
This section covers all the operations that need to be remoted, and ideally the code location that needs to be changed to do so.
Opreation | Code locations |
---|---|
PowerOff() | LinuxPower.cpp |
Reboot() | LinuxPower.cpp |
setpriority() | GonkHal.cpp |
wifi_load_driver() | WifiUtils.cpp |
wifi_unload_driver() | WifiUtils.cpp |
wifi_start_supplicant() | WifiUtils.cpp |
wifi_stop_supplicant() | WifiUtils.cpp |
wifi_connect_to_supplicant() | WifiUtils.cpp |
wifi_command() | WifiUtils.cpp |
Current
What is currently worked on will be listed here:
Priority | What | Notes | Status |
---|---|---|---|
high | find more broken code | identify operations that have to be remoted | |
high | |
implement sync messages, so that child (b2g) can wait for a response from parent (supervisor) | done |
high | |
root is required for setuid/setgid, currently we have nuwa run as root to do so | done |
high | fix WIFI | it seems everything in WifiUtils.cpp needs to be remoted | |
high | update software | find out how updating works and remote root operations | |
med | fix RIL | logcat shows a bunch of permission denied for RIL connect() | |
med | |
done | |
med | remote Reboot() | b2g crashes with SIGSEGV | |
med | proper logging | implement proper logging, not just with #ifdef DEBUG | |
low | |
done | |
low | fix screenshot save | probably can't write to the filesystem, but don't know yet what the problem is | |
low | /proc/self permissions | usually a process is allowed to make some changes to itself (e.g. /proc/self/oom_score_adj), but the permissions are wrong since we drop the privileges without a re-exec |
Notes
This sections contains dumps from raw logs to keep track of the important informations that might come in handy
[pid 2389] open("/sys/module/printk/parameters/time", O_WRONLY|O_LARGEFILE) = -1 EACCES (Permission denied) [pid 2389] open("/proc/2389/oom_score_adj", O_WRONLY|O_LARGEFILE) = -1 EACCES (Permission denied) [pid 2401] unlink("/dev/socket/keystore") = -1 EACCES (Permission denied) [pid 2389] open("/proc/2454/oom_score_adj", O_WRONLY|O_LARGEFILE) = -1 EACCES (Permission denied) [pid 2389] open("/proc/2454/oom_score_adj", O_WRONLY|O_LARGEFILE) = -1 EACCES (Permission denied) [pid 2389] open("/proc/2454/oom_score_adj", O_WRONLY|O_LARGEFILE) = -1 EACCES (Permission denied) [pid 2389] open("/proc/2504/oom_score_adj", O_WRONLY|O_LARGEFILE) = -1 EACCES (Permission denied) [pid 2389] open("/proc/2504/oom_score_adj", O_WRONLY|O_LARGEFILE) = -1 EACCES (Permission denied) [pid 2389] open("/proc/2504/oom_score_adj", O_WRONLY|O_LARGEFILE) = -1 EACCES (Permission denied) [pid 2389] <... open resumed> ) = -1 EACCES (Permission denied) [pid 2389] open("/proc/2454/oom_score_adj", O_WRONLY|O_LARGEFILE) = -1 EACCES (Permission denied) [pid 2389] open("/proc/2454/oom_score_adj", O_WRONLY|O_LARGEFILE) = -1 EACCES (Permission denied) [pid 2389] open("/sys/class/leds/lcd-backlight/brightness", O_RDWR|O_LARGEFILE) = 104 [pid 2389] write(104, "2", 1) = -1 EACCES (Permission denied) [pid 2389] open("/proc/2525/oom_score_adj", O_WRONLY|O_LARGEFILE) = -1 EACCES (Permission denied) [pid 2389] open("/proc/2698/oom_score_adj", O_WRONLY|O_LARGEFILE) = -1 EACCES (Permission denied) [pid 2389] <... open resumed> ) = -1 EACCES (Permission denied) [pid 2723] open("/data/dontpanic", O_RDONLY|O_LARGEFILE|O_DIRECTORY) = -1 EACCES (Permission denied) [pid 2723] open("/data/misc/bluetoothd", O_RDONLY|O_LARGEFILE|O_DIRECTORY) = -1 EACCES (Permission denied) [pid 2723] open("/data/misc/bluetooth", O_RDONLY|O_LARGEFILE|O_DIRECTORY) = -1 EACCES (Permission denied) [pid 2723] open("/data/misc/keystore", O_RDONLY|O_LARGEFILE|O_DIRECTORY) = -1 EACCES (Permission denied) [pid 2723] open("/data/misc/wifi", O_RDONLY|O_LARGEFILE|O_DIRECTORY) = -1 EACCES (Permission denied) [pid 2723] open("/data/misc/dhcp", O_RDONLY|O_LARGEFILE|O_DIRECTORY) = -1 EACCES (Permission denied) [pid 2723] open("/data/misc/audio", O_RDONLY|O_LARGEFILE|O_DIRECTORY) = -1 EACCES (Permission denied) [pid 2723] open("/data/misc/location", O_RDONLY|O_LARGEFILE|O_DIRECTORY) = -1 EACCES (Permission denied) [pid 2723] open("/data/property", O_RDONLY|O_LARGEFILE|O_DIRECTORY) = -1 EACCES (Permission denied) [pid 2723] open("/data/radio", O_RDONLY|O_LARGEFILE|O_DIRECTORY) = -1 EACCES (Permission denied) [pid 2723] open("/data/drm", O_RDONLY|O_LARGEFILE|O_DIRECTORY) = -1 EACCES (Permission denied) [pid 2723] stat64("/data/system/wpa_supplicant", 0x471ef5f0) = -1 EACCES (Permission denied) [pid 2723] stat64("/data/system/wpa_supplicant", 0x471ef5f0) = -1 EACCES (Permission denied) [pid 2389] open("/proc/2504/oom_score_adj", O_WRONLY|O_LARGEFILE) = -1 EACCES (Permission denied) [pid 2389] open("/proc/2525/oom_score_adj", O_WRONLY|O_LARGEFILE) = -1 EACCES (Permission denied) [pid 2389] open("/proc/2525/oom_score_adj", O_WRONLY|O_LARGEFILE) = -1 EACCES (Permission denied) [pid 2389] open("/sys/class/power_supply/battery/capacity", O_RDONLY|O_LARGEFILE) = 196 [pid 2389] write(196, "2", 1) = -1 EACCES (Permission denied) [pid 2389] open("/proc/2454/oom_score_adj", O_WRONLY|O_LARGEFILE) = -1 EACCES (Permission denied) [pid 2743] open("/sys/class/timed_output/vibrator/enable", O_RDWR|O_LARGEFILE) = 130 [pid 2389] write(130, "2", 1) = -1 EACCES (Permission denied) [pid 2389] open("/proc/2525/oom_score_adj", O_WRONLY|O_LARGEFILE) = -1 EACCES (Permission denied)
permissions
ls -la /data/misc drwxrwx--- audio audio 2014-08-11 19:43 audio drwxrwx--- bluetooth bluetooth 2014-08-11 19:43 bluetooth drwxrwx--- bluetooth bluetooth 2014-08-11 19:43 bluetoothd drwxrwx--- dhcp dhcp 2014-08-11 19:43 dhcp drwxrwx--- system gps 2014-08-11 19:43 gpsone_d drwxrwx--x system system 2014-08-11 19:43 keychain drwx------ keystore keystore 2014-08-11 19:43 keystore drwxrwx--- gps gps 2014-08-11 19:43 location drwxrwx--- gps system 2014-08-11 19:43 quipc drwxrwxr-x system system 2014-08-11 19:43 sensors drwx------ system system 2014-08-11 19:43 systemkeys drwxrwx--- system vpn 2014-08-11 19:43 vpn drwxrwx--- wifi wifi 2014-08-20 22:52 wifi ls -la /data/ ... drwx------ root root 2014-08-20 23:12 property drwxr-x--- root log 2014-08-11 19:43 dontpanic drwxrwx--- drm drm 2014-08-11 19:43 drm drwxrws--- radio radio 2014-08-11 19:43 radio ... ls -la /data/system/wpa_supplicant lrwxrwxrwx root root 2014-08-11 19:43 wpa_supplicant -> /data/misc/wifi/wpa_supplicant ls -la /data/misc/wifi/wpa_supplicant srwxrwx--- wifi wifi 2014-08-20 23:11 wlan0 ls -la /data/property -rw------- root root 5 2014-08-11 19:43 persist.dsds.enabled -rw------- root root 1 2014-08-11 19:43 persist.radio.adb_log_on -rw------- root root 1 2014-08-20 23:12 persist.radio.net_pref_0 -rw------- root root 1 2014-08-11 19:43 persist.radio.nv_sms_utc -rw------- root root 1 2014-08-11 19:43 persist.radio.sma_voice_3gpp -rw------- root root 9 2014-08-20 22:39 persist.sys.timezone -rw------- root root 16 2014-08-11 19:43 persist.sys.usb.config