COMMAND

    BSD I/O signals

SYSTEMS AFFECTED

    BSDI, NetBSD, OpenBSD, and FreeBSD, IRIX

PROBLEM

    Following  info  is  based  on  OpenBSD  Security  Advisory   from
    September  15,  1997  and  it  covers  vulnerability in I/O Signal
    handling.

    A   vulnerability   discovered   in   the   4.4BSD  kernel  allows
    unprivileged users to send certain signals to arbitrary  processes
    on the  system.   Depending on  the operating  system and targeted
    program, this  may allow  users to  kill off  processes or disrupt
    the operation of certain programs.

    Certain programs  implemented in  Unix operating  systems make use
    of a facility called  "asynchronous I/O" to handle  multiple tasks
    simultaneously. Asynchronous I/O allows  a process to be  notified
    whenever it has data that needs  to be read from an input  source;
    the kernel notifies the process using a signal.

    Asynchronous  I/O  is  enabled  on  a descriptor using the fcntl()
    system call; a descriptor with  the O_ASYNC flag set will  cause a
    signal to  be sent  whenever there  is data  available to  be read
    from it.  Additionally,  using the FIOASYNC ioctl(),  asynchronous
    notification can be enabled on a descriptor.

    In cases where multiple processes  are used in an application,  it
    becomes useful to allow a descriptor to notify other processes  as
    well. This is  accomplished by use  of another fcntl()  operation,
    F_SETOWN, as  well as  an ioctl,  FIOSETOWN (certain  devices also
    provide an interface to  this facility with the  TIOCSPGRP ioctl).
    These operations  allow a  program to  set the  process or process
    group that will receive signal notification of pending I/O.

    A  lack  of  checking  in  the  code that handles these operations
    allows a program to specify  an arbitrary process ID when  using a
    socket  or  device  file  descriptor.  By setting the recipient of
    signal  notification  to  a  process  that  is  not  owned  by the
    program,  the  kernel  can  be  tricked  into signalling arbitrary
    programs.

    Additionally,  vulnerable  kernels  do  not  keep  track  of   the
    credentials associated with a process when determining whether  to
    send I/O signals; because of  this, it is possible to  specify the
    PID of a process  that is owned by  an attacker, and then  destroy
    that process and wait for it's PID to be re-used. The new  process
    occupying  that  PID  can  then  be  signalled  by  the  attacker,
    regardless of it's owner.

    It's  important  to  note   that  operating  systems  that   check
    credentials  when  a  program  attempts  to  set  the  PID for I/O
    notification (thus evading part  of this vulnerability) may  still
    be  vulnerable  to  the  latter  problem  (process  ID re-use), if
    credentials aren't checked at signal delivery time.

    This vulnerability exists due to a lack of credential checking  in
    the  kernel  when  setting  the  recipient  of  I/O  notification.
    BSD-based kernels maintain this information in descriptor-specific
    data structures unrelated to the process table; the  vulnerability
    discussed  here  involves  sockets,  which  maintain  the   signal
    recipient  in  the  per-descriptor  "socket"  structure,  although
    certain devices provide similar facilities and vulnerabilities.

    On 4.4BSD systems,  the signal normally  sent to inform  a process
    of pending  I/O is  SIGIO. The  default disposition  of the  SIGIO
    signal is "ignore" - thus,  most processes are unaffected by  this
    vulnerability.  However,  certain programs explicitly  catch SIGIO
    in order to use asynchronous I/O; these programs can be  disrupted
    by sending stray SIGIO's.

    The process  notification information  is also  used to  determine
    the process that  receives notification of  out-of-band data on  a
    socket.  The same vulnerability applies, this time by setting  the
    process to  notify and  then sending  a message  with the  MSG_OOB
    flag  set;  the  targetted  process  will receive a SIGURG signal.
    Certain network daemons (ftpd,  for instance) can be  disrupted by
    being sent  a stray  SIGURG signal  when no  data is available for
    reading.

    The  problem  is  more  serious  on  vulnerable System V operating
    systems; in many  cases, SIGIO is  the equivalent of  SIGPOLL, and
    the default disposition of that signal is "terminate process".  On
    SGI's IRIX  operating system,  exploitation of  this vulnerability
    can kill any process on the system.

    In addition to being an extremely potent denial of service attack,
    surgical  application  of  this  vulnerability  can  be  used   to
    compromise the  system -  for example,  a process  holding a bound
    address (NFS port 2049, for  instance) can be killed off  and it's
    port stolen; this can be used to steal NFS file handles.

    In addition to sockets,  some devices also provide  facilities for
    notification of  pending I/O;  examples include  the "log", "tun",
    and "bpf".  The BPF and tunnel devices are of minimal concern,  as
    they are  not typically  accessible by  arbitrary users  (although
    BPF  is  interesting  in  that  it  will  allow  the  owner  of  a
    bpf-associated descriptor to choose  an arbitrary signal to  send,
    including SIGSTOP).

    Unfortunately, the  log device  is normally  accessible by  users,
    and can be used to perform the same attack as sockets allow.  It's
    also worth noting that the  interface that allows programs to  set
    the  process  to  receive  notification  of  I/O on the log device
    renders  the   legitimate  purpose   of  this   facility   totally
    unreliable;  unrelated   programs  can   seize  control   of   the
    asynchronous I/O notification on the log device, causing  programs
    that rely on it to  fail. The provided patches that  are available
    from address do not attempt to resolve this problem.

    This vulnerability is believed to have been discovered  originally
    by Alan Peakall.

SOLUTION

    This is a kernel  problem that can only  be fixed by patching  the
    problematic system code. Patches for the OpenBSD operating  system
    are  provided  advisory  mentioned  above;  FreeBSD is known to be
    working on a similar solution.

    OpenBSD patch causes the kernel  to keep track of the  credentials
    of the process associated with an I/O object; the credentials  are
    checked  whenever  I/O  notification  will  occur,  and  therefore
    resolve both the F_SETOWN  and PID-reuse problems. Device  drivers
    that present an interface to I/O notification must be modified  to
    check credentials  when the  TIOCSPGRP (or  equivalent) ioctl() is
    used  to  set  notificatio  PID;  the  OpenBSD  patch resolves all
    currently known occurances of this in that operating system.