04 Apr, 2014

1 commit

  • Pull security subsystem updates from James Morris:
    "Apart from reordering the SELinux mmap code to ensure DAC is called
    before MAC, these are minor maintenance updates"

    * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (23 commits)
    selinux: correctly label /proc inodes in use before the policy is loaded
    selinux: put the mmap() DAC controls before the MAC controls
    selinux: fix the output of ./scripts/get_maintainer.pl for SELinux
    evm: enable key retention service automatically
    ima: skip memory allocation for empty files
    evm: EVM does not use MD5
    ima: return d_name.name if d_path fails
    integrity: fix checkpatch errors
    ima: fix erroneous removal of security.ima xattr
    security: integrity: Use a more current logging style
    MAINTAINERS: email updates and other misc. changes
    ima: reduce memory usage when a template containing the n field is used
    ima: restore the original behavior for sending data with ima template
    Integrity: Pass commname via get_task_comm()
    fs: move i_readcount
    ima: use static const char array definitions
    security: have cap_dentry_init_security return error
    ima: new helper: file_inode(file)
    kernel: Mark function as static in kernel/seccomp.c
    capability: Use current logging styles
    ...

    Linus Torvalds
     

01 Apr, 2014

1 commit

  • Pull s390 compat wrapper rework from Heiko Carstens:
    "S390 compat system call wrapper simplification work.

    The intention of this work is to get rid of all hand written assembly
    compat system call wrappers on s390, which perform proper sign or zero
    extension, or pointer conversion of compat system call parameters.
    Instead all of this should be done with C code eg by using Al's
    COMPAT_SYSCALL_DEFINEx() macro.

    Therefore all common code and s390 specific compat system calls have
    been converted to the COMPAT_SYSCALL_DEFINEx() macro.

    In order to generate correct code all compat system calls may only
    have eg compat_ulong_t parameters, but no unsigned long parameters.
    Those patches which change parameter types from unsigned long to
    compat_ulong_t parameters are separate in this series, but shouldn't
    cause any harm.

    The only compat system calls which intentionally have 64 bit
    parameters (preadv64 and pwritev64) in support of the x86/32 ABI
    haven't been changed, but are now only available if an architecture
    defines __ARCH_WANT_COMPAT_SYS_PREADV64/PWRITEV64.

    System calls which do not have a compat variant but still need proper
    zero extension on s390, like eg "long sys_brk(unsigned long brk)" will
    get a proper wrapper function with the new s390 specific
    COMPAT_SYSCALL_WRAPx() macro:

    COMPAT_SYSCALL_WRAP1(brk, unsigned long, brk);

    which generates the following code (simplified):

    asmlinkage long sys_brk(unsigned long brk);
    asmlinkage long compat_sys_brk(long brk)
    {
    return sys_brk((u32)brk);
    }

    Given that the C file which contains all the COMPAT_SYSCALL_WRAP lines
    includes both linux/syscall.h and linux/compat.h, it will generate
    build errors, if the declaration of sys_brk() doesn't match, or if
    there exists a non-matching compat_sys_brk() declaration.

    In addition this will intentionally result in a link error if
    somewhere else a compat_sys_brk() function exists, which probably
    should have been used instead. Two more BUILD_BUG_ONs make sure the
    size and type of each compat syscall parameter can be handled
    correctly with the s390 specific macros.

    I converted the compat system calls step by step to verify the
    generated code is correct and matches the previous code. In fact it
    did not always match, however that was always a bug in the hand
    written asm code.

    In result we get less code, less bugs, and much more sanity checking"

    * 'compat' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux: (44 commits)
    s390/compat: add copyright statement
    compat: include linux/unistd.h within linux/compat.h
    s390/compat: get rid of compat wrapper assembly code
    s390/compat: build error for large compat syscall args
    mm/compat: convert to COMPAT_SYSCALL_DEFINE with changing parameter types
    kexec/compat: convert to COMPAT_SYSCALL_DEFINE with changing parameter types
    net/compat: convert to COMPAT_SYSCALL_DEFINE with changing parameter types
    ipc/compat: convert to COMPAT_SYSCALL_DEFINE with changing parameter types
    fs/compat: convert to COMPAT_SYSCALL_DEFINE with changing parameter types
    ipc/compat: convert to COMPAT_SYSCALL_DEFINE
    fs/compat: convert to COMPAT_SYSCALL_DEFINE
    security/compat: convert to COMPAT_SYSCALL_DEFINE
    mm/compat: convert to COMPAT_SYSCALL_DEFINE
    net/compat: convert to COMPAT_SYSCALL_DEFINE
    kernel/compat: convert to COMPAT_SYSCALL_DEFINE
    fs/compat: optional preadv64/pwrite64 compat system calls
    ipc/compat_sys_msgrcv: change msgtyp type from long to compat_long_t
    s390/compat: partial parameter conversion within syscall wrappers
    s390/compat: automatic zero, sign and pointer conversion of syscalls
    s390/compat: add sync_file_range and fallocate compat syscalls
    ...

    Linus Torvalds
     

