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: In order to change a different process's abilities, your process needs the PROCMGR_AID_XPROCESS_ABLE ability enabled.
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 a 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 Allocate permanent identifiers for additional named abilities; for more information, see procmgr_ability_create() and procmgr_ability_lookup()
PROCMGR_AID_ABLE_PRIV Yes (QNX Neutrino 7.0.1 or later) Enable a currently denied privileged ability, add subranges to such an ability, or inherit such an ability
PROCMGR_AID_APS_ROOT Yes Execute adaptive partitioning scheduler operations that usually require root permissions; for more information, see SchedCtl()
PROCMGR_AID_CHANNEL_CONNECT Yes Connect to channels belonging to other processes and that have a type ID other than 0. For more information, see Security Policy and Mandatory Access Control chapter of the Security Developer's Guide. Allowable channel type IDs
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_CHROOT Yes Change the root directory by calling chroot().
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 owned by a different process with a different user ID
  • Use a SIGEV_PULSE event to deliver a pulse to a channel in a different process with a different user ID from the process that owns the coid in the pulse event (e.g., with a timer, InterruptAttachEvent(), or SyncMutexEvent())
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 another 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_HIGH_RESOLUTION_TIMER Yes (QNX Neutrino 7.0.1 or later) Set the timer tolerance to a value between 0 and the clock period, by calling timer_settime(), timer_timeout(), TimerSettime(), or TimerTimeout()
PROCMGR_AID_INTERRUPT Yes Attach interrupt handlers by calling InterruptAttach() or InterruptAttachArray(), or events by calling InterruptAttachEvent(). Interrupt sources
PROCMGR_AID_INTERRUPTEVENT Yes (QNX Neutrino 7.0.1 or later) Attach interrupt events by calling InterruptAttachEvent(). Interrupt sources
PROCMGR_AID_IO Yes Request I/O privileges by calling ThreadCtl() with the _NTO_TCTL_IO or _NTO_TCTL_IO_PRIV command. (QNX Neutrino 7.0.1 or later) Level: 0 for _NTO_TCTL_IO, or 1 for _NTO_TCTL_IO_PRIV
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_MAC_POLICY Yes Change the security policy that procnto enforces; see secpolpush in the Utilities Reference
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_POWER Yes Set power-management parameters
PROCMGR_AID_PRIORITY Yes

The maximum unprivileged priority is usually 63, but is governed by the -P option to procnto.

