Control a process's ability to perform certain operations
#include <sys/procmgr.h> extern int procmgr_ability( pid_t pid, unsigned ability, ... );
- The process ID of the process whose abilities you want to control,
or 0 to control those of the calling process.
You need to be running as root in order to change a different process's abilities.
- A list of the abilities.
Each ability in the list is composed of three separate components that
are ORed together:
- An identifier (PROCMGR_AID_*) that tells procnto which particular ability you're modifying.
- One or more operations (PROCMGR_AOP_*) that identify the operation you're performing on the ability.
- One or more domains (PROCMGR_ADN_*) that indicate whether you're modifying what you can do with the ability while running as root or non-root.
Terminate the list with PROCMGR_AID_EOL.
- lower, upper
- If the ability is for a subrange (see below), follow it by two uint64_t arguments that specify the lower and upper limits on the range.
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_CLOCKPERIOD||Yes||Change the clock period, using ClockPeriod()||Allowable periods, in nanoseconds|
|PROCMGR_AID_CLOCKSET||Yes||Set the clock, using clock_settime() , ClockAdjust() , or ClockTime()||Allowable times, in nanoseconds|
|PROCMGR_AID_CONFSET||Yes||Set configuration strings, using confstr()||Allowable names (_CS_*)|
|PROCMGR_AID_CPUMODE||Yes||Change the CPU's power management mode||Allowable modes|
|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()||—|
|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_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_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|
The maximum is usually 63, but is governed by the -P option to procnto .
|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_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_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|
||Allowable user IDs|
|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_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_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:
- Disallow the performance of the operation in the specified domain(s).
- Allow the performance of the operation in the specified domain(s). You must be root when doing this for privileged abilities.
- Restrict the feature to set its parameter to a certain subrange
in the specified domain(s).
You must still have the PROCMGR_AOP_ALLOW flag
set for the ability in the domain to successfully use the feature.
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.
- Lock the current ability so that no further changes to it can be made.
- The changes to the ability are inherited across a spawn or exec.
- The changes to the ability aren't inherited across a spawn or exec. This is the default.
You must OR in at least one of the following for the domain portion:
- Modify the ability of the process when it's running as root.
- Modify the ability of the process when it isn't running as root.
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.
- The abilities were successfully modified.
- There's something wrong with the parameters to the function.
- A non-root process tried to give itself a privileged ability or tried to change a locked ability.
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:
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);