Re: ideas on interface (was Be careful please)

From: Chris Wright (chrisat_private)
Date: Sat Apr 14 2001 - 17:38:56 PDT

  • Next message: Crispin Cowan: "Re: Specifications (the beginning)"

    * Philippe Biondi (philippe.biondi@enst-bretagne.fr) wrote:
    > Let's put the problem in place : we have the (veryveryvery) generic
    > scheme:
    >            |
    >            |     +---------+
    >            |     | Decider |
    >            |     +---------+
    >            |          ^
    >            |          | (1)
    >            |          V
    >            |      +-------+
    > user space |   +--| hooks |---+
    >            |   |  +-------+   |
    >    App ----+-->| Syscall code |
    >            |   +--------------+
    > 
    > The question is : what is the arrow (1) ? In other words what is the
    > semantic behind such calls to the decider ?
    > 
    > Your approach was to say that the decider had to answer to :
    >  "Can 'current' exec <syscall> with <parameters>"
    > I'll prefer
    >  "Can 'current' do <type-of-action> with <object(s)>"
    > even if it seems very MAC-oriented
    
    No, I think we are misunderstanding each other.  I am strictly _not_
    interested in watching just syscalls.  In fact, I believe only a few
    syscalls will need the hooks.  The fact remains that syscalls are the
    user applications' interface to the kernel.  We are tyring to protect
    kernel objects (in my mind).  Therefore, the syscall interface is a good
    place to start looking at what a user app can acutally do to a kernel
    object.  For example, some kernel objects contain linked lists that are
    used only internally.  I don't think we care about protecting this kind
    of kernel object data (if the user app can't change it).
    
    I am trying to look at the handful of kernel objects and ask "what can a
    user app do to that object that we need to protect?"  I think we have the
    same goals.
    
    > Do we need to intercept each file-related syscall to enforce simple
    > rules like "Nobody write into /sbin" ?
    
    No.  We simply need a rule for write.  But what about "foo can read
    /lib/libc.so.6" and "bar can create in /tmp"?  For any individual policy
    statement, there may be only one hook.  But the composite policy will
    rely on many hooks.  Am I missing something?
    
    I actually left some file operations out intentionally (poll and
    readdir).  At first I looked only at things that allowed you to alter
    the state of a kernel object.  This is more straightforward for the
    task struct...change the uid value or priority value.  For the file and
    inode structs, the operations already provide the interface.  So then we
    begin deciding which operations we care about and want to expose hooks
    for.
    
    > What about considering as a 1st approximation to replace every call to
    > permission :
    > ./fs/open.c:    error = permission(inode,MAY_WRITE);
    > ./fs/open.c:                (error = permission(inode,MAY_WRITE)) != 0)
    > ./fs/open.c:            if ((error = permission(inode,MAY_WRITE)) != 0)
    > ./fs/open.c:            res = permission(nd.dentry->d_inode, mode);
    > [...]
    > ./fs/exec.c:    error = permission(nd.dentry->d_inode, MAY_READ |
    > MAY_EXEC);
    > ./fs/exec.c:                    int err = permission(inode, MAY_EXEC);
    > ./fs/exec.c:        permission(bprm->file->f_dentry->d_inode,MAY_READ))
    > ./fs/super.c:   if (permission(nd->dentry->d_inode, MAY_WRITE))
    > [...]
    
    In my proposal permission is part of the inode operations.  It is an
    obvious multiplexor for all the inode operations requests (and maybe
    some of the other inode operations' hooks can go away).  My only
    thought is whether we want to "replace" these calls or add our hook in
    the call.  I don't like the idea of giving every module the
    responsibility of re-coding standard UNIX permissions checks.  And in
    the case where no security module is loaded we can't leave system
    without standard permissions checks...that is inacceptable.
    
    Perhaps keeping the calls to permission, and changing permission to look
    like:
    
    int permission(struct inode * inode,int mask)
    {
        int retval;
        if (inode->i_op && inode->i_op->permission) {
            lock_kernel();
            retval = inode->i_op->permission(inode, mask);
    		if (!retval)
    			retval = security_ops->inode_ops->permission(inode, mask);
            unlock_kernel();
            return retval;
        }
        retval = vfs_permission(inode, mask);
    	if (!retval)
    		retval = security_ops->inode_ops->permission(inode, mask);
    	return retval;
    }
    
    > 
    > and every call to capable() :
    > ./fs/read_write.c:                      if (inode &&
    > S_ISBLK(inode->i_mode) && (!capable(CAP_SYS_RAWIO)))
    > ./fs/read_write.c:                                      if (inode &&
    > S_ISBLK(inode->i_mode) && (!capable(CAP_SYS_RAWIO))) {
    > ./fs/buffer.c:  if (!capable(CAP_SYS_ADMIN)) {
    > ./fs/open.c:    if (!capable(CAP_SYS_CHROOT)) {
    > ./fs/open.c:    if (capable(CAP_SYS_TTY_CONFIG)) {
    > [...]
    
    This is what I was doing when I started thinking about how to abstract
    the interface.  Capabilities gives 28 different modes (CAP_XXX) but this
    will probably not be enough granularity for most security modules.
    CAP_SYS_ADMIN is a real offender here...it's a bit like the kitchen
    sink ;-)  I think most security modules will want to differentiate
    between mounting devices, removing semaphores and enabling/disabling
    swap.  CAP_SYS_ADMIN does not capture this.
    
    If we develop an interface that allows you to export to the module more
    granularity that the module needs, it can simply ignore it.  So the
    capabilites module will map requests to mount devices, remove
    semaphores, and enable/disable swap to the same internal policy; the one
    that implements CAP_SYS_ADMIN.
    
    > by a call to a function with could implement the already existing scurity
    > model : DAC and capabilities.
    > The behaviour is quite simple : the function must have enough parameters
    > to know what action is intended to do : ("write to this inode", "being ADMIN
    > capable",..) and know the subject (let's keep on with the MAC terminology :))
    > because we are in process context. All what is needed to do is comparing
    > some security policy data stored in the current task struct (current->uid,
    > euid, cap_permitted...) with what is needed to be allowed to do the
    > action. No more than what is already done.
    
    It sounds to me like you are suggesting one function, something like:
    
    is_this_legal(action, credientials, additional data...)
    
    While this is a nice way to look at it, I don't think we'll be able to
    implement it that way.  There are so many different types of actions
    that need different types of additional data.
    > 
    > 
    > The next step would be to
    > * transform this function is something like a hub, with a register()...
    > * add a place for more fine grained security policy data in the task struct
    > * add a hook for inheritage rules of security policy data.
    > * reimplement the same security model using the new place in task struct
    >   (instead of ->uid,..), the hook of inheritage, and the hub function
    
    If you notice, in the interface I proposed there is a hook for adding
    per task security data that is opaque to the kernel.  This is to be
    unique for each security module.  Also, there is a mechanism for the
    module to register its module-specific security_operations.  But I
    disagree with the ->uid part.  If no security module is loaded the
    interface has a set of dummy functions (they all immediately return
    success).  This way we leave the traditional permission checks in tact,
    and just add one function call that immediately returns as the overhead
    (wherever our hooks are). This seems least intrusive and most likely to
    be accepted.
    
    -chris
    
    _______________________________________________
    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 : Sat Apr 14 2001 - 17:45:04 PDT