10 Mar, 2014

1 commit

  • This fixes CVE-2014-0102.

    The following command sequence produces an oops:

    keyctl new_session
    i=`keyctl newring _ses @s`
    keyctl link @s $i

    The problem is that search_nested_keyrings() sees two keyrings that have
    matching type and description, so keyring_compare_object() returns true.
    s_n_k() then passes the key to the iterator function -
    keyring_detect_cycle_iterator() - which *should* check to see whether this is
    the keyring of interest, not just one with the same name.

    Because assoc_array_find() will return one and only one match, I assumed that
    the iterator function would only see an exact match or never be called - but
    the iterator isn't only called from assoc_array_find()...

    The oops looks something like this:

    kernel BUG at /data/fs/linux-2.6-fscache/security/keys/keyring.c:1003!
    invalid opcode: 0000 [#1] SMP
    ...
    RIP: keyring_detect_cycle_iterator+0xe/0x1f
    ...
    Call Trace:
    search_nested_keyrings+0x76/0x2aa
    __key_link_check_live_key+0x50/0x5f
    key_link+0x4e/0x85
    keyctl_keyring_link+0x60/0x81
    SyS_keyctl+0x65/0xe4
    tracesys+0xdd/0xe2

    The fix is to make keyring_detect_cycle_iterator() check that the key it
    has is the key it was actually looking for rather than calling BUG_ON().

    A testcase has been included in the keyutils testsuite for this:

    http://git.kernel.org/cgit/linux/kernel/git/dhowells/keyutils.git/commit/?id=891f3365d07f1996778ade0e3428f01878a1790b

    Reported-by: Tommi Rantala
    Signed-off-by: David Howells
    Acked-by: James Morris
    Signed-off-by: Linus Torvalds

    David Howells
     

06 Mar, 2014

1 commit

  • Convert all compat system call functions where all parameter types
    have a size of four or less than four bytes, or are pointer types
    to COMPAT_SYSCALL_DEFINE.
    The implicit casts within COMPAT_SYSCALL_DEFINE will perform proper
    zero and sign extension to 64 bit of all parameters if needed.

    Signed-off-by: Heiko Carstens

    Heiko Carstens
     

06 Feb, 2014

1 commit


02 Dec, 2013

5 commits

  • We have a problem where the big_key key storage implementation uses a
    shmem backed inode to hold the key contents. Because of this detail of
    implementation LSM checks are being done between processes trying to
    read the keys and the tmpfs backed inode. The LSM checks are already
    being handled on the key interface level and should not be enforced at
    the inode level (since the inode is an implementation detail, not a
    part of the security model)

    This patch implements a new function shmem_kernel_file_setup() which
    returns the equivalent to shmem_file_setup() only the underlying inode
    has S_PRIVATE set. This means that all LSM checks for the inode in
    question are skipped. It should only be used for kernel internal
    operations where the inode is not exposed to userspace without proper
    LSM checking. It is possible that some other users of
    shmem_file_setup() should use the new interface, but this has not been
    explored.

    Reproducing this bug is a little bit difficult. The steps I used on
    Fedora are:

    (1) Turn off selinux enforcing:

    setenforce 0

    (2) Create a huge key

    k=`dd if=/dev/zero bs=8192 count=1 | keyctl padd big_key test-key @s`

    (3) Access the key in another context:

    runcon system_u:system_r:httpd_t:s0-s0:c0.c1023 keyctl print $k >/dev/null

    (4) Examine the audit logs:

    ausearch -m AVC -i --subject httpd_t | audit2allow

    If the last command's output includes a line that looks like:

    allow httpd_t user_tmpfs_t:file { open read };

    There was an inode check between httpd and the tmpfs filesystem. With
    this patch no such denial will be seen. (NOTE! you should clear your
    audit log if you have tested for this previously)

    (Please return you box to enforcing)

    Signed-off-by: Eric Paris
    Signed-off-by: David Howells
    cc: Hugh Dickins
    cc: linux-mm@kvack.org

    Eric Paris
     
  • If a keyring contains more than 16 keyrings (the capacity of a single node in
    the associative array) then those keyrings are split over multiple nodes
    arranged as a tree.

    If search_nested_keyrings() is called to search the keyring then it will
    attempt to manually walk over just the 0 branch of the associative array tree
    where all the keyring links are stored. This works provided the key is found
    before the algorithm steps from one node containing keyrings to a child node
    or if there are sufficiently few keyring links that the keyrings are all in
    one node.

    However, if the algorithm does need to step from a node to a child node, it
    doesn't change the node pointer unless a shortcut also gets transited. This
    means that the algorithm will keep scanning the same node over and over again
    without terminating and without returning.

    To fix this, move the internal-pointer-to-node translation from inside the
    shortcut transit handler so that it applies it to node arrival as well.

    This can be tested by:

    r=`keyctl newring sandbox @s`
    for ((i=0; i
    Tested-by: Stephen Gallagher

    David Howells
     
  • If sufficient keys (or keyrings) are added into a keyring such that a node in
    the associative array's tree overflows (each node has a capacity N, currently
    16) and such that all N+1 keys have the same index key segment for that level
    of the tree (the level'th nibble of the index key), then assoc_array_insert()
    calls ops->diff_objects() to indicate at which bit position the two index keys
    vary.

    However, __key_link_begin() passes a NULL object to assoc_array_insert() with
    the intention of supplying the correct pointer later before we commit the
    change. This means that keyring_diff_objects() is given a NULL pointer as one
    of its arguments which it does not expect. This results in an oops like the
    attached.

    With the previous patch to fix the keyring hash function, this can be forced
    much more easily by creating a keyring and only adding keyrings to it. Add any
    other sort of key and a different insertion path is taken - all 16+1 objects
    must want to cluster in the same node slot.

    This can be tested by:

    r=`keyctl newring sandbox @s`
    for ((i=0; idiff_objects() is always called with the first pointer pointing to
    the object to be inserted (ie. the NULL pointer), we can fix the problem by
    changing the to-be-inserted object pointer to point to the index key passed
    into assoc_array_insert() instead.

    Whilst we're at it, we also switch the arguments so that they are the same as
    for ->compare_object().

    BUG: unable to handle kernel NULL pointer dereference at 0000000000000088
    IP: [] hash_key_type_and_desc+0x18/0xb0
    ...
    RIP: 0010:[] hash_key_type_and_desc+0x18/0xb0
    ...
    Call Trace:
    [] keyring_diff_objects+0x21/0xd2
    [] assoc_array_insert+0x3b6/0x908
    [] __key_link_begin+0x78/0xe5
    [] key_create_or_update+0x17d/0x36a
    [] SyS_add_key+0x123/0x183
    [] tracesys+0xdd/0xe2

    Signed-off-by: David Howells
    Tested-by: Stephen Gallagher

    David Howells
     
  • The keyring hash function (used by the associative array) is supposed to clear
    the bottommost nibble of the index key (where the hash value resides) for
    keyrings and make sure it is non-zero for non-keyrings. This is done to make
    keyrings cluster together on one branch of the tree separately to other keys.

    Unfortunately, the wrong mask is used, so only the bottom two bits are
    examined and cleared and not the whole bottom nibble. This means that keys
    and keyrings can still be successfully searched for under most circumstances
    as the hash is consistent in its miscalculation, but if a keyring's
    associative array bottom node gets filled up then approx 75% of the keyrings
    will not be put into the 0 branch.

    The consequence of this is that a key in a keyring linked to by another
    keyring, ie.

    keyring A -> keyring B -> key

    may not be found if the search starts at keyring A and then descends into
    keyring B because search_nested_keyrings() only searches up the 0 branch (as it
    "knows" all keyrings must be there and not elsewhere in the tree).

    The fix is to use the right mask.

    This can be tested with:

    r=`keyctl newring sandbox @s`
    for ((i=0; i
    Signed-off-by: David Howells
    Tested-by: Stephen Gallagher

    David Howells
     
  • The second word of key->payload does not get initialised in key_alloc(), but
    the big_key type is relying on it having been cleared. The problem comes when
    big_key fails to instantiate a large key and doesn't then set the payload. The
    big_key_destroy() op is called from the garbage collector and this assumes that
    the dentry pointer stored in the second word will be NULL if instantiation did
    not complete.

    Therefore just pre-clear the entire struct key on allocation rather than trying
    to be clever and only initialising to 0 only those bits that aren't otherwise
    initialised.

    The lack of initialisation can lead to a bug report like the following if
    big_key failed to initialise its file:

    general protection fault: 0000 [#1] SMP
    Modules linked in: ...
    CPU: 0 PID: 51 Comm: kworker/0:1 Not tainted 3.10.0-53.el7.x86_64 #1
    Hardware name: Dell Inc. PowerEdge 1955/0HC513, BIOS 1.4.4 12/09/2008
    Workqueue: events key_garbage_collector
    task: ffff8801294f5680 ti: ffff8801296e2000 task.ti: ffff8801296e2000
    RIP: 0010:[] dput+0x21/0x2d0
    ...
    Call Trace:
    [] path_put+0x16/0x30
    [] big_key_destroy+0x44/0x60
    [] key_gc_unused_keys.constprop.2+0x5b/0xe0
    [] key_garbage_collector+0x1df/0x3c0
    [] process_one_work+0x17b/0x460
    [] worker_thread+0x11b/0x400
    [] ? rescuer_thread+0x3e0/0x3e0
    [] kthread+0xc0/0xd0
    [] ? kthread_create_on_node+0x110/0x110
    [] ret_from_fork+0x7c/0xb0
    [] ? kthread_create_on_node+0x110/0x110

    Reported-by: Patrik Kis
    Signed-off-by: David Howells
    Reviewed-by: Stephen Gallagher

    David Howells
     

14 Nov, 2013

2 commits

  • Key pointers stored in the keyring are marked in bit 1 to indicate if they
    point to a keyring. We need to strip off this bit before using the pointer
    when iterating over the keyring for the purpose of looking for links to garbage
    collect.

    This means that expirable keyrings aren't correctly expiring because the
    checker is seeing their key pointer with 2 added to it.

    Since the fix for this involves knowing about the internals of the keyring,
    key_gc_keyring() is moved to keyring.c and merged into keyring_gc().

    This can be tested by:

    echo 2 >/proc/sys/kernel/keys/gc_delay
    keyctl timeout `keyctl add keyring qwerty "" @s` 2
    cat /proc/keys
    sleep 5; cat /proc/keys

    which should see a keyring called "qwerty" appear in the session keyring and
    then disappear after it expires, and:

    echo 2 >/proc/sys/kernel/keys/gc_delay
    a=`keyctl get_persistent @s`
    b=`keyctl add keyring 0 "" $a`
    keyctl add user a a $b
    keyctl timeout $b 2
    cat /proc/keys
    sleep 5; cat /proc/keys

    which should see a keyring called "0" with a key called "a" in it appear in the
    user's persistent keyring (which will be attached to the session keyring) and
    then both the "0" keyring and the "a" key should disappear when the "0" keyring
    expires.

    Signed-off-by: David Howells
    Acked-by: Simo Sorce

    David Howells
     
  • In the big_key_instantiate() function we return 0 if kernel_write() returns us
    an error rather than returning an error. This can potentially lead to
    dentry_open() giving a BUG when called from big_key_read() with an unset
    tmpfile path.

    ------------[ cut here ]------------
    kernel BUG at fs/open.c:798!
    ...
    RIP: 0010:[] dentry_open+0xd1/0xe0
    ...
    Call Trace:
    [] big_key_read+0x55/0x100
    [] keyctl_read_key+0xb4/0xe0
    [] SyS_keyctl+0xf8/0x1d0
    [] system_call_fastpath+0x16/0x1b

    Signed-off-by: David Howells
    Reviewed-by: Stephen Gallagher

    David Howells
     

06 Nov, 2013

1 commit

  • If the UID is specified by userspace when calling the KEYCTL_GET_PERSISTENT
    function and the process does not have the CAP_SETUID capability, then the
    function will return -EPERM if the current process's uid, suid, euid and fsuid
    all match the requested UID. This is incorrect.

    Fix it such that when a non-privileged caller requests a persistent keyring by
    a specific UID they can only request their own (ie. the specified UID matches
    either then process's UID or the process's EUID).

    This can be tested by logging in as the user and doing:

    keyctl get_persistent @p
    keyctl get_persistent @p `id -u`
    keyctl get_persistent @p 0

    The first two should successfully print the same key ID. The third should do
    the same if called by UID 0 or indicate Operation Not Permitted otherwise.

    Signed-off-by: David Howells
    Acked-by: Stephen Gallagher

    David Howells
     

30 Oct, 2013

4 commits

  • Fix to return a negative error code from the error handling
    case instead of 0, as done elsewhere in this function.

    Signed-off-by: Wei Yongjun
    Signed-off-by: David Howells

    Wei Yongjun
     
  • If a key is displaced from a keyring by a matching one, then four more bytes
    of quota are allocated to the keyring - despite the fact that the keyring does
    not change in size.

    Further, when a key is unlinked from a keyring, the four bytes of quota
    allocated the link isn't recovered and returned to the user's pool.

    The first can be tested by repeating:

    keyctl add big_key a fred @s
    cat /proc/key-users

    (Don't put it in a shell loop otherwise the garbage collector won't have time
    to clear the displaced keys, thus affecting the result).

    This was causing the kerberos keyring to run out of room fairly quickly.

    The second can be tested by:

    cat /proc/key-users
    a=`keyctl add user a a @s`
    cat /proc/key-users
    keyctl unlink $a
    sleep 1 # Give RCU a chance to delete the key
    cat /proc/key-users

    assuming no system activity that otherwise adds/removes keys, the amount of
    key data allocated should go up (say 40/20000 -> 47/20000) and then return to
    the original value at the end.

    Reported-by: Stephen Gallagher
    Signed-off-by: David Howells

    David Howells
     
  • key_reject_and_link() marking a key as negative and setting the error with
    which it was negated races with keyring searches and other things that read
    that error.

    The fix is to switch the order in which the assignments are done in
    key_reject_and_link() and to use memory barriers.

    Kudos to Dave Wysochanski and Scott Mayhew
    for tracking this down.

    This may be the cause of:

    BUG: unable to handle kernel NULL pointer dereference at 0000000000000070
    IP: [] wait_for_key_construction+0x31/0x80
    PGD c6b2c3067 PUD c59879067 PMD 0
    Oops: 0000 [#1] SMP
    last sysfs file: /sys/devices/system/cpu/cpu3/cache/index2/shared_cpu_map
    CPU 0
    Modules linked in: ...

    Pid: 13359, comm: amqzxma0 Not tainted 2.6.32-358.20.1.el6.x86_64 #1 IBM System x3650 M3 -[7945PSJ]-/00J6159
    RIP: 0010:[] wait_for_key_construction+0x31/0x80
    RSP: 0018:ffff880c6ab33758 EFLAGS: 00010246
    RAX: ffffffff81219080 RBX: 0000000000000000 RCX: 0000000000000002
    RDX: ffffffff81219060 RSI: 0000000000000000 RDI: 0000000000000000
    RBP: ffff880c6ab33768 R08: 0000000000000000 R09: 0000000000000000
    R10: 0000000000000001 R11: 0000000000000000 R12: ffff880adfcbce40
    R13: ffffffffa03afb84 R14: ffff880adfcbce40 R15: ffff880adfcbce43
    FS: 00007f29b8042700(0000) GS:ffff880028200000(0000) knlGS:0000000000000000
    CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
    CR2: 0000000000000070 CR3: 0000000c613dc000 CR4: 00000000000007f0
    DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
    DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
    Process amqzxma0 (pid: 13359, threadinfo ffff880c6ab32000, task ffff880c610deae0)
    Stack:
    ffff880adfcbce40 0000000000000000 ffff880c6ab337b8 ffffffff81219695
    0000000000000000 ffff880a000000d0 ffff880c6ab337a8 000000000000000f
    ffffffffa03afb93 000000000000000f ffff88186c7882c0 0000000000000014
    Call Trace:
    [] request_key+0x65/0xa0
    [] nfs_idmap_request_key+0xc5/0x170 [nfs]
    [] nfs_idmap_lookup_id+0x34/0x80 [nfs]
    [] nfs_map_group_to_gid+0x75/0xa0 [nfs]
    [] decode_getfattr_attrs+0xbdd/0xfb0 [nfs]
    [] ? __dequeue_entity+0x30/0x50
    [] ? __switch_to+0x26e/0x320
    [] decode_getfattr+0x83/0xe0 [nfs]
    [] ? nfs4_xdr_dec_getattr+0x0/0xa0 [nfs]
    [] nfs4_xdr_dec_getattr+0x8f/0xa0 [nfs]
    [] rpcauth_unwrap_resp+0x84/0xb0 [sunrpc]
    [] ? nfs4_xdr_dec_getattr+0x0/0xa0 [nfs]
    [] call_decode+0x1b3/0x800 [sunrpc]
    [] ? wake_bit_function+0x0/0x50
    [] ? call_decode+0x0/0x800 [sunrpc]
    [] __rpc_execute+0x77/0x350 [sunrpc]
    [] ? bit_waitqueue+0x17/0xd0
    [] rpc_execute+0x61/0xa0 [sunrpc]
    [] rpc_run_task+0x75/0x90 [sunrpc]
    [] rpc_call_sync+0x42/0x70 [sunrpc]
    [] _nfs4_call_sync+0x30/0x40 [nfs]
    [] _nfs4_proc_getattr+0xac/0xc0 [nfs]
    [] ? futex_wait+0x227/0x380
    [] nfs4_proc_getattr+0x56/0x80 [nfs]
    [] __nfs_revalidate_inode+0xe3/0x220 [nfs]
    [] nfs_revalidate_mapping+0x4e/0x170 [nfs]
    [] nfs_file_read+0x77/0x130 [nfs]
    [] do_sync_read+0xfa/0x140
    [] ? autoremove_wake_function+0x0/0x40
    [] ? apic_timer_interrupt+0xe/0x20
    [] ? common_interrupt+0xe/0x13
    [] ? selinux_file_permission+0xfb/0x150
    [] ? security_file_permission+0x16/0x20
    [] vfs_read+0xb5/0x1a0
    [] sys_read+0x51/0x90
    [] ? __audit_syscall_exit+0x265/0x290
    [] system_call_fastpath+0x16/0x1b

    Signed-off-by: David Howells
    cc: Dave Wysochanski
    cc: Scott Mayhew

    David Howells
     
  • Having the big_keys functionality as a module is very marginally useful.
    The userspace code that would use this functionality will get odd error
    messages from the keys layer if the module isn't loaded. The code itself
    is fairly small, so just have this as a boolean option and not a tristate.

    Signed-off-by: Josh Boyer
    Signed-off-by: David Howells

    Josh Boyer
     

26 Sep, 2013

2 commits


24 Sep, 2013

11 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
     
  • Implement a big key type that can save its contents to tmpfs and thus
    swapspace when memory is tight. This is useful for Kerberos ticket caches.

    Signed-off-by: David Howells
    Tested-by: Simo Sorce

    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
     
  • Define a __key_get() wrapper to use rather than atomic_inc() on the key usage
    count as this makes it easier to hook in refcount error debugging.

    Signed-off-by: David Howells

    David Howells
     
  • Search for auth-key by name rather than by target key ID as, in a future
    patch, we'll by searching directly by index key in preference to iteration
    over all keys.

    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
     
  • Make make_key_ref() take a bool possession parameter and make
    is_key_possessed() return a bool.

    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
     

01 May, 2013

1 commit

  • Use call_usermodehelper_setup() + call_usermodehelper_exec() instead of
    calling call_usermodehelper_fns(). In case there's an OOM in this last
    function the cleanup function may not be called - in this case we would
    miss a call to key_put().

    Signed-off-by: Lucas De Marchi
    Cc: Oleg Nesterov
    Acked-by: David Howells
    Acked-by: James Morris
    Cc: Al Viro
    Cc: Tejun Heo
    Cc: "Rafael J. Wysocki"
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Lucas De Marchi
     

13 Mar, 2013

1 commit

  • Looking at mm/process_vm_access.c:process_vm_rw() and comparing it to
    compat_process_vm_rw() shows that the compatibility code requires an
    explicit "access_ok()" check before calling
    compat_rw_copy_check_uvector(). The same difference seems to appear when
    we compare fs/read_write.c:do_readv_writev() to
    fs/compat.c:compat_do_readv_writev().

    This subtle difference between the compat and non-compat requirements
    should probably be debated, as it seems to be error-prone. In fact,
    there are two others sites that use this function in the Linux kernel,
    and they both seem to get it wrong:

    Now shifting our attention to fs/aio.c, we see that aio_setup_iocb()
    also ends up calling compat_rw_copy_check_uvector() through
    aio_setup_vectored_rw(). Unfortunately, the access_ok() check appears to
    be missing. Same situation for
    security/keys/compat.c:compat_keyctl_instantiate_key_iov().

    I propose that we add the access_ok() check directly into
    compat_rw_copy_check_uvector(), so callers don't have to worry about it,
    and it therefore makes the compat call code similar to its non-compat
    counterpart. Place the access_ok() check in the same location where
    copy_from_user() can trigger a -EFAULT error in the non-compat code, so
    the ABI behaviors are alike on both compat and non-compat.

    While we are here, fix compat_do_readv_writev() so it checks for
    compat_rw_copy_check_uvector() negative return values.

    And also, fix a memory leak in compat_keyctl_instantiate_key_iov() error
    handling.

    Acked-by: Linus Torvalds
    Acked-by: Al Viro
    Signed-off-by: Mathieu Desnoyers
    Signed-off-by: Linus Torvalds

    Mathieu Desnoyers
     

12 Mar, 2013

1 commit

  • This fixes CVE-2013-1792.

    There is a race in install_user_keyrings() that can cause a NULL pointer
    dereference when called concurrently for the same user if the uid and
    uid-session keyrings are not yet created. It might be possible for an
    unprivileged user to trigger this by calling keyctl() from userspace in
    parallel immediately after logging in.

    Assume that we have two threads both executing lookup_user_key(), both
    looking for KEY_SPEC_USER_SESSION_KEYRING.

    THREAD A THREAD B
    =============================== ===============================
    ==>call install_user_keyrings();
    if (!cred->user->session_keyring)
    ==>call install_user_keyrings()
    ...
    user->uid_keyring = uid_keyring;
    if (user->uid_keyring)
    return 0;
    user->session_keyring [== NULL]
    user->session_keyring = session_keyring;
    atomic_inc(&key->usage); [oops]

    At the point thread A dereferences cred->user->session_keyring, thread B
    hasn't updated user->session_keyring yet, but thread A assumes it is
    populated because install_user_keyrings() returned ok.

    The race window is really small but can be exploited if, for example,
    thread B is interrupted or preempted after initializing uid_keyring, but
    before doing setting session_keyring.

    This couldn't be reproduced on a stock kernel. However, after placing
    systemtap probe on 'user->session_keyring = session_keyring;' that
    introduced some delay, the kernel could be crashed reliably.

    Fix this by checking both pointers before deciding whether to return.
    Alternatively, the test could be done away with entirely as it is checked
    inside the mutex - but since the mutex is global, that may not be the best
    way.

    Signed-off-by: David Howells
    Reported-by: Mateusz Guzik
    Cc:
    Signed-off-by: Andrew Morton
    Signed-off-by: James Morris

    David Howells
     

04 Mar, 2013

1 commit

  • Dave Jones writes:
    > Just hit this on Linus' current tree.
    >
    > [ 89.621770] BUG: unable to handle kernel NULL pointer dereference at 00000000000000c8
    > [ 89.623111] IP: [] commit_creds+0x250/0x2f0
    > [ 89.624062] PGD 122bfd067 PUD 122bfe067 PMD 0
    > [ 89.624901] Oops: 0000 [#1] PREEMPT SMP
    > [ 89.625678] Modules linked in: caif_socket caif netrom bridge hidp 8021q garp stp mrp rose llc2 af_rxrpc phonet af_key binfmt_misc bnep l2tp_ppp can_bcm l2tp_core pppoe pppox can_raw scsi_transport_iscsi ppp_generic slhc nfnetlink can ipt_ULOG ax25 decnet irda nfc rds x25 crc_ccitt appletalk atm ipx p8023 psnap p8022 llc lockd sunrpc ip6t_REJECT nf_conntrack_ipv6 nf_defrag_ipv6 xt_conntrack nf_conntrack ip6table_filter ip6_tables btusb bluetooth snd_hda_codec_realtek snd_hda_intel snd_hda_codec snd_pcm vhost_net snd_page_alloc snd_timer tun macvtap usb_debug snd rfkill microcode macvlan edac_core pcspkr serio_raw kvm_amd soundcore kvm r8169 mii
    > [ 89.637846] CPU 2
    > [ 89.638175] Pid: 782, comm: trinity-main Not tainted 3.8.0+ #63 Gigabyte Technology Co., Ltd. GA-MA78GM-S2H/GA-MA78GM-S2H
    > [ 89.639850] RIP: 0010:[] [] commit_creds+0x250/0x2f0
    > [ 89.641161] RSP: 0018:ffff880115657eb8 EFLAGS: 00010207
    > [ 89.641984] RAX: 00000000000003e8 RBX: ffff88012688b000 RCX: 0000000000000000
    > [ 89.643069] RDX: 0000000000000000 RSI: ffffffff81c32960 RDI: ffff880105839600
    > [ 89.644167] RBP: ffff880115657ed8 R08: 0000000000000000 R09: 0000000000000000
    > [ 89.645254] R10: 0000000000000001 R11: 0000000000000246 R12: ffff880105839600
    > [ 89.646340] R13: ffff88011beea490 R14: ffff88011beea490 R15: 0000000000000000
    > [ 89.647431] FS: 00007f3ac063b740(0000) GS:ffff88012b200000(0000) knlGS:0000000000000000
    > [ 89.648660] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b
    > [ 89.649548] CR2: 00000000000000c8 CR3: 0000000122bfc000 CR4: 00000000000007e0
    > [ 89.650635] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
    > [ 89.651723] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
    > [ 89.652812] Process trinity-main (pid: 782, threadinfo ffff880115656000, task ffff88011beea490)
    > [ 89.654128] Stack:
    > [ 89.654433] 0000000000000000 ffff8801058396a0 ffff880105839600 ffff88011beeaa78
    > [ 89.655769] ffff880115657ef8 ffffffff812c7d9b ffffffff82079be0 0000000000000000
    > [ 89.657073] ffff880115657f28 ffffffff8106c665 0000000000000002 ffff880115657f58
    > [ 89.658399] Call Trace:
    > [ 89.658822] [] key_change_session_keyring+0xfb/0x140
    > [ 89.659845] [] task_work_run+0xa5/0xd0
    > [ 89.660698] [] do_notify_resume+0x71/0xb0
    > [ 89.661581] [] int_signal+0x12/0x17
    > [ 89.662385] Code: 24 90 00 00 00 48 8b b3 90 00 00 00 49 8b 4c 24 40 48 39 f2 75 08 e9 83 00 00 00 48 89 ca 48 81 fa 60 29 c3 81 0f 84 41 fe ff ff 8b 8a c8 00 00 00 48 39 ce 75 e4 3b 82 d0 00 00 00 0f 84 4b
    > [ 89.667778] RIP [] commit_creds+0x250/0x2f0
    > [ 89.668733] RSP
    > [ 89.669301] CR2: 00000000000000c8
    >
    > My fastest trinity induced oops yet!
    >
    >
    > Appears to be..
    >
    > if ((set_ns == subset_ns->parent) &&
    > 850: 48 8b 8a c8 00 00 00 mov 0xc8(%rdx),%rcx
    >
    > from the inlined cred_cap_issubset

    By historical accident we have been reading trying to set new->user_ns
    from new->user_ns. Which is totally silly as new->user_ns is NULL (as
    is every other field in new except session_keyring at that point).

    The intent is clearly to copy all of the fields from old to new so copy
    old->user_ns into into new->user_ns.

    Cc: stable@vger.kernel.org
    Reported-by: Dave Jones
    Tested-by: Dave Jones
    Acked-by: Serge Hallyn
    Signed-off-by: "Eric W. Biederman"

    Eric W. Biederman
     

21 Feb, 2013

1 commit

  • A patch to fix some unreachable code in search_my_process_keyrings() got
    applied twice by two different routes upstream as commits e67eab39bee2
    and b010520ab3d2 (both "fix unreachable code").

    Unfortunately, the second application removed something it shouldn't
    have and this wasn't detected by GIT. This is due to the patch not
    having sufficient lines of context to distinguish the two places of
    application.

    The effect of this is relatively minor: inside the kernel, the keyring
    search routines may search multiple keyrings and then prioritise the
    errors if no keys or negative keys are found in any of them. With the
    extra deletion, the presence of a negative key in the thread keyring
    (causing ENOKEY) is incorrectly overridden by an error searching the
    process keyring.

    So revert the second application of the patch.

    Signed-off-by: David Howells
    Cc: Jiri Kosina
    Cc: Andrew Morton
    Cc: stable@vger.kernel.org
    Signed-off-by: Linus Torvalds

    David Howells
     

21 Dec, 2012

1 commit


17 Dec, 2012

1 commit

  • Pull security subsystem updates from James Morris:
    "A quiet cycle for the security subsystem with just a few maintenance
    updates."

    * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security:
    Smack: create a sysfs mount point for smackfs
    Smack: use select not depends in Kconfig
    Yama: remove locking from delete path
    Yama: add RCU to drop read locking
    drivers/char/tpm: remove tasklet and cleanup
    KEYS: Use keyring_alloc() to create special keyrings
    KEYS: Reduce initial permissions on keys
    KEYS: Make the session and process keyrings per-thread
    seccomp: Make syscall skipping and nr changes more consistent
    key: Fix resource leak
    keys: Fix unreachable code
    KEYS: Add payload preparsing opportunity prior to key instantiate or update

    Linus Torvalds
     

29 Oct, 2012

1 commit


26 Oct, 2012

1 commit