Process privileges
In systems where security is important, applications should run with the fewest privileges possible. This practice helps reduce the impact of possible compromises and can also help lower the privilege escalation attack surface of the device.
The more difficult it is for attackers to elevate an application's privileges, the better; forcing attackers to chain multiple attacks against various applications that each have minimal sets of permissions is ideal.
Services usually require a larger set of privileges when they start up. Ideally, they are launched in this more privileged state and then the process itself performs some operation to reduce its privileges once it has completed initialization. There are two ways this usually happens, depending on whether security policies are in use or not.
Dropping privileges with security policies
When the system uses security policies, instead of having a user ID that is
root, services can use a security type to give them the
additional privileges they intially need. After they have completed startup, they
should use secpol_transition_type() to switch to a
lower-privilege security type (see secpol_transition_type()
in the
System Security Guide).
If the service does not call secpol_transition_type() but supports
the -U option (see Dropping privileges without security
policies
for a description), you can use a hybrid approach: the service
starts as root, with a security type, and with
-U. Changing the user ID drops the privileges that are not
needed after startup, with the security type controlling the specific privileges
granted both before and after the change.
For more information on using security policies, including a tutorial for building a
system that uses them, see the Security Policies
chapter in the System Security
Guide.
Dropping privileges without security policies
When the system does not use security policies, services and other system processes usually have to be started as root so that they can perform privileged tasks. To improve security, some of these services and processes implement a command-line option (usually -U) that specifies the user and group IDs to run as.
- -U user_name[,sup_gid]*
- -U uid[:gid[,sup_gid]*]
For example, -U99:98 specifies that the process is to run as user ID 99 and group ID 98. An integration team can assign the appropriate permissions for each user and group.
After the process starts up and carries out any privileged functionality it requires, and possibly obtains capabilities to retain some privileged permissions, it's expected to switch to the user and group IDs specified by -U.
case 'U':
if( set_ids_from_arg( optarg ) != 0 ) {
// insert appropriate logging and error handling
log("Invalid user/group specified [%s]", optarg);
return EXIT_FAILURE;
}
break;
Often you can't call set_ids_from_arg() immediately because the process needs enhanced privileges to start up. In addition, there are often a number of privileges the process needs on an ongoing basis even after it is switched to non-root. In most cases, it is necessary to make one or more procmgr_ability() calls to grant non-root certain privileged abilities and then call set_ids_from_arg() with the value passed as the -U option.