Using security policies
QNX OS security policies use a security policy file to define the rules that grant privileges to processes and the security policy types used to apply the rules to processes and other system elements.
For convenience and efficiency, QNX OS provides the
secpolgenerate utility, which completes most of the work required
to create a security policy for the current system, as well as other tools that manage
and monitor behavior related to security policies. For a detailed description of how to
use secpolgenerate to develop and modify security policies, see
Tutorial: Build a system that uses a security
policy.
Creating and applying a security policy
The following workflow illustrates the security policy mechanism in brief.
- At system build time, create a file (for example,
policy.txt) and add content to it that defines security
policy types and the privileges they have. You can use
secpolgenerate to speed up the creation process. Some
example security policy file
content:
# Type that represents the random process type random_t; # Type to use for the sshd daemon (a client of random) type sshd_t; allow_attach random_t /dev/random; allow sshd_t random_t : channel connect;
- Compile the policy using the secpolcompile utility. For
example:
secpolcompile -o secpol.bin policy.txt
- Include the file in your IFS as /proc/boot/secpol.bin.
- At boot time, use the secpolpush utility to push policy content to procnto.
- Apply the corresponding policy rules by specifying the appropriate security type
when you run a process. For
example:
on -T random_t random -U 22:22
What a policy controls
A system's security policy controls the following privileges:- Operations specified by abilities.
- Which paths can be attached to. For example, a policy can guarantee that the random service and no other process provides /dev/random.
- Which channels a process can connect to. If a policy does not allow a process to connect to a server, a process cannot exploit any bugs that the server might have.
- Operations defined by custom permissions. Security polices can use custom classes and permissions that you define to create fine-grained privilege control that works with your particular system.
Types
Security policy rules use security types to identify processes and the objects that they interact with. In the security policy, the types are represented by names.
For example, the following two rules grant privileges to a process that has the type random_t (most likely the random service). The second rule grants a privilege to a process of type random_t when it interacts with a channel with type devb_t:
allow_attach random_t /dev/random;
allow random_t devb_t : channel connect;
The type devb_t could also be used for a process and grant it privileges via rules. However, because objects such as channels don’t have privileges, those privileges would only apply to processes with that type.
When you compile a policy, the types in the policy are assigned an integer value that is an alternate way to identify a security type. Numbering starts at 0 and increases by one for each type that’s declared.
When you start a process with a type, the system restricts it to the actions given to it by that type's rules (e.g., random started as random_t).
A process can change the rules that apply to it by changing its type (using secpol_transition_type()) and a process can spawn processes as a type other than its own type (using secpol_posix_spawnattr_settypeid()).Specifying types in a security policy
Type names follow the same rules as C identifiers. They can contain alphanumeric characters and the underscore, but must not start with a digit.
All the types that the system requires have to be declared in the policy. Any mistyped names are detected as errors at compilation time.Specifying types in code
Because the type identifiers assigned to types are not fixed, code that uses types should look up the name to convert to an identifier rather than embed a number (using secpol_get_type_id()).Assigning types to processes
Processes started from the ifs start-up script are not automatically fully controlled by a security policy. Although they appear to have a type ID of 0 and are affected by some parts of a policy, they only have the set of abilities that QNX OS assigns by default.
During the startup process, transient commands such as mount can be run without explicit types but anything that runs beyond startup should not. To start processes with explicit types, QNX OS provides the on utility and slm service, though you can also do it via custom services or utilities by using the type ID attribute in calls to posix_spawn().
After a process is started with an explicit type, it is fully controlled by a security policy and any child processes that it creates inherit the parent's type (unless the process explicitly changes it or the policy dictates that type should change). Thus, by making sure that all processes that run past startup have an explicit type, you ensure that the system is fully controlled by the policy, and only processes that the policy fully controls can be created.
To verify that there are no processes running without an explicit type, run pidin -f a_n after startup and check the output to make sure that all processes have a security type.
Processes can change their own type by calling secpol_transition_type() and set the type of processes they spawn by using secpol_posixattr_settypeid(). However, the ability to change their own type or that of their children is controlled by an ability and thus controlled by the policy.
Assigning types to objects
When a policy determines whether an action can be taken, it considers the type of the process that takes the action and the object it acts on.Currently, the only object that QNX OS provides is a channel. The type assigned to a channel determines the types that other processes must have to connect to it.
By default, channels have the type of the process that
creates them. In addition, a security policy can specify which type a channel takes
when a process of a specified type calls resmgr_attach() for a
specific path. For more information, see
Rules for connecting to channels.
You can
add objects that take types as required by defining the object class and the
associated actions in the security policy and then referencing them in policy rules.
For an example of using a custom class that represents an acted-on object (a
mountpoint), see Permission checking by operation and object acted on
in
Customizing permissions using
a security policy.
Controlling type changes
Use the PROCMGR_AID_SETTYPEID ability to:
- control the ability of a process to specify a type identifier when a new process is spawned
- indicate that a process is allowed to change its own type