intercepting system calls

From: Anil B. Somayaji (somaat_private)
Date: Wed Apr 11 2001 - 23:32:26 PDT

  • Next message: Amon Ott: "intercepting system calls"

    -----BEGIN PGP SIGNED MESSAGE-----
    Hash: SHA1
    
    Hello everyone!  My name is Anil Somayaji, and as some of you know
    (and most of you probably don't), for the past few years I've been
    doing research on how short sequences of system calls can be used to
    differentiate between normal and abnormal program behavior.  For this
    work I've played around with audit packages, strace, and even resorted
    to wrapping system calls in libc (disassembling SunOS 4 libraries, not
    something you should ever think of doing).  Finally I broke down and
    started hacking the Linux kernel to do what I needed it to do, and now
    I'm working on ways to automatically stop attacks based on what
    happens at the system call level.
    
    I mention this just to say that I've had to grapple with what it means
    to monitor and interfere with system calls in Linux, and so I have
    some comments to make about Linus's thoughts on system-call
    interposition.
    
    Linus Torvalds wrote:
    
    > On Sat, 7 Apr 2001, David Wagner wrote:
    > >   - What to interpose on?
    > >     Here are a few suggestions for possibilities: interposition on all
    > >     system calls; interposition on all VFS calls; on sockets.  What else?
    >
    > Not at a system call level. It gets too intrusive, and too many people
    > (including me) start to worry a _lot_ if you lose even one cycle in the
    > system call path. Linux system calls are lightweight, and I like them that
    > way.
    
    Light system calls are good, indeed.  I sorry to say that my
    modifications have killed system call latency (but because system
    calls in Linux are so lightweight, nobody seems to notice).  However,
    I also know that security costs something, and if you want to minimize
    those costs, it is best to do actions at the right place, and at the
    right time.  If you want to mess with system calls, you should mess
    with them in kernel-space - anywhere else is either too expensive,
    insecure, or both.
    
    ...
    > You interpose on well-defined abstraction levels. Anything else is a waste
    > of time, and useless. Why should you care if the user does a system call:
    > sometimes the user can do the same thing by hand, and the system call is
    > nothing but a convenience. The extreme case of this would be the whole
    > TCP/IP stack: the user _could_ just open a raw packet socket and do its
    > own TCP/IP stack totally in user mode. Or think about "gettimeofday()":
    > it could be a system call on some architectures, and avaiable in user mode
    > on others.
    >
    > And even when you have meaningful system calls like "write", why interpose
    > on that. Nobody cares if you write to /dev/null, while if you write to
    > /etc/passwd people might take a second look. You need to get in at the
    > _meaningful_ level.
    
    System calls _are_ a well-defined abstraction level - it is the
    abstraction of functions that userspace programs can invoke in the
    kernel.  It is a fundamental mechanism - system calls are how
    processes talk with the kernel.  Even memory-mapped IO and raw socket
    accesses start with system calls.  Except for maybe a few exceptions
    (which I can't think of at the moment - anyone, please correct me), a
    process without system calls is a process locked away in its own box,
    incapable of interacting with the outside world.  Sure, it is
    Turing-complete, but it isn't too interesting.
    
    I actually do believe that sometimes you do care that a program is
    writing to /dev/null - especially if that program normally writes to a
    log file!  But really, what it comes down to is that many people have
    proposed and tested effective security mechanisms that work at the
    system-call level.
    
    Having said that, I don't think a completely general system-call
    interposition mechanism would be a good idea.  It would definitely add
    significant overhead.  But worse, it would probably discourage people
    from making changes in the right places.  If you want to mess around
    with the behavior of execve, you should do it from within the code of
    do_execve.  If some security code gains control before do_execve has
    run, you're stuck with decoding the arguments to execve, which means
    that the security code has to duplicate the checks and repeat the
    processing done in do_execve.
    
    OK, maybe you could have a hook somewhere in execve - but where would
    you put that hook?  Maybe a security module wants to keep track of
    attempted execve's of non-existent files, and differentiate those from
    execve's of non-executable files.  I don't see how to do this without
    duplicating the functionality of do_execve, or having hooks at every
    error condition.
    
    So, while I like the general idea of interposing on system calls, I
    see lots of problems with doing it in practice.  I'm curious - what do
    other people actually want to do to system calls?  How much info is
    needed?  Maybe we can't have a really flexible API, but maybe we can
    have one that does 90% of the job for 10% of the effort and 1% of the
    slowdown.  Otherwise, system call hacks will probably have to continue
    to live outside the main kernel tree.
    
      --Anil
    
    - -- 
    Anil Somayaji (somaat_private)
    http://www.cs.unm.edu/~soma
    +1 505 872 3150
    -----BEGIN PGP SIGNATURE-----
    Version: GnuPG v1.0.4 (GNU/Linux)
    
    iEYEARECAAYFAjrVS+8ACgkQXOpXEmNZ3ScE6wCffvYX2bkHlmRSmAl5jbQh/Skx
    VAUAn1tsFmaMtpCS2TlPfil4zeZoX6N+
    =UDEY
    -----END PGP SIGNATURE-----
    



    This archive was generated by hypermail 2b30 : Fri Apr 13 2001 - 14:15:21 PDT