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.
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 |
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 |
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_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() | |
wifi_load_driver() | WifiUtils.cpp |
wifi_unload_driver() | WifiUtils.cpp |
Current
What is currently worked on will be listed here:
Solve problem of setuid/setgid after nuwa forks (requires root)(done: with help of b2gloader)- Remoting wifi operations
Remoting PowerOff()(done)- Remoting Reboot()
- Remoting setpriority()
- Fix screenshot permission denied
- Some /proc/self/ content is usually changeable by the process, after setuid/setgid, those permissions are wrong
- affects b2g process since it tries to change /proc/self/oom_score_adj
- re-exec would solve this, but increases memory usage and would make the b2gloader useless
- Finding more locations in code to remote