Control a process's ability to perform certain operations
#include <sys/procmgr.h> extern int procmgr_ability( pid_t pid, unsigned ability, ... );
Terminate the list with PROCMGR_AID_EOL.
libc
Use the -l c option to qcc to link against this library. This library is usually included automatically.
The procmgr_ability() function takes a list of ability operations to control what the identified process is allowed to do. This function lets a process start running as root, set the abilities it needs, and then change its group and user IDs. This can make your system more secure by reducing the number of potentially vulnerable processes running as root.
The table below describes the identifier portion for each ability, indicates whether the operation is normally privileged (e.g. rebooting the system) or not (e.g. spawning and forking), and describes the subrange if applicable. If you want to specify a subrange, include PROCMGR_AOP_SUBRANGE in the operation flags.
Identifier | Privileged? | Controls the process's ability to: | Subrange (optional) |
---|---|---|---|
PROCMGR_AID_CHILD_NEWAPP | Yes | Create a new application ID for a child process by setting POSIX_SPAWN_NEWAPP for posix_spawn() or posix_spawnp(), or SPAWN_NEWAPP for the spawn*() functions. | — |
PROCMGR_AID_CLOCKPERIOD | Yes | Change the clock period, using ClockPeriod() | Allowable periods, in nanoseconds |
PROCMGR_AID_CLOCKSET | Yes | Set the clock, using clock_settime(), settimeofday(), ClockAdjust(), or ClockTime() | Allowable times, in nanoseconds |
PROCMGR_AID_CONFSET | Yes | Set configuration strings, using confstr() | Allowable names (_CS_*) |
PROCMGR_AID_CONNECTION | Yes |
|
— |
PROCMGR_AID_CPUMODE | Yes | Change the CPU's power management mode | Allowable modes |
PROCMGR_AID_DEFAULT_TIMER_TOLERANCE | Yes | Set the default timer tolerance for a process, using procmgr_timer_tolerance() | — |
PROCMGR_AID_EVENT | Yes | Trigger privileged system-wide events, using procmgr_event_trigger() | Trigger bits |
PROCMGR_AID_FORK | No | Create a new process by calling fork() | — |
PROCMGR_AID_GETID | Yes | Get the group ID or session ID of a process outside the calling process's session, by using getpgid() or getsid(), respectively | — |
PROCMGR_AID_INTERRUPT | Yes | Attach interrupt handlers by calling InterruptAttach(), or events by calling InterruptAttachEvent(). You also need I/O privileges; see PROCMGR_AID_IO, below. | Interrupt sources |
PROCMGR_AID_IO | Yes | Request I/O privileges by calling ThreadCtl(_NTO_TCTL_IO, 0) | — |
PROCMGR_AID_KEYDATA | Yes | Pass data through a common client, by calling MsgKeyData(). Resource managers that don't run as root should retain this ability, or else DUP messages will fail. | — |
PROCMGR_AID_MAP_FIXED | No | Use mmap() with MAP_FIXED to map fixed addresses (including zero) | Allowable virtual addresses |
PROCMGR_AID_MEM_ADD | Yes | Add physical memory | Allowable physical addresses |
PROCMGR_AID_MEM_GLOBAL | Yes | Mark shared memory as being global across all processes, by calling shm_ctl() or shm_ctl_special(), specifying SHMCTL_GLOBAL | — |
PROCMGR_AID_MEM_LOCK | Yes | Lock a range of process address space into physical memory, by calling mlock() or mlockall() | Allowable virtual addresses |
PROCMGR_AID_MEM_PEER | Yes | Manipulate a peer process's memory | Peer process IDs |
PROCMGR_AID_MEM_PHYS | Yes |
|
The lower and upper physical address range |
PROCMGR_AID_MEM_SPECIAL | Yes | Call shm_ctl_special() | — |
PROCMGR_AID_PATHSPACE | Yes | Add items to the procnto pathname prefix space, specifically to create symbolic links by calling pathmgr_symlink(), or to register names in the path space by calling resmgr_attach() | — |
PROCMGR_AID_PATH_TRUST | Yes | Modify the list of trusted files and filesystems. For more information, see the entry for pathtrust in the Utilities Reference, as well as the description of PROT_EXEC in the entry for mmap(). | — |
PROCMGR_AID_PGRP | No | Set its process group ID, by calling setpgrp() or procmgr_session(). This ability is enabled by default (for POSIX conformance). You can disable it completely or restrict it to specific pid ranges. | Process IDs |
PROCMGR_AID_PRIORITY | Yes |
The maximum is usually 63, but is governed by the -P option to procnto. |
Allowable priorities |
PROCMGR_AID_PROT_EXEC | No | Load code by calling dlopen() or map memory as executable by calling mmap() with PROT_EXEC | Allowable virtual addresses |
PROCMGR_AID_PUBLIC_CHANNEL | No | Create a public channel by calling ChannelCreate() without setting _NTO_CHF_PRIVATE | — |
PROCMGR_AID_QNET | Yes | Used by Qnet when it creates a channel. | — |
PROCMGR_AID_REBOOT | Yes | Cause the system to reboot by calling sysmgr_reboot() | — |
PROCMGR_AID_RLIMIT | Yes | Use setrlimit() to raise hard limits on system resources | Limits (RLIMIT_*) that it can raise |
PROCMGR_AID_RSRCDBMGR | Yes | Use the rsrcdbmgr*() functions to manipulate the resource database manager | — |
PROCMGR_AID_RUNSTATE | Yes | Use sysmgr_runstate() and sysmgr_runstate_dynamic() to control a CPU's running state | Allowable CPU numbers |
PROCMGR_AID_RUNSTATE_BURST | No | Use sysmgr_runstate_burst() to tell the kernel to turn on any offlined CPUs because the system is about to get busy | The maximum length of time, in milliseconds, for which the process is allowed to set burst mode |
PROCMGR_AID_SCHEDULE | Yes | Use pthread_getschedparam(), SchedGet(), pthread_setschedparam(), or SchedSet() to get or set the scheduling policy for a process whose real or saved user ID is different from the calling process's real or effective user ID | — |
PROCMGR_AID_SESSION | Yes | Use procmgr_session() to change a character terminal's process group or to send a signal to a member of a session group | Allowable session IDs |
PROCMGR_AID_SETGID | Yes | Set its group ID, effective group ID, real and effective group IDs, or supplementary group IDs by calling setgid(), setegid(), setregid(), or setgroups(), respectively | Allowable group IDs |
PROCMGR_AID_SETUID | Yes |
|
Allowable user IDs |
PROCMGR_AID_SIGNAL | Yes |
|
Allowable signals |
PROCMGR_AID_SPAWN | No | Spawn new processes by calling exec*(), spawn*, or posix_spawn() | — |
PROCMGR_AID_SPAWN_SETGID | Yes | Set the group ID of the child process when using posix_spawn() | Lower and upper bounds on the group IDs that the process can set the child process to |
PROCMGR_AID_SPAWN_SETUID | Yes | Set the user ID of the child process when using posix_spawn() | Lower and upper bounds on the user IDs that the process can set the child process to |
PROCMGR_AID_SWAP | Yes | Enable, disable, or configure the memory swapper, pager | — |
PROCMGR_AID_TIMER | Yes |
|
Timer IDs |
PROCMGR_AID_TRACE | Yes | Add handlers for trace events or allocate the instrumented kernel's trace buffers by calling TraceEvent() | — |
PROCMGR_AID_UMASK | Yes | Use umask() to change the file-mode creation mask for a process with a different effective user ID | — |
PROCMGR_AID_V86 | Yes | Call _intr_v86() | — |
PROCMGR_AID_WAIT | Yes | Use wait(), wait3(), wait4(), waitid(), or waitpid() to wait for the status of a terminated child process whose real or saved user ID is different from the calling process's real or effective user ID | Child process IDs |
You must OR in at least one of the following operations:
The meaning of the "parameter" varies, depends on on the ability, as described above.
Follow the ability entry in the function's parameter list with two uint64_t arguments that give the lower and upper bounds of the subrange. You must be root when doing this for privileged abilities.
You can have multiple subrange entries in the list; they "OR" together to let you form a discontiguous set. To do this, specify the identifier-operation-domain argument again, followed by another pair of range arguments.
You must OR in at least one of the following for the domain portion:
There's also a special ability identifier, PROCMGR_AID_EOL, that indicates the end of the list of abilities passed to this function.
You can OR the domain flags and any of PROCMGR_AOP_DENY, PROCMGR_AOP_ALLOW, and PROCMGR_AOP_LOCK into the PROCMGR_AID_EOL macro that ends the list. If you do this, the operations are performed on all the unlocked abilities that you didn't specify in the list.
Remove the ability for a root process to set the user ID when spawning a process:
procmgr_ability(0, PROCMGR_ADN_ROOT|PROCMGR_AOP_DENY|PROCMGR_AID_SPAWN_SETUID, PROCMGR_AID_EOL);
Regain the ability for a root process to set the user ID:
procmgr_ability(0, PROCMGR_ADN_ROOT|PROCMGR_AOP_ALLOW|PROCMGR_AID_SPAWN_SETUID, PROCMGR_AID_EOL);
Drop all abilities while running as root and lock out any further changes:
procmgr_ability(0, PROCMGR_ADN_ROOT|PROCMGR_AOP_DENY|PROCMGR_AOP_LOCK|PROCMGR_AID_EOL);
Allow a non-root process to set the user ID while spawning, but restrict the number to 10000 or higher and lock out any further changes. Remove all other abilities while running as root, and lock any further changes to them as well:
procmgr_ability(0, PROCMGR_ADN_NONROOT|PROCMGR_AOP_ALLOW|PROCMGR_AID_SPAWN_SETUID, PROCMGR_ADN_NONROOT|PROCMGR_AOP_SUBRANGE|PROCMGR_AOP_LOCK|PROCMGR_AID_SPAWN_SETUID, (uint64_t)10000, ~(uint64_t)0, PROCMGR_ADN_ROOT|PROCMGR_AOP_DENY|PROCMGR_AOP_LOCK|PROCMGR_AID_EOL);
Do the same as the above, but specify a discontiguous set of user IDs by using a second PROCMGR_AID_SPAWN_SETUID ability:
procmgr_ability(0, PROCMGR_ADN_NONROOT|PROCMGR_AOP_ALLOW|PROCMGR_AID_SPAWN_SETUID, PROCMGR_ADN_NONROOT|PROCMGR_AOP_SUBRANGE|PROCMGR_AID_SPAWN_SETUID, (uint64_t)1000, (uint64_t)1050, PROCMGR_ADN_NONROOT|PROCMGR_AOP_SUBRANGE|PROCMGR_AOP_LOCK|PROCMGR_AID_SPAWN_SETUID, (uint64_t)2000, (uint64_t)2013, PROCMGR_ADN_ROOT|PROCMGR_AOP_DENY|PROCMGR_AOP_LOCK|PROCMGR_AID_EOL);
Safety: | |
---|---|
Cancellation point | No |
Interrupt handler | No |
Signal handler | Yes |
Thread | Yes |