12 Apr, 2015

1 commit


02 Dec, 2014

1 commit

  • Since the keyring facility can be viewed as a cache (at least in some
    applications), the local expiration time on the key should probably be viewed
    as a 'needs updating after this time' property rather than an absolute 'anyone
    now wanting to use this object is out of luck' property.

    Since request_key() is the main interface for the usage of keys, this should
    update or replace an expired key rather than issuing EKEYEXPIRED if the local
    expiration has been reached (ie. it should refresh the cache).

    For absolute conditions where refreshing the cache probably doesn't help, the
    key can be negatively instantiated using KEYCTL_REJECT_KEY with EKEYEXPIRED
    given as the error to issue. This will still cause request_key() to return
    EKEYEXPIRED as that was explicitly set.

    In the future, if the key type has an update op available, we might want to
    upcall with the expired key and allow the upcall to update it. We would pass
    a different operation name (the first column in /etc/request-key.conf) to the
    request-key program.

    request_key() returning EKEYEXPIRED is causing an NFS problem which Chuck
    Lever describes thusly:

    After about 10 minutes, my NFSv4 functional tests fail because the
    ownership of the test files goes to "-2". Looking at /proc/keys
    shows that the id_resolv keys that map to my test user ID have
    expired. The ownership problem persists until the expired keys are
    purged from the keyring, and fresh keys are obtained.

    I bisected the problem to 3.13 commit b2a4df200d57 ("KEYS: Expand
    the capacity of a keyring"). This commit inadvertantly changes the
    API contract of the internal function keyring_search_aux().

    The root cause appears to be that b2a4df200d57 made "no state check"
    the default behavior. "No state check" means the keyring search
    iterator function skips checking the key's expiry timeout, and
    returns expired keys. request_key_and_link() depends on getting
    an -EAGAIN result code to know when to perform an upcall to refresh
    an expired key.

    This patch can be tested directly by:

    keyctl request2 user debug:fred a @s
    keyctl timeout %user:debug:fred 3
    sleep 4
    keyctl request2 user debug:fred a @s

    Without the patch, the last command gives error EKEYEXPIRED, but with the
    command it gives a new key.

    Reported-by: Carl Hetherington
    Reported-by: Chuck Lever
    Signed-off-by: David Howells
    Tested-by: Chuck Lever

    David Howells
     

17 Sep, 2014

4 commits

  • Make the key matching functions pointed to by key_match_data::cmp return bool
    rather than int.

    Signed-off-by: David Howells
    Acked-by: Vivek Goyal

    David Howells
     
  • A previous patch added a ->match_preparse() method to the key type. This is
    allowed to override the function called by the iteration algorithm.
    Therefore, we can just set a default that simply checks for an exact match of
    the key description with the original criterion data and allow match_preparse
    to override it as needed.

    The key_type::match op is then redundant and can be removed, as can the
    user_match() function.

    Signed-off-by: David Howells
    Acked-by: Vivek Goyal

    David Howells
     
  • Remove key_type::def_lookup_type as it's no longer used. The information now
    defaults to KEYRING_SEARCH_LOOKUP_DIRECT but may be overridden by
    type->match_preparse().

    Signed-off-by: David Howells
    Acked-by: Vivek Goyal

    David Howells
     
  • Preparse the match data. This provides several advantages:

    (1) The preparser can reject invalid criteria up front.

    (2) The preparser can convert the criteria to binary data if necessary (the
    asymmetric key type really wants to do binary comparison of the key IDs).

    (3) The preparser can set the type of search to be performed. This means
    that it's not then a one-off setting in the key type.

    (4) The preparser can set an appropriate comparator function.

    Signed-off-by: David Howells
    Acked-by: Vivek Goyal

    David Howells
     

15 Mar, 2014

1 commit

  • Move the flags representing required permission to linux/key.h as the perm
    parameter of security_key_permission() is in terms of them - and not the
    permissions mask flags used in key->perm.

    Whilst we're at it:

    (1) Rename them to be KEY_NEED_xxx rather than KEY_xxx to avoid collisions
    with symbols in uapi/linux/input.h.

    (2) Don't use key_perm_t for a mask of required permissions, but rather limit
    it to the permissions mask attached to the key and arguments related
    directly to that.

    Signed-off-by: David Howells
    Tested-by: Dmitry Kasatkin

    David Howells
     

24 Sep, 2013

7 commits

  • Add support for per-user_namespace registers of persistent per-UID kerberos
    caches held within the kernel.

    This allows the kerberos cache to be retained beyond the life of all a user's
    processes so that the user's cron jobs can work.

    The kerberos cache is envisioned as a keyring/key tree looking something like:

    struct user_namespace
    \___ .krb_cache keyring - The register
    \___ _krb.0 keyring - Root's Kerberos cache
    \___ _krb.5000 keyring - User 5000's Kerberos cache
    \___ _krb.5001 keyring - User 5001's Kerberos cache
    \___ tkt785 big_key - A ccache blob
    \___ tkt12345 big_key - Another ccache blob

    Or possibly:

    struct user_namespace
    \___ .krb_cache keyring - The register
    \___ _krb.0 keyring - Root's Kerberos cache
    \___ _krb.5000 keyring - User 5000's Kerberos cache
    \___ _krb.5001 keyring - User 5001's Kerberos cache
    \___ tkt785 keyring - A ccache
    \___ krbtgt/REDHAT.COM@REDHAT.COM big_key
    \___ http/REDHAT.COM@REDHAT.COM user
    \___ afs/REDHAT.COM@REDHAT.COM user
    \___ nfs/REDHAT.COM@REDHAT.COM user
    \___ krbtgt/KERNEL.ORG@KERNEL.ORG big_key
    \___ http/KERNEL.ORG@KERNEL.ORG big_key

    What goes into a particular Kerberos cache is entirely up to userspace. Kernel
    support is limited to giving you the Kerberos cache keyring that you want.

    The user asks for their Kerberos cache by:

    krb_cache = keyctl_get_krbcache(uid, dest_keyring);

    The uid is -1 or the user's own UID for the user's own cache or the uid of some
    other user's cache (requires CAP_SETUID). This permits rpc.gssd or whatever to
    mess with the cache.

    The cache returned is a keyring named "_krb." that the possessor can read,
    search, clear, invalidate, unlink from and add links to. Active LSMs get a
    chance to rule on whether the caller is permitted to make a link.

    Each uid's cache keyring is created when it first accessed and is given a
    timeout that is extended each time this function is called so that the keyring
    goes away after a while. The timeout is configurable by sysctl but defaults to
    three days.

    Each user_namespace struct gets a lazily-created keyring that serves as the
    register. The cache keyrings are added to it. This means that standard key
    search and garbage collection facilities are available.

    The user_namespace struct's register goes away when it does and anything left
    in it is then automatically gc'd.

    Signed-off-by: David Howells
    Tested-by: Simo Sorce
    cc: Serge E. Hallyn
    cc: Eric W. Biederman

    David Howells
     
  • Expand the capacity of a keyring to be able to hold a lot more keys by using
    the previously added associative array implementation. Currently the maximum
    capacity is:

    (PAGE_SIZE - sizeof(header)) / sizeof(struct key *)

    which, on a 64-bit system, is a little more 500. However, since this is being
    used for the NFS uid mapper, we need more than that. The new implementation
    gives us effectively unlimited capacity.

    With some alterations, the keyutils testsuite runs successfully to completion
    after this patch is applied. The alterations are because (a) keyrings that
    are simply added to no longer appear ordered and (b) some of the errors have
    changed a bit.

    Signed-off-by: David Howells

    David Howells
     
  • Drop the permissions argument from __keyring_search_one() as the only caller
    passes 0 here - which causes all checks to be skipped.

    Signed-off-by: David Howells

    David Howells
     
  • Search functions pass around a bunch of arguments, each of which gets copied
    with each call. Introduce a search context structure to hold these.

    Whilst we're at it, create a search flag that indicates whether the search
    should be directly to the description or whether it should iterate through all
    keys looking for a non-description match.

    This will be useful when keyrings use a generic data struct with generic
    routines to manage their content as the search terms can just be passed
    through to the iterator callback function.

    Also, for future use, the data to be supplied to the match function is
    separated from the description pointer in the search context. This makes it
    clear which is being supplied.

    Signed-off-by: David Howells

    David Howells
     
  • Consolidate the concept of an 'index key' for accessing keys. The index key
    is the search term needed to find a key directly - basically the key type and
    the key description. We can add to that the description length.

    This will be useful when turning a keyring into an associative array rather
    than just a pointer block.

    Signed-off-by: David Howells

    David Howells
     
  • key_is_dead() should take a const key pointer argument as it doesn't modify
    what it points to.

    Signed-off-by: David Howells

    David Howells
     
  • Skip key state checks (invalidation, revocation and expiration) when checking
    for possession. Without this, keys that have been marked invalid, revoked
    keys and expired keys are not given a possession attribute - which means the
    possessor is not granted any possession permits and cannot do anything with
    them unless they also have one a user, group or other permit.

    This causes failures in the keyutils test suite's revocation and expiration
    tests now that commit 96b5c8fea6c0861621051290d705ec2e971963f1 reduced the
    initial permissions granted to a key.

    The failures are due to accesses to revoked and expired keys being given
    EACCES instead of EKEYREVOKED or EKEYEXPIRED.

    Signed-off-by: David Howells

    David Howells
     

08 May, 2013

1 commit

  • Faster kernel compiles by way of fewer unnecessary includes.

    [akpm@linux-foundation.org: fix fallout]
    [akpm@linux-foundation.org: fix build]
    Signed-off-by: Kent Overstreet
    Cc: Zach Brown
    Cc: Felipe Balbi
    Cc: Greg Kroah-Hartman
    Cc: Mark Fasheh
    Cc: Joel Becker
    Cc: Rusty Russell
    Cc: Jens Axboe
    Cc: Asai Thambi S P
    Cc: Selvan Mani
    Cc: Sam Bradshaw
    Cc: Jeff Moyer
    Cc: Al Viro
    Cc: Benjamin LaHaise
    Reviewed-by: "Theodore Ts'o"
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Kent Overstreet
     

14 Sep, 2012

1 commit

  • - Replace key_user ->user_ns equality checks with kuid_has_mapping checks.
    - Use from_kuid to generate key descriptions
    - Use kuid_t and kgid_t and the associated helpers instead of uid_t and gid_t
    - Avoid potential problems with file descriptor passing by displaying
    keys in the user namespace of the opener of key status proc files.

    Cc: linux-security-module@vger.kernel.org
    Cc: keyrings@linux-nfs.org
    Cc: David Howells
    Signed-off-by: Eric W. Biederman

    Eric W. Biederman
     

24 Jul, 2012

1 commit

  • Pull security subsystem updates from James Morris:
    "Nothing groundbreaking for this kernel, just cleanups and fixes, and a
    couple of Smack enhancements."

    * 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (21 commits)
    Smack: Maintainer Record
    Smack: don't show empty rules when /smack/load or /smack/load2 is read
    Smack: user access check bounds
    Smack: onlycap limits on CAP_MAC_ADMIN
    Smack: fix smack_new_inode bogosities
    ima: audit is compiled only when enabled
    ima: ima_initialized is set only if successful
    ima: add policy for pseudo fs
    ima: remove unused cleanup functions
    ima: free securityfs violations file
    ima: use full pathnames in measurement list
    security: Fix nommu build.
    samples: seccomp: add .gitignore for untracked executables
    tpm: check the chip reference before using it
    TPM: fix memleak when register hardware fails
    TPM: chip disabled state erronously being reported as error
    MAINTAINERS: TPM maintainers' contacts update
    Merge branches 'next-queue' and 'next' into next
    Remove unused code from MPI library
    Revert "crypto: GnuPG based MPI lib - additional sources (part 4)"
    ...

    Linus Torvalds
     

23 Jul, 2012

2 commits


10 Jun, 2012

1 commit


25 May, 2012

1 commit

  • Fix some sparse warnings in the keyrings code:

    (1) compat_keyctl_instantiate_key_iov() should be static.

    (2) There were a couple of places where a pointer was being compared against
    integer 0 rather than NULL.

    (3) keyctl_instantiate_key_common() should not take a __user-labelled iovec
    pointer as the caller must have copied the iovec to kernel space.

    (4) __key_link_begin() takes and __key_link_end() releases
    keyring_serialise_link_sem under some circumstances and so this should be
    declared.

    Note that adding __acquires() and __releases() for this doesn't help cure
    the warnings messages - something only commenting out both helps.

    Signed-off-by: David Howells
    Signed-off-by: James Morris

    David Howells
     

24 May, 2012

1 commit

  • Change keyctl_session_to_parent() to use task_work_add() and move
    key_replace_session_keyring() logic into task_work->func().

    Note that we do task_work_cancel() before task_work_add() to ensure that
    only one work can be pending at any time. This is important, we must not
    allow user-space to abuse the parent's ->task_works list.

    The callback, replace_session_keyring(), checks PF_EXITING. I guess this
    is not really needed but looks better.

    As a side effect, this fixes the (unlikely) race. The callers of
    key_replace_session_keyring() and keyctl_session_to_parent() lack the
    necessary barriers, the parent can miss the request.

    Now we can remove task_struct->replacement_session_keyring and related
    code.

    Signed-off-by: Oleg Nesterov
    Acked-by: David Howells
    Cc: Thomas Gleixner
    Cc: Richard Kuo
    Cc: Linus Torvalds
    Cc: Alexander Gordeev
    Cc: Chris Zankel
    Cc: David Smith
    Cc: "Frank Ch. Eigler"
    Cc: Geert Uytterhoeven
    Cc: Larry Woodman
    Cc: Peter Zijlstra
    Cc: Tejun Heo
    Cc: Ingo Molnar
    Signed-off-by: Andrew Morton
    Signed-off-by: Al Viro

    Oleg Nesterov
     

11 May, 2012

1 commit

  • Add support for invalidating a key - which renders it immediately invisible to
    further searches and causes the garbage collector to immediately wake up,
    remove it from keyrings and then destroy it when it's no longer referenced.

    It's better not to do this with keyctl_revoke() as that marks the key to start
    returning -EKEYREVOKED to searches when what is actually desired is to have the
    key refetched.

    To invalidate a key the caller must be granted SEARCH permission by the key.
    This may be too strict. It may be better to also permit invalidation if the
    caller has any of READ, WRITE or SETATTR permission.

    The primary use for this is to evict keys that are cached in special keyrings,
    such as the DNS resolver or an ID mapper.

    Signed-off-by: David Howells

    David Howells
     

18 Jan, 2012

1 commit

  • For CIFS, we want to be able to store NTLM credentials (aka username
    and password) in the keyring. We do not, however want to allow users
    to fetch those keys back out of the keyring since that would be a
    security risk.

    Unfortunately, due to the nuances of key permission bits, it's not
    possible to do this. We need to grant search permissions so the kernel
    can find these keys, but that also implies permissions to read the
    payload.

    Resolve this by adding a new key_type. This key type is essentially
    the same as key_type_user, but does not define a .read op. This
    prevents the payload from ever being visible from userspace. This
    key type also vets the description to ensure that it's "qualified"
    by checking to ensure that it has a ':' in it that is preceded by
    other characters.

    Acked-by: David Howells
    Signed-off-by: Jeff Layton
    Signed-off-by: Steve French

    Jeff Layton
     

23 Aug, 2011

2 commits

  • unregister_key_type() has code to mark a key as dead and make it unavailable in
    one loop and then destroy all those unavailable key payloads in the next loop.
    However, the loop to mark keys dead renders the key undetectable to the second
    loop by changing the key type pointer also.

    Fix this by the following means:

    (1) The key code has two garbage collectors: one deletes unreferenced keys and
    the other alters keyrings to delete links to old dead, revoked and expired
    keys. They can end up holding each other up as both want to scan the key
    serial tree under spinlock. Combine these into a single routine.

    (2) Move the dead key marking, dead link removal and dead key removal into the
    garbage collector as a three phase process running over the three cycles
    of the normal garbage collection procedure. This is tracked by the
    KEY_GC_REAPING_DEAD_1, _2 and _3 state flags.

    unregister_key_type() then just unlinks the key type from the list, wakes
    up the garbage collector and waits for the third phase to complete.

    (3) Downgrade the key types sem in unregister_key_type() once it has deleted
    the key type from the list so that it doesn't block the keyctl() syscall.

    (4) Dead keys that cannot be simply removed in the third phase have their
    payloads destroyed with the key's semaphore write-locked to prevent
    interference by the keyctl() syscall. There should be no in-kernel users
    of dead keys of that type by the point of unregistration, though keyctl()
    may be holding a reference.

    (5) Only perform timer recalculation in the GC if the timer actually expired.
    If it didn't, we'll get another cycle when it goes off - and if the key
    that actually triggered it has been removed, it's not a problem.

    (6) Only garbage collect link if the timer expired or if we're doing dead key
    clean up phase 2.

    (7) As only key_garbage_collector() is permitted to use rb_erase() on the key
    serial tree, it doesn't need to revalidate its cursor after dropping the
    spinlock as the node the cursor points to must still exist in the tree.

    (8) Drop the spinlock in the GC if there is contention on it or if we need to
    reschedule. After dealing with that, get the spinlock again and resume
    scanning.

    This has been tested in the following ways:

    (1) Run the keyutils testsuite against it.

    (2) Using the AF_RXRPC and RxKAD modules to test keytype removal:

    Load the rxrpc_s key type:

    # insmod /tmp/af-rxrpc.ko
    # insmod /tmp/rxkad.ko

    Create a key (http://people.redhat.com/~dhowells/rxrpc/listen.c):

    # /tmp/listen &
    [1] 8173

    Find the key:

    # grep rxrpc_s /proc/keys
    091086e1 I--Q-- 1 perm 39390000 0 0 rxrpc_s 52:2

    Link it to a session keyring, preferably one with a higher serial number:

    # keyctl link 0x20e36251 @s

    Kill the process (the key should remain as it's linked to another place):

    # fg
    /tmp/listen
    ^C

    Remove the key type:

    rmmod rxkad
    rmmod af-rxrpc

    This can be made a more effective test by altering the following part of
    the patch:

    if (unlikely(gc_state & KEY_GC_REAPING_DEAD_2)) {
    /* Make sure everyone revalidates their keys if we marked a
    * bunch as being dead and make sure all keyring ex-payloads
    * are destroyed.
    */
    kdebug("dead sync");
    synchronize_rcu();

    To call synchronize_rcu() in GC phase 1 instead. That causes that the
    keyring's old payload content to hang around longer until it's RCU
    destroyed - which usually happens after GC phase 3 is complete. This
    allows the destroy_dead_key branch to be tested.

    Reported-by: Benjamin Coddington
    Signed-off-by: David Howells
    Signed-off-by: James Morris

    David Howells
     
  • Move the unreferenced key reaper function to the keys garbage collector file
    as that's a more appropriate place with the dead key link reaper.

    Signed-off-by: David Howells
    Signed-off-by: James Morris

    David Howells
     

17 Mar, 2011

1 commit

  • Improve /proc/keys by:

    (1) Don't attempt to summarise the payload of a negated key. It won't have
    one. To this end, a helper function - key_is_instantiated() has been
    added that allows the caller to find out whether the key is positively
    instantiated (as opposed to being uninstantiated or negatively
    instantiated).

    (2) Do show keys that are negative, expired or revoked rather than hiding
    them. This requires an override flag (no_state_check) to be passed to
    search_my_process_keyrings() and keyring_search_aux() to suppress this
    check.

    Without this, keys that are possessed by the caller, but only grant
    permissions to the caller if possessed are skipped as the possession check
    fails.

    Keys that are visible due to user, group or other checks are visible with
    or without this patch.

    Signed-off-by: David Howells
    Signed-off-by: James Morris

    David Howells
     

08 Mar, 2011

2 commits

  • Add a keyctl op (KEYCTL_INSTANTIATE_IOV) that is like KEYCTL_INSTANTIATE, but
    takes an iovec array and concatenates the data in-kernel into one buffer.
    Since the KEYCTL_INSTANTIATE copies the data anyway, this isn't too much of a
    problem.

    Signed-off-by: David Howells
    Signed-off-by: James Morris

    David Howells
     
  • Add a new keyctl op to reject a key with a specified error code. This works
    much the same as negating a key, and so keyctl_negate_key() is made a special
    case of keyctl_reject_key(). The difference is that keyctl_negate_key()
    selects ENOKEY as the error to be reported.

    Typically the key would be rejected with EKEYEXPIRED, EKEYREVOKED or
    EKEYREJECTED, but this is not mandatory.

    Signed-off-by: David Howells
    Signed-off-by: James Morris

    David Howells
     

26 Jan, 2011

1 commit

  • Fix __key_link_end()'s attempt to fix up the quota if an error occurs.

    There are two erroneous cases: Firstly, we always decrease the quota if
    the preallocated replacement keyring needs cleaning up, irrespective of
    whether or not we should (we may have replaced a pointer rather than
    adding another pointer).

    Secondly, we never clean up the quota if we added a pointer without the
    keyring storage being extended (we allocate multiple pointers at a time,
    even if we're not going to use them all immediately).

    We handle this by setting the bottom bit of the preallocation pointer in
    __key_link_begin() to indicate that the quota needs fixing up, which is
    then passed to __key_link() (which clears the whole thing) and
    __key_link_end().

    Signed-off-by: David Howells
    Signed-off-by: Linus Torvalds

    David Howells
     

22 Jan, 2011

1 commit


13 Aug, 2010

1 commit


02 Aug, 2010

1 commit

  • Make /proc/keys check to see if the calling process possesses each key before
    performing the security check. The possession check can be skipped if the key
    doesn't have the possessor-view permission bit set.

    This causes the keys a process possesses to show up in /proc/keys, even if they
    don't have matching user/group/other view permissions.

    Signed-off-by: David Howells
    Signed-off-by: James Morris

    David Howells
     

28 May, 2010

1 commit

  • call_usermodehelper_keys() uses call_usermodehelper_setkeys() to change
    subprocess_info->cred in advance. Now that we have info->init() we can
    change this code to set tgcred->session_keyring in context of execing
    kernel thread.

    Note: since currently call_usermodehelper_keys() is never called with
    UMH_NO_WAIT, call_usermodehelper_keys()->key_get() and umh_keys_cleanup()
    are not really needed, we could rely on install_session_keyring_to_cred()
    which does key_get() on success.

    Signed-off-by: Oleg Nesterov
    Acked-by: Neil Horman
    Acked-by: David Howells
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Oleg Nesterov
     

06 May, 2010

1 commit

  • Do preallocation for __key_link() so that the various callers in request_key.c
    can deal with any errors from this source before attempting to construct a key.
    This allows them to assume that the actual linkage step is guaranteed to be
    successful.

    Signed-off-by: David Howells
    Signed-off-by: James Morris

    David Howells
     

02 Sep, 2009

3 commits

  • Add a keyctl to install a process's session keyring onto its parent. This
    replaces the parent's session keyring. Because the COW credential code does
    not permit one process to change another process's credentials directly, the
    change is deferred until userspace next starts executing again. Normally this
    will be after a wait*() syscall.

    To support this, three new security hooks have been provided:
    cred_alloc_blank() to allocate unset security creds, cred_transfer() to fill in
    the blank security creds and key_session_to_parent() - which asks the LSM if
    the process may replace its parent's session keyring.

    The replacement may only happen if the process has the same ownership details
    as its parent, and the process has LINK permission on the session keyring, and
    the session keyring is owned by the process, and the LSM permits it.

    Note that this requires alteration to each architecture's notify_resume path.
    This has been done for all arches barring blackfin, m68k* and xtensa, all of
    which need assembly alteration to support TIF_NOTIFY_RESUME. This allows the
    replacement to be performed at the point the parent process resumes userspace
    execution.

    This allows the userspace AFS pioctl emulation to fully emulate newpag() and
    the VIOCSETTOK and VIOCSETTOK2 pioctls, all of which require the ability to
    alter the parent process's PAG membership. However, since kAFS doesn't use
    PAGs per se, but rather dumps the keys into the session keyring, the session
    keyring of the parent must be replaced if, for example, VIOCSETTOK is passed
    the newpag flag.

    This can be tested with the following program:

    #include
    #include
    #include

    #define KEYCTL_SESSION_TO_PARENT 18

    #define OSERROR(X, S) do { if ((long)(X) == -1) { perror(S); exit(1); } } while(0)

    int main(int argc, char **argv)
    {
    key_serial_t keyring, key;
    long ret;

    keyring = keyctl_join_session_keyring(argv[1]);
    OSERROR(keyring, "keyctl_join_session_keyring");

    key = add_key("user", "a", "b", 1, keyring);
    OSERROR(key, "add_key");

    ret = keyctl(KEYCTL_SESSION_TO_PARENT);
    OSERROR(ret, "KEYCTL_SESSION_TO_PARENT");

    return 0;
    }

    Compiled and linked with -lkeyutils, you should see something like:

    [dhowells@andromeda ~]$ keyctl show
    Session Keyring
    -3 --alswrv 4043 4043 keyring: _ses
    355907932 --alswrv 4043 -1 \_ keyring: _uid.4043
    [dhowells@andromeda ~]$ /tmp/newpag
    [dhowells@andromeda ~]$ keyctl show
    Session Keyring
    -3 --alswrv 4043 4043 keyring: _ses
    1055658746 --alswrv 4043 4043 \_ user: a
    [dhowells@andromeda ~]$ /tmp/newpag hello
    [dhowells@andromeda ~]$ keyctl show
    Session Keyring
    -3 --alswrv 4043 4043 keyring: hello
    340417692 --alswrv 4043 4043 \_ user: a

    Where the test program creates a new session keyring, sticks a user key named
    'a' into it and then installs it on its parent.

    Signed-off-by: David Howells
    Signed-off-by: James Morris

    David Howells
     
  • Add garbage collection for dead, revoked and expired keys. This involved
    erasing all links to such keys from keyrings that point to them. At that
    point, the key will be deleted in the normal manner.

    Keyrings from which garbage collection occurs are shrunk and their quota
    consumption reduced as appropriate.

    Dead keys (for which the key type has been removed) will be garbage collected
    immediately.

    Revoked and expired keys will hang around for a number of seconds, as set in
    /proc/sys/kernel/keys/gc_delay before being automatically removed. The default
    is 5 minutes.

    Signed-off-by: David Howells
    Signed-off-by: James Morris

    David Howells
     
  • Allow keys for which the key type has been removed to be unlinked. Currently
    dead-type keys can only be disposed of by completely clearing the keyrings
    that point to them.

    Signed-off-by: David Howells
    Acked-by: Serge Hallyn
    Signed-off-by: James Morris

    David Howells
     

27 Feb, 2009

1 commit

  • per-uid keys were looked by uid only. Use the user namespace
    to distinguish the same uid in different namespaces.

    This does not address key_permission. So a task can for instance
    try to join a keyring owned by the same uid in another namespace.
    That will be handled by a separate patch.

    Signed-off-by: Serge E. Hallyn
    Acked-by: David Howells
    Signed-off-by: James Morris

    Serge E. Hallyn
     

14 Nov, 2008

1 commit

  • Inaugurate copy-on-write credentials management. This uses RCU to manage the
    credentials pointer in the task_struct with respect to accesses by other tasks.
    A process may only modify its own credentials, and so does not need locking to
    access or modify its own credentials.

    A mutex (cred_replace_mutex) is added to the task_struct to control the effect
    of PTRACE_ATTACHED on credential calculations, particularly with respect to
    execve().

    With this patch, the contents of an active credentials struct may not be
    changed directly; rather a new set of credentials must be prepared, modified
    and committed using something like the following sequence of events:

    struct cred *new = prepare_creds();
    int ret = blah(new);
    if (ret < 0) {
    abort_creds(new);
    return ret;
    }
    return commit_creds(new);

    There are some exceptions to this rule: the keyrings pointed to by the active
    credentials may be instantiated - keyrings violate the COW rule as managing
    COW keyrings is tricky, given that it is possible for a task to directly alter
    the keys in a keyring in use by another task.

    To help enforce this, various pointers to sets of credentials, such as those in
    the task_struct, are declared const. The purpose of this is compile-time
    discouragement of altering credentials through those pointers. Once a set of
    credentials has been made public through one of these pointers, it may not be
    modified, except under special circumstances:

    (1) Its reference count may incremented and decremented.

    (2) The keyrings to which it points may be modified, but not replaced.

    The only safe way to modify anything else is to create a replacement and commit
    using the functions described in Documentation/credentials.txt (which will be
    added by a later patch).

    This patch and the preceding patches have been tested with the LTP SELinux
    testsuite.

    This patch makes several logical sets of alteration:

    (1) execve().

    This now prepares and commits credentials in various places in the
    security code rather than altering the current creds directly.

    (2) Temporary credential overrides.

    do_coredump() and sys_faccessat() now prepare their own credentials and
    temporarily override the ones currently on the acting thread, whilst
    preventing interference from other threads by holding cred_replace_mutex
    on the thread being dumped.

    This will be replaced in a future patch by something that hands down the
    credentials directly to the functions being called, rather than altering
    the task's objective credentials.

    (3) LSM interface.

    A number of functions have been changed, added or removed:

    (*) security_capset_check(), ->capset_check()
    (*) security_capset_set(), ->capset_set()

    Removed in favour of security_capset().

    (*) security_capset(), ->capset()

    New. This is passed a pointer to the new creds, a pointer to the old
    creds and the proposed capability sets. It should fill in the new
    creds or return an error. All pointers, barring the pointer to the
    new creds, are now const.

    (*) security_bprm_apply_creds(), ->bprm_apply_creds()

    Changed; now returns a value, which will cause the process to be
    killed if it's an error.

    (*) security_task_alloc(), ->task_alloc_security()

    Removed in favour of security_prepare_creds().

    (*) security_cred_free(), ->cred_free()

    New. Free security data attached to cred->security.

    (*) security_prepare_creds(), ->cred_prepare()

    New. Duplicate any security data attached to cred->security.

    (*) security_commit_creds(), ->cred_commit()

    New. Apply any security effects for the upcoming installation of new
    security by commit_creds().

    (*) security_task_post_setuid(), ->task_post_setuid()

    Removed in favour of security_task_fix_setuid().

    (*) security_task_fix_setuid(), ->task_fix_setuid()

    Fix up the proposed new credentials for setuid(). This is used by
    cap_set_fix_setuid() to implicitly adjust capabilities in line with
    setuid() changes. Changes are made to the new credentials, rather
    than the task itself as in security_task_post_setuid().

    (*) security_task_reparent_to_init(), ->task_reparent_to_init()

    Removed. Instead the task being reparented to init is referred
    directly to init's credentials.

    NOTE! This results in the loss of some state: SELinux's osid no
    longer records the sid of the thread that forked it.

    (*) security_key_alloc(), ->key_alloc()
    (*) security_key_permission(), ->key_permission()

    Changed. These now take cred pointers rather than task pointers to
    refer to the security context.

    (4) sys_capset().

    This has been simplified and uses less locking. The LSM functions it
    calls have been merged.

    (5) reparent_to_kthreadd().

    This gives the current thread the same credentials as init by simply using
    commit_thread() to point that way.

    (6) __sigqueue_alloc() and switch_uid()

    __sigqueue_alloc() can't stop the target task from changing its creds
    beneath it, so this function gets a reference to the currently applicable
    user_struct which it then passes into the sigqueue struct it returns if
    successful.

    switch_uid() is now called from commit_creds(), and possibly should be
    folded into that. commit_creds() should take care of protecting
    __sigqueue_alloc().

    (7) [sg]et[ug]id() and co and [sg]et_current_groups.

    The set functions now all use prepare_creds(), commit_creds() and
    abort_creds() to build and check a new set of credentials before applying
    it.

    security_task_set[ug]id() is called inside the prepared section. This
    guarantees that nothing else will affect the creds until we've finished.

    The calling of set_dumpable() has been moved into commit_creds().

    Much of the functionality of set_user() has been moved into
    commit_creds().

    The get functions all simply access the data directly.

    (8) security_task_prctl() and cap_task_prctl().

    security_task_prctl() has been modified to return -ENOSYS if it doesn't
    want to handle a function, or otherwise return the return value directly
    rather than through an argument.

    Additionally, cap_task_prctl() now prepares a new set of credentials, even
    if it doesn't end up using it.

    (9) Keyrings.

    A number of changes have been made to the keyrings code:

    (a) switch_uid_keyring(), copy_keys(), exit_keys() and suid_keys() have
    all been dropped and built in to the credentials functions directly.
    They may want separating out again later.

    (b) key_alloc() and search_process_keyrings() now take a cred pointer
    rather than a task pointer to specify the security context.

    (c) copy_creds() gives a new thread within the same thread group a new
    thread keyring if its parent had one, otherwise it discards the thread
    keyring.

    (d) The authorisation key now points directly to the credentials to extend
    the search into rather pointing to the task that carries them.

    (e) Installing thread, process or session keyrings causes a new set of
    credentials to be created, even though it's not strictly necessary for
    process or session keyrings (they're shared).

    (10) Usermode helper.

    The usermode helper code now carries a cred struct pointer in its
    subprocess_info struct instead of a new session keyring pointer. This set
    of credentials is derived from init_cred and installed on the new process
    after it has been cloned.

    call_usermodehelper_setup() allocates the new credentials and
    call_usermodehelper_freeinfo() discards them if they haven't been used. A
    special cred function (prepare_usermodeinfo_creds()) is provided
    specifically for call_usermodehelper_setup() to call.

    call_usermodehelper_setkeys() adjusts the credentials to sport the
    supplied keyring as the new session keyring.

    (11) SELinux.

    SELinux has a number of changes, in addition to those to support the LSM
    interface changes mentioned above:

    (a) selinux_setprocattr() no longer does its check for whether the
    current ptracer can access processes with the new SID inside the lock
    that covers getting the ptracer's SID. Whilst this lock ensures that
    the check is done with the ptracer pinned, the result is only valid
    until the lock is released, so there's no point doing it inside the
    lock.

    (12) is_single_threaded().

    This function has been extracted from selinux_setprocattr() and put into
    a file of its own in the lib/ directory as join_session_keyring() now
    wants to use it too.

    The code in SELinux just checked to see whether a task shared mm_structs
    with other tasks (CLONE_VM), but that isn't good enough. We really want
    to know if they're part of the same thread group (CLONE_THREAD).

    (13) nfsd.

    The NFS server daemon now has to use the COW credentials to set the
    credentials it is going to use. It really needs to pass the credentials
    down to the functions it calls, but it can't do that until other patches
    in this series have been applied.

    Signed-off-by: David Howells
    Acked-by: James Morris
    Signed-off-by: James Morris

    David Howells