Allowable priorities
PROCMGR_AID_PRIVREG Yes (QNX Neutrino 7.0.4 or later) Use the DCMD_PROC_GETREGSET and DCMD_PROC_SETREGSET devctl() commands to get and set privileged registers in the range from REGSET_STARTPRIV and up. See Controlling processes via the /proc filesystem in the “Processes” chapter of the QNX Neutrino Programmer's Guide.
PROCMGR_AID_PROT_EXEC No Load code by calling dlopen() or map memory as executable by calling mmap(), mmap_device_memory(), or mprotect() with PROT_EXEC Allowable virtual addresses
PROCMGR_AID_PROT_WRITE_AND_EXEC No Simultaneously map memory as writable and executable by calling mmap(), mmap_device_memory(), or mprotect() with PROT_WRITE | 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_QVM Yes Reserved for the hypervisor
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_RLIMIT_PEER Yes Change limits on system resources for other processes. Allowable user IDs
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_SANDBOX Yes Create and delete sandboxes, attach a process to a sandbox, and detach a process from a sandbox.
PROCMGR_AID_SCHEDULE Yes Use SchedCtl() with the SCHED_CONFIGURE command, SchedGet(), sched_getparam(), sched_getscheduler(), SchedSet(), sched_setparam(), or sched_setscheduler() to get or set the scheduling policy and parameters for a process whose user ID is different from the calling process's real or effective user ID
PROCMGR_AID_SERVER_MONITOR Yes Register with the process manager to be notified when servers don't respond to unblock requests promptly enough; see server-monitor in the Utilities Reference.
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 real or effective group ID to values other than its real or effective group ID or its saved set-group ID, by calling setgid(), setegid(), setregid(), or change or delete its supplementary group IDs by calling setgroups() Allowable group IDs
PROCMGR_AID_SETTYPEID Yes Specify a type identifier in a call to posix_spawn or to call procmgr_set_type_id. This ability supports subranges that control which type identifiers a process is able to use. A process may not even spawn a process or set its type to its current type if it lacks the ability. For more information, see Security Policy and Mandatory Access Control chapter of the Security Developer's Guide. Allowable type IDs
PROCMGR_AID_SETUID Yes Set its real or effective user ID to values other than its real or effective user ID or its saved set-user ID, by calling seteuid(), setuid(), or setreuid() Allowable user IDs
PROCMGR_AID_SIGEV_THREAD No (QNX Neutrino 7.0.4 or later) Use a SIGEV_THREAD sigevent. For a registered event, the ability check is done only when you call MsgRegisterEvent(). Other C library functions that are passed a sigevent as an argument do the ability check only for an unregistered SIGEV_THREAD event. These functions include InterruptAttachEvent(), MsgDeliverEvent(), procmgr_event_notify(), procmgr_event_notify_add(), procmgr_value_notify_add(), SyncCtl(), ThreadCtlExt(), TimerCreate(), and TimerTimeout().
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() Allowable group IDs
PROCMGR_AID_SPAWN_SETUID Yes Set the user ID of the child process when using posix_spawn() Allowable user IDs
PROCMGR_AID_SRANDOM Yes Use SysSrandom() to install a source of entropy for the kernel's pseudorandom number generator
PROCMGR_AID_SWAP Yes Enable, disable, or configure the memory swapper
PROCMGR_AID_TIMER Yes 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
PROCMGR_AID_XPROCESS_ABLE Yes (QNX Neutrino 7.0.1 or later) Change the abilities of another process.
PROCMGR_AID_XPROCESS_DEBUG Yes (QNX Neutrino 7.0.1 or later) Open for writing the /proc/pid/as or /proc/pid/ctl files of another process that's running as a different user ID than the requesting process. Doing this is required to debug a process.
Note: This ability does not apply to root processes. A root process can always get write access to the as and ctl files of another process. You can't restrict this operation by setting PROCMGR_AID_XPROCESS_DEBUG | PROCMGR_AOP_DENY | PROCMGR_ADN_ROOT.
User IDs that can be accessed
PROCMGR_AID_XPROCESS_MEM_READ Yes (QNX Neutrino 7.0.1 or later) Open for reading the /proc/pid/as file of another process that's running as a different user ID than the requesting process. This ability is required to create core files, for full pidin functionality, and for debugging another process.
Note: This ability does not apply to root processes. A root process can always get read access to the as file of another process. You can't restrict this operation by setting PROCMGR_AID_XPROCESS_MEM_READ | PROCMGR_AOP_DENY | PROCMGR_ADN_ROOT.
User IDs that can be accessed
PROCMGR_AID_XPROCESS_QUERY Yes
  • Use clock_gettime(), ClockTime(), ConnectFlags(), or TimerInfo() to request information about another process.
  • Open for reading the /proc/pid/* files (except for the as file) of another process that's running as a different user ID than the requesting process.
Allowable user IDs
PROCMGR_AID_XTHREAD_THREADCTL No Use ThreadCtlExt() or ThreadCtlExt_r() to control a thread other than the calling thread. By default, all processes have this ability for all commands (that is, by default a thread is allowed to invoke a ThreadCtlExt() command on a different thread in the same process). _NTO_TCTL_* commands

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 have the PROCMGR_AID_ABLE_PRIV ability enabled to do 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 have the PROCMGR_AID_ABLE_PRIV ability enabled to do 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 has an effective user ID of 0.
PROCMGR_ADN_NONROOT
Modify the ability of the process when it has an effective user ID other than 0.

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.
ENXIO
(QNX Neutrino 7.0 or later) The process indicated by pid is no longer valid. It's going away, has core dumped, or become a zombie.
EPERM
One of the following:
  • A process that does not have PROCMGR_AID_ABLE_PRIV tried to give itself a privileged ability or change a locked ability, or one that does not have PROCMGR_AID_XPROCESS_ABLE tried to change the abilities of another process.
  • One of the specified abilities has a temporary ID (i.e., has PROCMGR_AID_UNCREATED ORed into it).

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 No
Thread Yes