procmgr_ability()

Control a process's ability to perform certain operations

Synopsis:

#include <sys/procmgr.h>

int procmgr_ability( pid_t pid,
                     unsigned ability, ... );

Arguments:

pid
The process ID of the process whose abilities you want to control, or 0 to control those of the calling process.
Note: You need to be running as root in order to change a different process's abilities.
ability
A list of the abilities. Each ability in the list is composed of three separate components that are ORed together:
  • An identifier (PROCMGR_AID_*, or an custom ability found with procmgr_ability_lookup()) 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.
Note: Terminate the list with the special ability identifier PROCMGR_AID_EOL.

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.

uint64_t lower, uint64_t 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.

Library:

libc

Use the -l c option to qcc to link against this library. This library is usually included automatically.

Description:

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. You can also specify custom abilities that a server has defined by calling procmgr_ability_create().

Note: If you want to set more than one ability, you must specify a separate identifier-operation-domain argument (with any subranges) for each. The identifiers are an enumeration; don't try to OR them together.
Identifier Privileged? Controls the process's ability to: Subrange (optional)
PROCMGR_AID_ABLE_CREATE Yes Create additional abilities; for more information, see procmgr_ability_create()
PROCMGR_AID_APS_ROOT Yes Execute adaptive partitioning scheduler operations that usually require root permissions; for more information, see SchedCtl()
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
  • Use ConnectFlags() to change the connection flags on a coid for another process with a different user ID
  • Use MsgSendPulse() to send a pulse to a channel that was created by a different process with a different user ID
  • Use SyncMutexEvent() with a SIGEV_PULSE sigevent that's going to a channel that was created by a different process with a different user ID
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() or procmgr_event_trigger_updateable() 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) or ThreadCtl(_NTO_TCTL_IO_PRIV, 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 Allowable physical addresses
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. Resource managers need this ability in order to create a public channel when they call dispatch_create_channel() or resmgr_attach(). Programs that aren't resource managers need it in order to create a public channel when they call name_attach(). You might also need this ability when you call message_attach(), pulse_attach(), or select_attach().
PROCMGR_AID_QNET Yes Used by Qnet when it creates a channel.
PROCMGR_AID_RCONSTRAINT No Operate without any resource constraints. For more information, see Resource constraint thresholds in the Processes chapter of the QNX Neutrino Programmer's Guide.
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 SchedGet(), sched_getparam(), sched_getscheduler(), SchedSet(), sched_setparam(), or sched_setscheduler() to get or set the scheduling policy and parameters for a thread 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, or delete existing groups using setgroups() Allowable group IDs
PROCMGR_AID_SETUID Yes
  • Use setuid() to set its user ID and effective user ID to values other than its real or saved-set user ID
  • Use seteuid() to set its effective user ID to a value other than its real or saved-set user ID
  • Use setreuid() to set its user ID to a value other than its effective user ID, and to set its effective user ID to values other than its effective or saved-set user ID
Allowable user IDs
PROCMGR_AID_SIGNAL Yes
  • Attach signal handlers to a process with a different real or effective user ID by calling SignalAction()
  • Set the signal-blocked mask for a process with a different real or effective user ID by calling SignalProcmask()
  • Send signals to a process with a different real or effective user ID by calling kill(), sigqueue(), or SignalKill()
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
  • Call timer_create() or TimerCreate() to create a timer that sends a pulse to a process belonging to a different user
  • Get timer information for a process belonging to a different user and reset overruns by calling TimerInfo()
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 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:

PROCMGR_AOP_DENY
Disallow the performance of the operation in the specified domain(s).
PROCMGR_AOP_ALLOW
Allow the performance of the operation in the specified domain(s). You must be root when doing this for privileged abilities.
PROCMGR_AOP_SUBRANGE
Restrict the feature to set its parameter to a certain subrange in the specified domain(s). The meaning of the parameter 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.

Note the following:

  • You must still have the PROCMGR_AOP_ALLOW flag set for the ability in the domain in order to successfully use the feature.
  • If you don't specify a subrange on an ability, and the ability is allowed, then it's allowed for the entire range.
  • If you specify a subrange on an ability, and the ability is allowed, it's allowed for just the subranges specified.
  • If you specify a subrange on an ability, and the ability is denied, the set subranges are ignored; the ability is denied regardless of the requested range.
  • If you specify the PROCMGR_AOP_SUBRANGE and PROCMGR_AOP_DENY flags together, the ability is denied, but the allowed subranges list (should the ability be enabled in the future) is modified to add the new range listed.
  • 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. For access checks that span a range, the entire range must be covered by a single subrange. For example, the PROCMGR_AID_MEM_PHYS ability with the enabled subranges 100–200 and 190–300 would not allow a request for the subrange 150–250.
  • Subranges can never be deleted once added to an ability. A PROCMGR_AOP_DENY doesn't delete any subranges associated with the ability being dropped. Any request to set a subrange adds to the list of allowed subranges.
PROCMGR_AOP_LOCK
Lock the current ability so that no further changes to it can be made.
PROCMGR_AOP_INHERIT_YES
The changes to the ability are inherited across a spawn or exec.
PROCMGR_AOP_INHERIT_NO
The changes to the ability aren't inherited across a spawn or exec. This is the default.
Note: For a fork(), the parent's ability configuration is copied to the child verbatim, regardless of the INHERIT status of each of the abilities.

You must OR in at least one of the following for the domain portion:

PROCMGR_ADN_ROOT
Modify the ability of the process when it's running as root.
PROCMGR_ADN_NONROOT
Modify the ability of the process when it isn't running as root.

Returns:

EOK
The abilities were successfully modified.
E2BIG
The list of abilities is too large. You might not have terminated the list with PROCMGR_AID_EOL.
EINVAL
There's something wrong with the parameters to the function.
EPERM
A non-root process tried to give itself a privileged ability, change a locked ability, or change the abilities for another process.

Examples:

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);

Classification:

QNX Neutrino

Safety:  
Cancellation point No
Interrupt handler No
Signal handler Yes
Thread Yes