secpollaunch
Launch a process with different privileges
Runs on:
QNX OS
Description:
The secpollaunch utility provides a secure way to allow a process to launch processes with privileges that are different than its own. Like setting the setuid or setgid permission bits for an executable, secpollaunch allows a process to spawn a process with additional privileges but can control more than just the user ID (UID) or group ID (GID) of the spawned process.
Without secpollaunch, if a process needs to spawn another process with different security requirements, it needs both its own privileges and those of the process it spawns. But if the new process is spawned via secpollaunch (either directly or indirectly using a symbolic link), secpollaunch determines which process is spawned as well as its arguments, environment variables, and other properties.
The secpollaunch utility relies on a process having one set of abilities when it runs as root and a different set when it runs as non-root. Having extra abilities in the root set is not an issue because the process can't take advantage of them when it runs as non-root (unless it has the abilities PROCMGR_AID_SETUID or PROCMGR_AID_SPAWN_SETUID that include the range 0). When a process launches a process via secpollaunch, secpollaunch can access these extra abilities and run them in a way that the calling process can't because it is setuid root. Because secpollaunch only runs what it is configured to run, it provides a safe way of allowing a process to run things that require different privileges without allowing the process to make use of those privileges in any other way. It is similar to just using setuid root programs but is more flexible and more secure.
To use secpollaunch:
- The system must use security policies.
- Any process that invokes secpollaunch must be running with a non-root user ID and not have the ability to switch to root.
- The secpollaunch binary must be setuid root.
Setting up a system to use secpollaunch
For a process to invoke secpollaunch, a secpollaunch configuration file that corresponds to its security type is required. For security reasons, the invoking process cannot provide secpollaunch with the configuration file's location. Instead, secpollaunch determines the path based on the security type of the process. The path is always in the following format:
/proc/boot/secpollaunch-type_name.cfg
For example, the following configuration file applies to a process with a security type proctype_t:
/proc/boot/secpollaunch-proctype_t.cfg
To make sure this file is protected appropriately, keep it in the IFS (which ideally is protected by secure boot). However, if it cannot be in the IFS, the path can be a symbolic link (including a process manager symlink) that points elsewhere.
To keep secpollaunch secure, processes cannot be able to affect the configuration files. For example, they are not secure if you mount a writable file system at / or allow processes to attach their channels to anything that includes /proc/boot.
Invoking secpollaunch
When you invoke secpollaunch, you specify the name of the command to run and any arguments that are needed. The command name determines which section in the configuration file contains any alternative arguments and any other configuration such as environment variables.
Use one of the following methods to invoke a program via secpollaunch:
- Invoke secpollaunch directly with the name of the command to
execute as the first argument. For
example:
secpollaunch ping
- Invoke secpollaunch through a symbolic or hard link that ends
with the name of the command to execute.
For example, if the file /system/other_bin/ping is a symbolic link to secpollaunch:
/system/other_bin/ping www.qnx.com
Configuration file format
A secpollaunch configuration file uses a simple, line-based format. Lines that contain only whitespace or whose first non-whitespace character is a pound sign (#) are ignored.The following lines are an example of a configuration file:
# Settings that are used for all commands
[global]
keep_env = TERM HOME
[ping]
cmd = /system/other_bin/ping -c 1 %1
type = ping_t
[make_logs]
cmd = /system/other_bin/generate_logs -c %1 -w %2
creds = 10:20:keep
type = log_gen_t
set_env = PATH=/proc/boot:/system/other_bin:/system/xbin
keep_env = LOGNAME
umask = 0
launch_if = path /dev/socket
Section headings are in square brackets. Settings in a [global] section apply to any command, but can be overridden by values later in the file. All other sections apply when secpollaunch invokes the corresponding command (i.e., the section name was the first command line argument when secpollaunch was invoked or the name in the link that invoked secpollaunch indirectly).
Sections can specify the following options:
- cmd
- A string that contains the command to execute. The first element of the string must be the absolute path of the program to execute. The remainder of the line is a space-separated list of arguments to pass to the program. These arguments can be wrapped in single or double quotes to allow for whitespace.
- dir
- The directory to launch the process in.
- type
- The security type for the new process. By default, the type is unchanged.
- creds
- A string that sets the UID, GID, and supplementary GIDs. The string uses one
of the following formats:
- uid:gid
- uid:gid:gid1[,gid2...]
where uid and gid* are user and group IDs, names from /etc/passwd and /etc/group, or the string keep.
When uid or gid are keep, the UID or GID is unchanged from the parent. However, if gid is keep and uid is a name, the GID of the entry in /etc/passwd is used. If gid1 is keep, the supplementary groups of the parent are used and can be added to.
Omitting creds is the same as specifying keep:keep:keep.
- keep_env
- A space-delimited list of environment variables to preserve. By default, all environment variables are discarded. If you use this option multiple times, each instance adds to the set of environment variables.
- set_env
- A space-delimited list of name-value pairs (format is name=value) that define environment variables to set. Overrides any existing environment variable setting, including any set by a previous instance of set_env.
- umask
- An octal string that defines the file mode creation mask to use. Default is 022.
- options
- A space-separated list of one or more of the following options:
- noaslr — Disable address space layout randomization (ASLR) for the spawned process. By default, it is always enabled.
- preswitch — Indicates that secpollaunch should switch its own type, UID, and GID prior to spawning instead of having posix_spawn() perform the changes. This option is only needed to honor the setuid/setgid behavior when you invoke a setuid or setgid program.
- debug — Output information that can be helpful for diagnosing problems.
- launch_if
-
When you specify this option, the main command is executed only when one or more criteria are satisfied. If you have more than one condition, they must all be met for the main command to be executed. There are two variants for this option: path, and cmd or qcmd.
Below is the syntax for each option:
path option:
cmd or qcmd option:launch_if = [!] path pathname
launch_if = [!] cmd|qcmd command (args)
The difference between using cmd and qcmd: qcmd will redirect stdout and stderr to /dev/null.
Details for each of the options:- path — Checks the existence of pathname. If pathname doesn't exist, the main command is not executed.
-
cmd or qcmd — Checks the return value of executing command
with the given args. The rules for this command and its arguments are the
same as the rules for the main command. The specified command is run as
root. If the return status is non-zero, the main command is not
executed. To reduce potential security issues, PATH
and LD_LIBRARY_PATH variables are set to the configuration values of
_CS_PATH and _CS_LIBPATH.
Notice:Since the cmd and qcmd commands are executed as root, arguments passed to secpollaunch for a launch_if command must be used carefully to avoid potential security issues.
To invert the condition the main function depends on, add!
before the chosen test type. For example, if you wanted to ensure the main command didn't execute when /dev/socket exists:
An example of inverting a qcmd command to have the main command run if io-sock is running:launch_if = ! path /dev/socket
launch_if = ! qcmd slay -p io-sock
Examples:
The following configuration file section specifies the configuration for pidin when it is invoked via secpollaunch:
[pidin]
cmd = /system/other_bin/pidin %*
type = pidin_t
It allows any arguments that the invoking process specifies, without the invoking process needing the privileges required to execute the commands. The privileges are given to the spawned process by secpollaunch. For example, to show the environment of random:
secpollaunch pidin -p random env
However, using %* allows unrestricted access to pidin (other than restrictions applied by using the pidin_t type). The following example sections also configure pidin, but restrict the permitted arguments:
[pidin_state]
cmd = /system/other_bin/pidin -p %1
type = pidin_t
[pidin_type]
cmd = /system/other_bin/pidin -p %1 -f _
type = pidin_t
With this configuration, when a process uses the following command to run pidin_state, only the single argument—which has to be a process ID or process name that -p takes—is substituted:
secpollaunch pidin_state random
Similarly, when a process uses the following command to run pidin_type, secpollaunch gets the process name from the invoking process and the value that -f takes from the configuration file.
secpollaunch pidin_type random