06 Apr, 2018

1 commit

  • Currently #includes for no obvious
    reason. It looks like it's only a convenience, so remove kmemleak.h
    from slab.h and add to any users of kmemleak_* that
    don't already #include it. Also remove from source
    files that do not use it.

    This is tested on i386 allmodconfig and x86_64 allmodconfig. It would
    be good to run it through the 0day bot for other $ARCHes. I have
    neither the horsepower nor the storage space for the other $ARCHes.

    Update: This patch has been extensively build-tested by both the 0day
    bot & kisskb/ozlabs build farms. Both of them reported 2 build failures
    for which patches are included here (in v2).

    [ slab.h is the second most used header file after module.h; kernel.h is
    right there with slab.h. There could be some minor error in the
    counting due to some #includes having comments after them and I didn't
    combine all of those. ]

    [akpm@linux-foundation.org: security/keys/big_key.c needs vmalloc.h, per sfr]
    Link: http://lkml.kernel.org/r/e4309f98-3749-93e1-4bb7-d9501a39d015@infradead.org
    Link: http://kisskb.ellerman.id.au/kisskb/head/13396/
    Signed-off-by: Randy Dunlap
    Reviewed-by: Ingo Molnar
    Reported-by: Michael Ellerman [2 build failures]
    Reported-by: Fengguang Wu [2 build failures]
    Reviewed-by: Andrew Morton
    Cc: Wei Yongjun
    Cc: Luis R. Rodriguez
    Cc: Greg Kroah-Hartman
    Cc: Mimi Zohar
    Cc: John Johansen
    Cc: Stephen Rothwell
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Randy Dunlap
     

22 Feb, 2018

