Developing systems with a security policy

Updated: April 19, 2023

In most development environments, security policies will need to be revised or updated. For example, your initial attempt at a policy may not account for all desired behavior, or you might add a new program or new version of a program. Although you can capture any new rules that are required by running secpolgenerate again in an unrestricted manner, in most cases it's better to selectively remove restrictions using the configuration file.

Rerunning secpolgenerate in an unrestricted or selectively restricted system again

To generate new rules by rerunning the system in an unrestricted manner, in the startup script, restore the three lines that run secpolgenerate and are described in “Booting the system for the first time.”

In some cases, running the system with no restrictions is not desirable because its behavior departs too far from how the system should behave when it is released, especially if you have deliberately changed the policy to restrict some processes. Instead, you can select which types to remove restrictions from. For example, you have a new version of a GPS tracking process that you want to run as type gps_track_t. Because you are going to issue commands over the console (which the example in “Setting up a system to use security types” starts as a shell running as type console_t), you want it to be unrestricted. To remove the restrictions for these two types only, create a secpolgenerate configuration file secpolgenerate.cfg that contains the following lines:

type gps_track_t unrestricted
type console_t unrestricted

Then, use the following command to start secpolgenerate:

secpolgenerate -t 0 -c conf-file-path

The secpolgenerate utility reads the existing security policy (in /proc/boot/secpol.bin) and then creates a policy file that identifies behavior that is not accounted for in the existing policy. In this example, -t specifies 0 (zero) types because the system has no new types, but specifying 50 like the earlier example would also work. The -t option is required because secpolgenerate does not modify an existing policy unless either -t or -u is used.

When you perform these steps and run a system with an existing policy, the contents of /dev/secpolgenerate/policy changes noticeably. Instead of containing the full security policy as before, it contains only new rules that allow any observed behavior that was not allowed by the original policy. Depending on the results and the desired system behavior, you can take some or all of these rules and apply them to your original policy. For this example, you would likely take the changes indicated for gps_track_t because the rules represent the requirements of a new software version. You would probably ignore rules for console_t because it was unrestricted simply to make development easier and it is unlikely its behavior in that context should be allowed in a system that is shipped to an end user.

Using a configuration file when you develop policies

Using the configuration file to adjust how secpolgenerate operates is a valuable development tool. However, because secpolgenerate reads its configuration file early in the startup when only the IFS is available, you have to rebuild the IFS each time you want to modify the configuration file. Rebuilding the IFS can be difficult. It is easier to have the configuration file on a writable filesystem, but in a system that uses a security policy, any processes that create a filesystem need to run as types and start after secpolgenerate.

For example, the following steps outline a method that overcomes this problem:
  1. Determine a minimal set of resource managers that can be run to provide a writable, persistent filesystem. Because secpolgenerate only ever reads from its configuration file, the filesystem can initially be read-only.
  2. Run this set of resource managers in a basic, insecure fashion.
  3. Start secpolgenerate and have it read its configuration file.
  4. Kill the services that were started previously and then start the system normally.

The following commands illustrate this method. In this case, because the system image has an empty /etc/secpolgenerate.cfg, the normal security policy is enforced. A developer having special needs would boot the system, modify /etc/secpolgenerate.cfg as required, and then reboot:

pci-server --config=/etc/pci_server.cfg
devb-eide blk alloc=demand,auto=partition,vnode=100,ncache=100,noatime,commit=low dos exe=all
waitfor /dev/hd0
mount -t qnx6 /dev/hd0t179 /
secpolgenerate -c /etc/secpolgenerate.cfg -t 0
slay devb-eide pci-server
Although this method slows down system start-up, it is for development purposes only and should be removed for production systems.
Note:

If you use this method to make use of a writable configuration file, secpolgenerate may not start up if you reboot your system and the configuration file contains any errors.

To avoid this problem, after you make any changes to configuration file, run secpolgenerate again using the same command line options as before (run pidin arg to see them). Although secpolgenerate will fail to start because you can't run multiple instances, it will still output any errors relating to its configuration file before it exits.