
Here is a hasher-priv (euid=root,egid=hashman,gid!=egid) control flow:
+ sanitize file descriptors
  + set safe umask
  + ensure 0,1,2 are valid file descriptors
  + close all the rest
+ parse command line arguments
  + check for non-zero argument list
  + parse -h, --help and -number options
    + caller_num initialized here
  + parse arguments, abort if wrong
    + chroot_path and chroot_argv are initialized here
    + valid arguments are:
      getconf
      killuid
      getugid1
      chrootuid1 <chroot path> <program> [program args]
      getugid2
      chrootuid2 <chroot path> <program> [program args]
      makedev <chroot path>
      mount <chroot path> <mount point>
      umount <chroot path>
+ initialize data related to caller
  + caller_uid initialized here from getuid()
    + caller_uid must be valid uid
  + caller_gid initialized here from getgid()
    + caller_gid must be valid gid
  + caller_user initialized here from getpwnam(LOGNAME)->pw_name or
    getpwuid(caller_uid)->pw_name
    + must be true: caller_uid == pw->pw_uid
    + must be true: caller_gid == pw->pw_gid
  + caller_home initialized here
    + caller_user's home directory must exist
+ read work limit hints from environment variables
+ drop all environment variables
+ load configuration
  + safe chdir to /etc/hasher-priv
  + safe load "system" file
    + config format is sequence of name=value lines
    + valid names are:
      user1
      user2
      prefix
      umask
      nice
      allow_ttydev
      allowed_mountpoints
      rlimit_(hard|soft)_*
      wlimit_(time_elapsed|time_idle|bytes_written)
  + safe chdir to "user.d"
  + safe load caller_user file
    + change_user1 and change_user2 should be initialized here
  + if caller_num is defined
    + discard change_user1 and change_user2
    + safe load caller_user:caller_num file
      + change_user1 and change_user2 should be initialized here
  + change_uid1 and change_gid1 initialized from change_user1
  + change_uid2 and change_gid2 initialized from change_user2
+ execute choosen task
  + getconf: print config file /etc/hasher-priv/user.d/caller_user[:caller_num]
  + getugid1: print change_uid1:change_gid1 pair
  + getugid2: print change_uid2:change_gid2 pair
  + killuid
    + check for valid uids specified
    + drop dumpable flag (just in case - not required)
    + setuid to specified uid pair
    + kill (-1, SIGKILL)
    + purge all SYSV IPC objects belonging to specified uid pair
  + chrootuid1/chrootuid2
    + check for valid uid specified
    + safe chdir to chroot_path
    + sanitize file descriptors again
    + if use_pty is disabled, create pipe to handle child's stdout and stderr
    + create pty
    + if X11 forwarding is requested, create socketpair and
      open /tmp/.X11-unix directory readonly for later use with fchdir()
    + unless share_ipc is enabled, isolate System V IPC namespace
    + unless share_uts is enabled, unshare UTS namespace
    + unless share_network is enabled, unshare network
    + chroot to "."
    + clear supplementary group access list
    + set rlimits
    + set close-on-exec flag on all non-standard descriptors
    + fork
      + in parent:
        + setgid/setuid to caller user
        + install CHLD signal handler
        + unblock master pty and pipe descriptors
        + if use_pty is enabled, initialize tty and install WINCH signal handler
        + listen to "/dev/log"
        + while work limits are not exceeded, handle child input/output
        + close master pty descriptor, thus sending HUP to child session
        + wait for child process termination
        + remove CHLD signal handler
        + return child proccess exit code
      + in child:
        + setgid/setuid to specified user
        + setsid
        + change controlling terminal to pty
        + redirect stdin if required, either to null or to pty
        + redirect stdout and stderr either to pipe or to pty
        + set nice
        + if X11 forwarding is requested,
          + add X11 auth entry using xauth utility
          + create and bind unix socket for X11 forwarding
          + send listening descriptor and fake auth data to the parent
        + set umask
        + execute specified program
  + makedev
    + safe chdir to chroot_path
    + safe chdir to dev
    + create devices available to all users: null, zero, full, random, urandom
    + create devices available to root only: console, tty0, fb0
  + maketty
    + safe chdir to chroot_path
    + safe chdir to dev
    + create devices: tty, ptmx
  + mount
    + safe chdir to chroot_path
    + safe chdir to appropriate mount point
    + mount given file system
  + umount
    + for each mount point with chroot_path prefix listed in /proc/mounts
      + safe chdir to chroot_path
      + safe chdir to appropriate mount point
      + lazy unmount current work directory
