Implementing hooks

From: David Wheeler (dwheelerat_private)
Date: Thu Apr 19 2001 - 08:17:46 PDT

  • Next message: Serge E. Hallyn: "Re: Inodes hooks example"

    I agree with Andrew Morgan <morganat_private>'s proposal to
    use C preprocessor macros to implement hook insertions and returns.  That way,
    you can optimize differently for different processor types and implement
    rival designs.  In addition, Linus has previously stated that he
    does NOT want code littered with #ifdef's.. if you need multiple #ifdefs that
    do the same thing, he'd prefer to have it hidden in a macro call.
    That way, the #ifdef is confined to a single location (the macro definition).
    The main reason to do this, however, would be so that you can
    separate HOW hooks are implemented from the decision on WHERE to put them.
    
    And frankly, it appears that there are LOTS of ways to implement hooks,
    and which is better is almost certainly architecture-dependent.
    For many pipelined systems, any insertion of a branch is likely to
    cause a stall... unless it does speculative execution & has the resources
    to do it... unless, unless, unless.  Here are a few implementation
    possibilities that I see for hooks (there are probably more), which
    argues for encapsulating the hook mechanism to permit compile-time
    selection the best mechanism:
    
    
    Option 1:  ALWAYS call a function, which may just return.
      err = security_ops->ioperm();
    
    Option 2: Call the function only if non-null
      err = security_ops->ioperm ? security_ops->ioperm() : 0;
      /* If resulting branch causes a stall, this could be worse, but by
         avoiding the call setup & execution, this may be better.
         The compiler should optimize this so retrieval of "security_ops->ioperm"
         will actually occur only once, though I haven't checked this. */
    
    Option 3: Replace with NOPs at load time.
       /* For each hook, on start-up replace with NOPs and store "original"
          values; when a hook is invoked, re-insert the original code. */
    
    Option 4: Replace JSR with uninteresting operation.
       /* For each hook, replace the CPU's "jump to subroutine" call with
          an operation that does something worthless.  Advantage: don't
          need to store original values or subroutine setup/destruction
          in a separate area.  Disadvantage: probably not as fast as a NOP */
    
    Option 5: Insert a jump to another location.
       /* When the hook is enabled, copy the relevant operation elsewhere, add
       the relevant subroutine calls, and insert a jump.  This would be
       the absolute fastest for unused hooks -- literally absolutely NO
       performance hit -- but the hit for _used_ hooks would be higher, since
       jumps usually flush instruction caches & that would happen on both
       call and return. */
    
    
    The nice thing about encapsulating the hook implementation is that you
    can start work with something simple (#1 or #2), then move to more
    complex approaches if desirable.  Makes benchmarking more realistic too,
    and benchmarks would be needed for a decision (for a given architecture).
    
    > Crispin Cowan wrote:
    > >
    > > I think that the self-modifying-code approach is likely to bounce, as it
    > > completely breaks on ROM'd systems.  With Linux's current momentum into
    embedded
    > > space, I suspect that self-modifying code would be rejected out of hand.
    
    That's a valid point.  I would say, then, that a non-self-modifying
    approach would at least need to be available.  However, it's my understanding
    that few systems actually _RUN_ out of their ROMs.  So, if you separate
    the hook _implementation_ from the hook placement, you can have various
    hook implementation options.
    
    
    _______________________________________________
    linux-security-module mailing list
    linux-security-moduleat_private
    http://mail.wirex.com/mailman/listinfo/linux-security-module
    



    This archive was generated by hypermail 2b30 : Thu Apr 19 2001 - 08:22:15 PDT