1 commit

  • kmalloc() can't always allocate large enough buffers for big_key to use for
    crypto (1MB + some metadata) so we cannot use that to allocate the buffer.
    Further, vmalloc'd pages can't be passed to sg_init_one() and the aead
    crypto accessors cannot be called progressively and must be passed all the
    data in one go (which means we can't pass the data in one block at a time).

    Fix this by allocating the buffer pages individually and passing them
    through a multientry scatterlist to the crypto layer. This has the bonus
    advantage that we don't have to allocate a contiguous series of pages.

    We then vmap() the page list and pass that through to the VFS read/write
    routines.

    This can trigger a warning:

    WARNING: CPU: 0 PID: 60912 at mm/page_alloc.c:3883 __alloc_pages_nodemask+0xb7c/0x15f8
    ([] __alloc_pages_nodemask+0x1ee/0x15f8)
    [] kmalloc_order+0x46/0x90
    [] kmalloc_order_trace+0x40/0x1f8
    [] __kmalloc+0x430/0x4c0
    [] big_key_preparse+0x7c/0x210
    [] key_create_or_update+0x128/0x420
    [] SyS_add_key+0x124/0x220
    [] system_call+0xc4/0x2b0

    from the keyctl/padd/useradd test of the keyutils testsuite on s390x.

    Note that it might be better to shovel data through in page-sized lumps
    instead as there's no particular need to use a monolithic buffer unless the
    kernel itself wants to access the data.

    Fixes: 13100a72f40f ("Security: Keys: Big keys stored encrypted")
    Reported-by: Paul Bunyan
    Signed-off-by: David Howells
    cc: Kirill Marinushkin

    David Howells
     

18 Oct, 2017

1 commit

  • Consolidate KEY_FLAG_INSTANTIATED, KEY_FLAG_NEGATIVE and the rejection
    error into one field such that:

    (1) The instantiation state can be modified/read atomically.

    (2) The error can be accessed atomically with the state.

    (3) The error isn't stored unioned with the payload pointers.

    This deals with the problem that the state is spread over three different
    objects (two bits and a separate variable) and reading or updating them
    atomically isn't practical, given that not only can uninstantiated keys
    change into instantiated or rejected keys, but rejected keys can also turn
    into instantiated keys - and someone accessing the key might not be using
    any locking.

    The main side effect of this problem is that what was held in the payload
    may change, depending on the state. For instance, you might observe the
    key to be in the rejected state. You then read the cached error, but if
    the key semaphore wasn't locked, the key might've become instantiated
    between the two reads - and you might now have something in hand that isn't
    actually an error code.

    The state is now KEY_IS_UNINSTANTIATED, KEY_IS_POSITIVE or a negative error
    code if the key is negatively instantiated. The key_is_instantiated()
    function is replaced with key_is_positive() to avoid confusion as negative
    keys are also 'instantiated'.

    Additionally, barriering is included:

    (1) Order payload-set before state-set during instantiation.

    (2) Order state-read before payload-read when using the key.

    Further separate barriering is necessary if RCU is being used to access the
    payload content after reading the payload pointers.

    Fixes: 146aa8b1453b ("KEYS: Merge the type-specific data with the payload data")
    Cc: stable@vger.kernel.org # v4.4+
    Reported-by: Eric Biggers
    Signed-off-by: David Howells
    Reviewed-by: Eric Biggers

    David Howells
     

26 Sep, 2017

2 commits

  • This started out as just replacing the use of crypto/rng with
    get_random_bytes_wait, so that we wouldn't use bad randomness at boot
    time. But, upon looking further, it appears that there were even deeper
    underlying cryptographic problems, and that this seems to have been
    committed with very little crypto review. So, I rewrote the whole thing,
    trying to keep to the conventions introduced by the previous author, to
    fix these cryptographic flaws.

    It makes no sense to seed crypto/rng at boot time and then keep
    using it like this, when in fact there's already get_random_bytes_wait,
    which can ensure there's enough entropy and be a much more standard way
    of generating keys. Since this sensitive material is being stored
    untrusted, using ECB and no authentication is simply not okay at all. I
    find it surprising and a bit horrifying that this code even made it past
    basic crypto review, which perhaps points to some larger issues. This
    patch moves from using AES-ECB to using AES-GCM. Since keys are uniquely
    generated each time, we can set the nonce to zero. There was also a race
    condition in which the same key would be reused at the same time in
    different threads. A mutex fixes this issue now.

    So, to summarize, this commit fixes the following vulnerabilities:

    * Low entropy key generation, allowing an attacker to potentially
    guess or predict keys.
    * Unauthenticated encryption, allowing an attacker to modify the
    cipher text in particular ways in order to manipulate the plaintext,
    which is is even more frightening considering the next point.
    * Use of ECB mode, allowing an attacker to trivially swap blocks or
    compare identical plaintext blocks.
    * Key re-use.
    * Faulty memory zeroing.

    Signed-off-by: Jason A. Donenfeld
    Reviewed-by: Eric Biggers
    Signed-off-by: David Howells
    Cc: Herbert Xu
    Cc: Kirill Marinushkin
    Cc: security@kernel.org
    Cc: stable@vger.kernel.org

    Jason A. Donenfeld
     
  • Error paths forgot to zero out sensitive material, so this patch changes
    some kfrees into a kzfrees.

    Signed-off-by: Jason A. Donenfeld
    Signed-off-by: David Howells
    Reviewed-by: Eric Biggers
    Cc: Herbert Xu
    Cc: Kirill Marinushkin
    Cc: security@kernel.org
    Cc: stable@vger.kernel.org

    Jason A. Donenfeld
     

05 Sep, 2017

2 commits

  • Make the position an in/out argument like all the other read/write
    helpers and and make the buf argument a void pointer.

    Signed-off-by: Christoph Hellwig
    Signed-off-by: Al Viro

    Christoph Hellwig
     
  • Use proper ssize_t and size_t types for the return value and count
    argument, move the offset last and make it an in/out argument like
    all other read/write helpers, and make the buf argument a void pointer
    to get rid of lots of casts in the callers.

    Signed-off-by: Christoph Hellwig
    Signed-off-by: Al Viro

    Christoph Hellwig
     

27 Oct, 2016

1 commit

  • big_key has two separate initialisation functions, one that registers the
    key type and one that registers the crypto. If the key type fails to
    register, there's no problem if the crypto registers successfully because
    there's no way to reach the crypto except through the key type.

    However, if the key type registers successfully but the crypto does not,
    big_key_rng and big_key_blkcipher may end up set to NULL - but the code
    neither checks for this nor unregisters the big key key type.

    Furthermore, since the key type is registered before the crypto, it is
    theoretically possible for the kernel to try adding a big_key before the
    crypto is set up, leading to the same effect.

    Fix this by merging big_key_crypto_init() and big_key_init() and calling
    the resulting function late. If they're going to be encrypted, we
    shouldn't be creating big_keys before we have the facilities to do the
    encryption available. The key type registration is also moved after the
    crypto initialisation.

    The fix also includes message printing on failure.

    If the big_key type isn't correctly set up, simply doing:

    dd if=/dev/zero bs=4096 count=1 | keyctl padd big_key a @s

    ought to cause an oops.

    Fixes: 13100a72f40f5748a04017e0ab3df4cf27c809ef ('Security: Keys: Big keys stored encrypted')
    Signed-off-by: David Howells
    cc: Peter Hlavaty
    cc: Kirill Marinushkin
    cc: Artem Savkov
    cc: stable@vger.kernel.org
    Signed-off-by: James Morris

    David Howells
     

24 Jun, 2016

1 commit


13 Apr, 2016

1 commit


18 Feb, 2016

1 commit

  • The Kconfig currently controlling compilation of this code is:

    config BIG_KEYS
    bool "Large payload keys"

    ...meaning that it currently is not being built as a module by anyone.

    Lets remove the modular code that is essentially orphaned, so that
    when reading the driver there is no doubt it is builtin-only.

    Since module_init translates to device_initcall in the non-modular
    case, the init ordering remains unchanged with this commit.

    We also delete the MODULE_LICENSE tag since all that information
    is already contained at the top of the file in the comments.

    Cc: James Morris
    Cc: "Serge E. Hallyn"
    Cc: keyrings@vger.kernel.org
    Cc: linux-security-module@vger.kernel.org
    Signed-off-by: Paul Gortmaker
    Signed-off-by: David Howells

    Paul Gortmaker
     

21 Oct, 2015

1 commit

  • Merge the type-specific data with the payload data into one four-word chunk
    as it seems pointless to keep them separate.

    Use user_key_payload() for accessing the payloads of overloaded
    user-defined keys.

    Signed-off-by: David Howells
    cc: linux-cifs@vger.kernel.org
    cc: ecryptfs@vger.kernel.org
    cc: linux-ext4@vger.kernel.org
    cc: linux-f2fs-devel@lists.sourceforge.net
    cc: linux-nfs@vger.kernel.org
    cc: ceph-devel@vger.kernel.org
    cc: linux-ima-devel@lists.sourceforge.net

    David Howells
     

17 Sep, 2014

2 commits

  • 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
     

23 Jul, 2014

1 commit


02 Dec, 2013

1 commit

  • 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
     

14 Nov, 2013

1 commit

  • 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
     

30 Oct, 2013

1 commit


24 Sep, 2013

1 commit