procmgr_ability() calls and the security policy

The secpol-preload.so library allows the security policy that secpolgenerate generates to account for resource managers that use procmgr_ability() to retain any abilities.

Because the use of types to control a process's security capabilities is new with QNX Neutrino 7.0, existing resource managers do not make use of the feature. Instead, many resource managers start up as root and then switch to a non-root user ID after calling procmgr_ability() to retain any abilities they need. Unfortunately, this interacts badly with the preferred approach of having abilities that are locked and inherited. If a program tries to change—or even simply mentions—an ability that is locked in a procmgr_ability() call, the call fails and all requested changes are ignored. In many cases, programs treat this as a fatal error and quit.

The secpol-preload.so library is designed to solve this problem. You are not required to use this library when you use secpolgenerate. However, if you don't use it, processes operate properly when you generate the policy (that is, when secpolgenerate runs in unrestricted mode) but fail when you apply the resulting policy. To avoid this, preload libsecpol-preload.so for every process. The library intercepts all procmgr_ability() calls and sends the details to secpolgenerate. These details allow secpolgenerate to modify the policy to accommodate any process that uses procmgr_ability(). The result is not optimal but is the best that can be done without modifying the affected program.

You can see when the use of procmgr_ability() has been detected by looking for the keywords unlock and noinherit in the generated policy. In most cases, these entries should not be changed because removing unlock will likely make the program fail and removing noinherit might allow processes to inherit elevated abilities.

QNX does not recommend that a program control its own abilities because it often does not control them optimally and there are cases of programs trying to give away abilities they need. To help avoid this problem, secpolgenerate annotates the abilities that it has been forced to leave unlocked with comments that indicate what the procmgr_ability() call was doing. For example, running pps generates the following rules:

allow pps_t self:ability {
    nonroot
    unlock
    noinherit
    # deny all lock
    spawn
    # deny all lock
    fork
    # deny all lock
    prot_exec
    # deny all lock
    pgrp
    # deny all lock
    map_fixed
};    

These rules indicate that even if pps retains the abilities spawn, fork, prot_exec, pgrp, and map_fixed, it likely doesn't matter since pps denies and locks them all anyway.

For another example, io_pkt generates the following rules:

allow io_pkt_t self:ability {
    unlock
    noinherit
    # allow nonroot
    pathspace
    # allow nonroot
    mem_phys
    # allow nonroot
    keydata
    # allow nonroot
    priority
    # allow nonroot
    iofunc/read
    # allow nonroot
    iofunc/dup
    # allow nonroot
    iofunc/exec
};};    

Unlike the set of rules generated by pps, this set indicates potential problems. Abilities such as mem_phys are quite powerful and ideally should be only be held over a limited range. Others such as iofunc/read might be needed but it is not immediately clear why. When processes manipulate abilities themselves via procmgr_ability() calls, they can easily be given abilities that they don't use. In contrast, determining abilities using secpolgenerate gives them abilities that they actually use.

In some cases, programs call procmgr_ability() and continue even if it fails (for example, io-pkt). It is possible to have secpolgenerate ignore procmgr_ability() calls from some types and pay attention to them for others (the equivalent of not preloading libsecpol-preload.so.1 for those programs). To configure this behavior, add a line that uses the following format to secpolgenerate's config file:

type io_pkt_t no_procmgr_ability

Although it is not guaranteed, programs should work correctly with this configuration option as long as they simply ignore the failure rather than modifying their behavior in an attempt to compensate.