Gmane
Favicon
From: David Howells <dhowells <at> redhat.com>
Subject: [PATCH 00/27] Introduce credentials [ver #6]
Newsgroups: gmane.linux.kernel.lsm
Date: 2008-07-11 11:05:14 GMT (51 weeks, 2 days, 9 hours and 12 minutes ago)

Hi Al, Christoph, Stephen, Casey, Andrew, James,

A tarball of these patches can be retrieved from:

	http://people.redhat.com/~dhowells/cow-creds-6.tar.bz2

I've brought up to latest linux-next and fixed Al Viro's review comments.

 (*) Changed ({ NULL; }) in key.h to NULL as Al points out the two are
     equivalent [patch #5].

 (*) Split out the kernel_cap_t pointer constification from the patch that
     neuters sys_capset() [patches #6 & #7].

 (*) Adjusted the description of the patch that adds task_e?[ug]id() [patch #9]
     to mention RCU in conjunction with that rather than current_e?[ug]id(),
     and to refer forward to the patch that adds the RCU.

 (*) Added a patch to remove the obsolete references to UID/GID stuff used by
     Sparc's no longer extant sclow.S from its asm-offsets [patch #10].

 (*) Altered the Alpha arch to correctly dereference the current cred pointer
     in its syscalls written in asm to get at [UG]ID and E[UG]ID [patch #11].

 (*) Altered the description of patch #12 to mention copy_process() and
     __put_task_struct() rather than fork and exit.

 (*) Don't use RCU in accessing tsk's creds in audit_log_exit(), but rather go
     use current_cred() instead on the basis that tsk == current under all
     circumstances in this function [patch #14].

 (*) Don't get the RCU read lock in release_task() to access the dead task's
     creds [patch #14].  It is, after all, dead, and so can't be modifying its
     own creds.

 (*) Annotated wait_task_stopped() to say why I don't need the rcu_read_lock()
     [there's a spinlock in force, and IRQs are disabled] [patch #14].

 (*) Adjusted the comment in __sigqueue_alloc() to say why the explicit barrier
     is no longer necessary [patch #14] and discard the rcu_read_lock() added
     later unnecessarily [patch #20].  The caller, if not queuing a signal for
     itself (ie: t == current) must hold a spinlock, and thus the
     rcu_read_lock().

 (*) Repurposed and renamed cred_replace_mutex to cred_exec_mutex [patch #20].
     It is only required for preventing ptrace_attach() interfering with exec's
     credential calculations.  However, making prepare_creds() always lock the
     mutex may cause kernel_thread() to deadlock if called from something
     execve calls.  So it is obtained directly by ptrace_attach() and by
     do_execve() and nowhere else.

 (*) Adjusted the description of patch #23 to mention that the open() file
     operation should use file->f_cred rather than current_cred() and that
     these should be the same, noting HPPFS as an example.

I will post the FS-Cache patches separately.

I've been testing these patches with the LTP syscalls and SELinux test scripts.

---
There are three parts to this project:

 (1) Implement COW credentials.

 (2) Pass the cred pointer through the vfs_xxx() functions and suchlike to all
     the places that need them.

 (3) Document it.

I'm intending to use this code to implement FS-Cache/CacheFiles, but it can
also be used for NFSD.

The associated patches implements (1) and partially implements (3).  Some
things to note:

 (a) All of {,e,s,fs}{u,g}id and supplementary groups, capabilities, secure
     bits, keyrings, and the task security pointer have migrated into struct
     cred.

 (b) Changing a tasks credentials involves creating a new struct cred (call
     prepare_creds()) and then using RCU to change things over (call
     commit_creds()).

 (c) task_struct::cred is a const struct cred *, as are all pointers that
     aren't used specifically for creating new credentials.  This catches
     places that are changing creds when they shouldn't be at compile time.

     To get a new ref on a const cred, use get_cred() which casts away the
     const and calls atomic_inc().

 (d) It is no longer possible for a task to instantiate another task's
     keyrings.  The keyrings code tries to make sure that the required keyrings
     are present in request_key(), and redirects any attempt to nominate a
     process-specific keyring when instantiating a key to whatever keyring was
     suggested by sys_request_key() (or it uses the default).

 (e) sys_capset() is neutered: it can only affect the caller.  This means
     current doesn't have to lock to access its own credentials.

 (f) execve() is cleaner.  The changes are all worked out in a new set of
     credentials, then the whole lot is installed in install_exec_creds() (a
     replacement for compute_creds()) in three stages:

     (i) The LSM is called - security_bprm_committing_creds() - so that the LSM
     	 can do stuff that must be done before the new creds take effect.
     	 SELinux uses this to call flush_authorized_files() and to flush
     	 rlimits.

     (ii) commit_creds() is called to make the actual change.

     (iii) The LSM is called again - security_bprm_committed_creds() - so that
         the LSM can do stuff that must be done under the new creds.  SELinux
         uses this to flush signal handlers.

 (g) Most of the bprm LSM hooks have been replaced with simplified code
     arranged differently.

 (h) In struct file, f_uid and f_gid have been replaced by f_cred, which is a
     pointer to the opener's credentials at the time of opening.

 (i) Credentials are shared where possible.  More work should go into this as
     it plays it safe when sharing keyrings over non-CLONE_THREAD clones.

 (j) The reparent_to_init LSM hook for kernel threads is gone.  Kernel threads
     now made to share init_cred instead at the start of their life (they may
     change this later).

Most of the work is in patch 20 [Subject: CRED: Inaugurate COW credentials].
The description attached to this describes each of the logical changes in more
detail.  The preceding patches are preparation.

I'm working on (2) and (3) at the moment.

These patches compile for make allyesconfig, and I've built and run a kernel on
my x86_64 test box with these patches applied.

The patches are:

 (*) 01-fix-PF_SUPERPRIV.diff

     Fix a potential corruption bug in capable() with setting PF_SUPERPRIV on
     other tasks without locks.

 (*) 02-filecap-refactor-support.patch
 (*) 03-filecap-no-longer-experimental.diff

     Andrew Morgan's file capabilities fixing patches.

 (*) 04-keys-disperse-key_ui_h.diff

     Disperse the bits of <linux/key_ui.h> and delete the file.  The keyfs
     filesystem didn't happen, so this isn't necessary.

 (*) 05-keys-alter-key-instantiation.diff

     Alter the key instantiation code so as to remove the ability to directly
     access another process's credentials.  The contents of the keyrings
     themselves may still change, however.  I could implement a COW shadow of
     the subscribed keyrings, but I really don't think it's worth it.

 (*) 06-cred-neuter-sys_capset.diff

     Remove the ability of sys_capset() to affect other processes.

 (*) 07-cred-constify-capset-hooks.diff

     Constify the kernel_cap_t pointers to the capset LSM hooks.

 (*) 08-cred-current-fsugid.diff
 (*) 09-cred-current-ugid-eugid.diff

     Wrap accesses to most current->*[ug]id and some task->*[ug]id to use
     accessor macros to cut down the later patches and to hide RCU locking
     where it may be necessary later.

 (*) 10-cred-sparc-no-sclow.diff

     Discard the obsolete references in the Sparc asm-offsets to task
     credentials.

 (*) 11-cred-separate-creds.diff

     Separate the credentials into cred struct, though that's still embedded in
     task_struct at this point.

 (*) 12-cred-detach-creds.diff

     Detach the struct cred from task_struct, though its lifetime still follows
     that of task_struct.

 (*) 13-cred-current-wrappers.diff
 (*) 14-cred-task-rcu-wrappers.diff
 (*) 15-cred-selinux-wrappers.diff

     Wrap accesses to current's creds.  Wrap accesses to other tasks' creds to
     hide the RCU where possible.  Add in RCU directly where it is has to be.

 (*) 16-cred-pertg-keyrings.diff

     Separate the process and session keyrings from signal_struct, and make
     them dangle shareably from struct cred instead.

 (*) 17-cred-is_single_threaded.diff

     Rename is_single_threaded() to is_wq_single_threaded().

 (*) 18-cred-selinux-xxx_has_perm.diff

     Make {file,inode}_has_perm() take a cred pointer.

 (*) 19-cred-dentry_open.diff

     Pass a cred pointer through dentry_open().

 (*) 20-cred-cow-creds.diff

     Do the actual work of COW credentials.

 (*) 21-cred-improve-execve.diff

     Make execve() take advantage of COW credentials.

 (*) 22-cred-prettify-commoncap.diff

     Add comments in to commoncap.c and do some other stylistic cleanups.

 (*) 23-cred-file-creds.diff

     Share the process's credentials with any files it opens.

 (*) 24-cred-document.diff

     Documentation of Linux credentials and the methods by which they may be
     manipulated.

 (*) 25-cred-objsubj-split.diff

     Differentiate objective/real subjective creds vs effective creds, and
     allow just the latter to be overridden.

 (*) 26-cred-kernel_service-class.diff

     Introduce an SELinux class for kernel service ops.

 (*) 27-cred-kernel-service.diff

     Provide cred ops for kernel service credential management.

David
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo <at> vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html