1. 18 10月, 2017 6 次提交
    • E
      KEYS: load key flags and expiry time atomically in proc_keys_show() · ab5c69f0
      Eric Biggers 提交于
      In proc_keys_show(), the key semaphore is not held, so the key ->flags
      and ->expiry can be changed concurrently.  We therefore should read them
      atomically just once.
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      ab5c69f0
    • E
      KEYS: Load key expiry time atomically in keyring_search_iterator() · 9d6c8711
      Eric Biggers 提交于
      Similar to the case for key_validate(), we should load the key ->expiry
      once atomically in keyring_search_iterator(), since it can be changed
      concurrently with the flags whenever the key semaphore isn't held.
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      9d6c8711
    • E
      KEYS: load key flags and expiry time atomically in key_validate() · 1823d475
      Eric Biggers 提交于
      In key_validate(), load the flags and expiry time once atomically, since
      these can change concurrently if key_validate() is called without the
      key semaphore held.  And we don't want to get inconsistent results if a
      variable is referenced multiple times.  For example, key->expiry was
      referenced in both 'if (key->expiry)' and in 'if (now.tv_sec >=
      key->expiry)', making it theoretically possible to see a spurious
      EKEYEXPIRED while the expiration time was being removed, i.e. set to 0.
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      1823d475
    • D
      KEYS: don't let add_key() update an uninstantiated key · 60ff5b2f
      David Howells 提交于
      Currently, when passed a key that already exists, add_key() will call the
      key's ->update() method if such exists.  But this is heavily broken in the
      case where the key is uninstantiated because it doesn't call
      __key_instantiate_and_link().  Consequently, it doesn't do most of the
      things that are supposed to happen when the key is instantiated, such as
      setting the instantiation state, clearing KEY_FLAG_USER_CONSTRUCT and
      awakening tasks waiting on it, and incrementing key->user->nikeys.
      
      It also never takes key_construction_mutex, which means that
      ->instantiate() can run concurrently with ->update() on the same key.  In
      the case of the "user" and "logon" key types this causes a memory leak, at
      best.  Maybe even worse, the ->update() methods of the "encrypted" and
      "trusted" key types actually just dereference a NULL pointer when passed an
      uninstantiated key.
      
      Change key_create_or_update() to wait interruptibly for the key to finish
      construction before continuing.
      
      This patch only affects *uninstantiated* keys.  For now we still allow a
      negatively instantiated key to be updated (thereby positively
      instantiating it), although that's broken too (the next patch fixes it)
      and I'm not sure that anyone actually uses that functionality either.
      
      Here is a simple reproducer for the bug using the "encrypted" key type
      (requires CONFIG_ENCRYPTED_KEYS=y), though as noted above the bug
      pertained to more than just the "encrypted" key type:
      
          #include <stdlib.h>
          #include <unistd.h>
          #include <keyutils.h>
      
          int main(void)
          {
              int ringid = keyctl_join_session_keyring(NULL);
      
              if (fork()) {
                  for (;;) {
                      const char payload[] = "update user:foo 32";
      
                      usleep(rand() % 10000);
                      add_key("encrypted", "desc", payload, sizeof(payload), ringid);
                      keyctl_clear(ringid);
                  }
              } else {
                  for (;;)
                      request_key("encrypted", "desc", "callout_info", ringid);
              }
          }
      
      It causes:
      
          BUG: unable to handle kernel NULL pointer dereference at 0000000000000018
          IP: encrypted_update+0xb0/0x170
          PGD 7a178067 P4D 7a178067 PUD 77269067 PMD 0
          PREEMPT SMP
          CPU: 0 PID: 340 Comm: reproduce Tainted: G      D         4.14.0-rc1-00025-g428490e3 #796
          Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
          task: ffff8a467a39a340 task.stack: ffffb15c40770000
          RIP: 0010:encrypted_update+0xb0/0x170
          RSP: 0018:ffffb15c40773de8 EFLAGS: 00010246
          RAX: 0000000000000000 RBX: ffff8a467a275b00 RCX: 0000000000000000
          RDX: 0000000000000005 RSI: ffff8a467a275b14 RDI: ffffffffb742f303
          RBP: ffffb15c40773e20 R08: 0000000000000000 R09: ffff8a467a275b17
          R10: 0000000000000020 R11: 0000000000000000 R12: 0000000000000000
          R13: 0000000000000000 R14: ffff8a4677057180 R15: ffff8a467a275b0f
          FS:  00007f5d7fb08700(0000) GS:ffff8a467f200000(0000) knlGS:0000000000000000
          CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
          CR2: 0000000000000018 CR3: 0000000077262005 CR4: 00000000001606f0
          Call Trace:
           key_create_or_update+0x2bc/0x460
           SyS_add_key+0x10c/0x1d0
           entry_SYSCALL_64_fastpath+0x1f/0xbe
          RIP: 0033:0x7f5d7f211259
          RSP: 002b:00007ffed03904c8 EFLAGS: 00000246 ORIG_RAX: 00000000000000f8
          RAX: ffffffffffffffda RBX: 000000003b2a7955 RCX: 00007f5d7f211259
          RDX: 00000000004009e4 RSI: 00000000004009ff RDI: 0000000000400a04
          RBP: 0000000068db8bad R08: 000000003b2a7955 R09: 0000000000000004
          R10: 000000000000001a R11: 0000000000000246 R12: 0000000000400868
          R13: 00007ffed03905d0 R14: 0000000000000000 R15: 0000000000000000
          Code: 77 28 e8 64 34 1f 00 45 31 c0 31 c9 48 8d 55 c8 48 89 df 48 8d 75 d0 e8 ff f9 ff ff 85 c0 41 89 c4 0f 88 84 00 00 00 4c 8b 7d c8 <49> 8b 75 18 4c 89 ff e8 24 f8 ff ff 85 c0 41 89 c4 78 6d 49 8b
          RIP: encrypted_update+0xb0/0x170 RSP: ffffb15c40773de8
          CR2: 0000000000000018
      
      Cc: <stable@vger.kernel.org> # v2.6.12+
      Reported-by: NEric Biggers <ebiggers@google.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      cc: Eric Biggers <ebiggers@google.com>
      60ff5b2f
    • D
      KEYS: Fix race between updating and finding a negative key · 363b02da
      David Howells 提交于
      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: 146aa8b1 ("KEYS: Merge the type-specific data with the payload data")
      Cc: stable@vger.kernel.org # v4.4+
      Reported-by: NEric Biggers <ebiggers@google.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      Reviewed-by: NEric Biggers <ebiggers@google.com>
      363b02da
    • A
      security/keys: BIG_KEY requires CONFIG_CRYPTO · 3cd18d19
      Arnd Bergmann 提交于
      The recent rework introduced a possible randconfig build failure
      when CONFIG_CRYPTO configured to only allow modules:
      
      security/keys/big_key.o: In function `big_key_crypt':
      big_key.c:(.text+0x29f): undefined reference to `crypto_aead_setkey'
      security/keys/big_key.o: In function `big_key_init':
      big_key.c:(.init.text+0x1a): undefined reference to `crypto_alloc_aead'
      big_key.c:(.init.text+0x45): undefined reference to `crypto_aead_setauthsize'
      big_key.c:(.init.text+0x77): undefined reference to `crypto_destroy_tfm'
      crypto/gcm.o: In function `gcm_hash_crypt_remain_continue':
      gcm.c:(.text+0x167): undefined reference to `crypto_ahash_finup'
      crypto/gcm.o: In function `crypto_gcm_exit_tfm':
      gcm.c:(.text+0x847): undefined reference to `crypto_destroy_tfm'
      
      When we 'select CRYPTO' like the other users, we always get a
      configuration that builds.
      
      Fixes: 428490e3 ("security/keys: rewrite all of big_key crypto")
      Signed-off-by: NArnd Bergmann <arnd@arndb.de>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      3cd18d19
  2. 12 10月, 2017 1 次提交
    • E
      KEYS: encrypted: fix dereference of NULL user_key_payload · 13923d08
      Eric Biggers 提交于
      A key of type "encrypted" references a "master key" which is used to
      encrypt and decrypt the encrypted key's payload.  However, when we
      accessed the master key's payload, we failed to handle the case where
      the master key has been revoked, which sets the payload pointer to NULL.
      Note that request_key() *does* skip revoked keys, but there is still a
      window where the key can be revoked before we acquire its semaphore.
      
      Fix it by checking for a NULL payload, treating it like a key which was
      already revoked at the time it was requested.
      
      This was an issue for master keys of type "user" only.  Master keys can
      also be of type "trusted", but those cannot be revoked.
      
      Fixes: 7e70cb49 ("keys: add new key-type encrypted")
      Reviewed-by: NJames Morris <james.l.morris@oracle.com>
      Cc: <stable@vger.kernel.org>    [v2.6.38+]
      Cc: Mimi Zohar <zohar@linux.vnet.ibm.com>
      Cc: David Safford <safford@us.ibm.com>
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      13923d08
  3. 26 9月, 2017 2 次提交
    • J
      security/keys: rewrite all of big_key crypto · 428490e3
      Jason A. Donenfeld 提交于
      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: NJason A. Donenfeld <Jason@zx2c4.com>
      Reviewed-by: NEric Biggers <ebiggers3@gmail.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      Cc: Herbert Xu <herbert@gondor.apana.org.au>
      Cc: Kirill Marinushkin <k.marinushkin@gmail.com>
      Cc: security@kernel.org
      Cc: stable@vger.kernel.org
      428490e3
    • J
      security/keys: properly zero out sensitive key material in big_key · 91080180
      Jason A. Donenfeld 提交于
      Error paths forgot to zero out sensitive material, so this patch changes
      some kfrees into a kzfrees.
      Signed-off-by: NJason A. Donenfeld <Jason@zx2c4.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      Reviewed-by: NEric Biggers <ebiggers3@gmail.com>
      Cc: Herbert Xu <herbert@gondor.apana.org.au>
      Cc: Kirill Marinushkin <k.marinushkin@gmail.com>
      Cc: security@kernel.org
      Cc: stable@vger.kernel.org
      91080180
  4. 25 9月, 2017 10 次提交
    • E
      KEYS: use kmemdup() in request_key_auth_new() · e007ce9c
      Eric Biggers 提交于
      kmemdup() is preferred to kmalloc() followed by memcpy().
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      e007ce9c
    • E
      KEYS: restrict /proc/keys by credentials at open time · 4aa68e07
      Eric Biggers 提交于
      When checking for permission to view keys whilst reading from
      /proc/keys, we should use the credentials with which the /proc/keys file
      was opened.  This is because, in a classic type of exploit, it can be
      possible to bypass checks for the *current* credentials by passing the
      file descriptor to a suid program.
      
      Following commit 34dbbcdb ("Make file credentials available to the
      seqfile interfaces") we can finally fix it.  So let's do it.
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      4aa68e07
    • E
      KEYS: reset parent each time before searching key_user_tree · 8f674565
      Eric Biggers 提交于
      In key_user_lookup(), if there is no key_user for the given uid, we drop
      key_user_lock, allocate a new key_user, and search the tree again.  But
      we failed to set 'parent' to NULL at the beginning of the second search.
      If the tree were to be empty for the second search, the insertion would
      be done with an invalid 'parent', scribbling over freed memory.
      
      Fortunately this can't actually happen currently because the tree always
      contains at least the root_key_user.  But it still should be fixed to
      make the code more robust.
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      8f674565
    • E
      KEYS: prevent KEYCTL_READ on negative key · 37863c43
      Eric Biggers 提交于
      Because keyctl_read_key() looks up the key with no permissions
      requested, it may find a negatively instantiated key.  If the key is
      also possessed, we went ahead and called ->read() on the key.  But the
      key payload will actually contain the ->reject_error rather than the
      normal payload.  Thus, the kernel oopses trying to read the
      user_key_payload from memory address (int)-ENOKEY = 0x00000000ffffff82.
      
      Fortunately the payload data is stored inline, so it shouldn't be
      possible to abuse this as an arbitrary memory read primitive...
      
      Reproducer:
          keyctl new_session
          keyctl request2 user desc '' @s
          keyctl read $(keyctl show | awk '/user: desc/ {print $1}')
      
      It causes a crash like the following:
           BUG: unable to handle kernel paging request at 00000000ffffff92
           IP: user_read+0x33/0xa0
           PGD 36a54067 P4D 36a54067 PUD 0
           Oops: 0000 [#1] SMP
           CPU: 0 PID: 211 Comm: keyctl Not tainted 4.14.0-rc1 #337
           Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-20170228_101828-anatol 04/01/2014
           task: ffff90aa3b74c3c0 task.stack: ffff9878c0478000
           RIP: 0010:user_read+0x33/0xa0
           RSP: 0018:ffff9878c047bee8 EFLAGS: 00010246
           RAX: 0000000000000001 RBX: ffff90aa3d7da340 RCX: 0000000000000017
           RDX: 0000000000000000 RSI: 00000000ffffff82 RDI: ffff90aa3d7da340
           RBP: ffff9878c047bf00 R08: 00000024f95da94f R09: 0000000000000000
           R10: 0000000000000001 R11: 0000000000000000 R12: 0000000000000000
           R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000
           FS:  00007f58ece69740(0000) GS:ffff90aa3e200000(0000) knlGS:0000000000000000
           CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
           CR2: 00000000ffffff92 CR3: 0000000036adc001 CR4: 00000000003606f0
           Call Trace:
            keyctl_read_key+0xac/0xe0
            SyS_keyctl+0x99/0x120
            entry_SYSCALL_64_fastpath+0x1f/0xbe
           RIP: 0033:0x7f58ec787bb9
           RSP: 002b:00007ffc8d401678 EFLAGS: 00000206 ORIG_RAX: 00000000000000fa
           RAX: ffffffffffffffda RBX: 00007ffc8d402800 RCX: 00007f58ec787bb9
           RDX: 0000000000000000 RSI: 00000000174a63ac RDI: 000000000000000b
           RBP: 0000000000000004 R08: 00007ffc8d402809 R09: 0000000000000020
           R10: 0000000000000000 R11: 0000000000000206 R12: 00007ffc8d402800
           R13: 00007ffc8d4016e0 R14: 0000000000000000 R15: 0000000000000000
           Code: e5 41 55 49 89 f5 41 54 49 89 d4 53 48 89 fb e8 a4 b4 ad ff 85 c0 74 09 80 3d b9 4c 96 00 00 74 43 48 8b b3 20 01 00 00 4d 85 ed <0f> b7 5e 10 74 29 4d 85 e4 74 24 4c 39 e3 4c 89 e2 4c 89 ef 48
           RIP: user_read+0x33/0xa0 RSP: ffff9878c047bee8
           CR2: 00000000ffffff92
      
      Fixes: 61ea0c0b ("KEYS: Skip key state checks when checking for possession")
      Cc: <stable@vger.kernel.org>	[v3.13+]
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      37863c43
    • E
      KEYS: prevent creating a different user's keyrings · 237bbd29
      Eric Biggers 提交于
      It was possible for an unprivileged user to create the user and user
      session keyrings for another user.  For example:
      
          sudo -u '#3000' sh -c 'keyctl add keyring _uid.4000 "" @u
                                 keyctl add keyring _uid_ses.4000 "" @u
                                 sleep 15' &
          sleep 1
          sudo -u '#4000' keyctl describe @u
          sudo -u '#4000' keyctl describe @us
      
      This is problematic because these "fake" keyrings won't have the right
      permissions.  In particular, the user who created them first will own
      them and will have full access to them via the possessor permissions,
      which can be used to compromise the security of a user's keys:
      
          -4: alswrv-----v------------  3000     0 keyring: _uid.4000
          -5: alswrv-----v------------  3000     0 keyring: _uid_ses.4000
      
      Fix it by marking user and user session keyrings with a flag
      KEY_FLAG_UID_KEYRING.  Then, when searching for a user or user session
      keyring by name, skip all keyrings that don't have the flag set.
      
      Fixes: 69664cf1 ("keys: don't generate user and user session keyrings unless they're accessed")
      Cc: <stable@vger.kernel.org>	[v2.6.26+]
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      237bbd29
    • E
      KEYS: fix writing past end of user-supplied buffer in keyring_read() · e645016a
      Eric Biggers 提交于
      Userspace can call keyctl_read() on a keyring to get the list of IDs of
      keys in the keyring.  But if the user-supplied buffer is too small, the
      kernel would write the full list anyway --- which will corrupt whatever
      userspace memory happened to be past the end of the buffer.  Fix it by
      only filling the space that is available.
      
      Fixes: b2a4df20 ("KEYS: Expand the capacity of a keyring")
      Cc: <stable@vger.kernel.org>	[v3.13+]
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      e645016a
    • E
      KEYS: fix key refcount leak in keyctl_read_key() · 7fc0786d
      Eric Biggers 提交于
      In keyctl_read_key(), if key_permission() were to return an error code
      other than EACCES, we would leak a the reference to the key.  This can't
      actually happen currently because key_permission() can only return an
      error code other than EACCES if security_key_permission() does, only
      SELinux and Smack implement that hook, and neither can return an error
      code other than EACCES.  But it should still be fixed, as it is a bug
      waiting to happen.
      
      Fixes: 29db9190 ("[PATCH] Keys: Add LSM hooks for key management [try #3]")
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      7fc0786d
    • E
      KEYS: fix key refcount leak in keyctl_assume_authority() · 884bee02
      Eric Biggers 提交于
      In keyctl_assume_authority(), if keyctl_change_reqkey_auth() were to
      fail, we would leak the reference to the 'authkey'.  Currently this can
      only happen if prepare_creds() fails to allocate memory.  But it still
      should be fixed, as it is a more severe bug waiting to happen.
      
      This patch also moves the read of 'authkey->serial' to before the
      reference to the authkey is dropped.  Doing the read after dropping the
      reference is very fragile because it assumes we still hold another
      reference to the key.  (Which we do, in current->cred->request_key_auth,
      but there's no reason not to write it in the "obviously correct" way.)
      
      Fixes: d84f4f99 ("CRED: Inaugurate COW credentials")
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      884bee02
    • E
      KEYS: don't revoke uninstantiated key in request_key_auth_new() · f7b48cf0
      Eric Biggers 提交于
      If key_instantiate_and_link() were to fail (which fortunately isn't
      possible currently), the call to key_revoke(authkey) would crash with a
      NULL pointer dereference in request_key_auth_revoke() because the key
      has not yet been instantiated.
      
      Fix this by removing the call to key_revoke().  key_put() is sufficient,
      as it's not possible for an uninstantiated authkey to have been used for
      anything yet.
      
      Fixes: b5f545c8 ("[PATCH] keys: Permit running process to instantiate keys")
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      f7b48cf0
    • E
      KEYS: fix cred refcount leak in request_key_auth_new() · 44d81433
      Eric Biggers 提交于
      In request_key_auth_new(), if key_alloc() or key_instantiate_and_link()
      were to fail, we would leak a reference to the 'struct cred'.  Currently
      this can only happen if key_alloc() fails to allocate memory.  But it
      still should be fixed, as it is a more severe bug waiting to happen.
      
      Fix it by cleaning things up to use a helper function which frees a
      'struct request_key_auth' correctly.
      
      Fixes: d84f4f99 ("CRED: Inaugurate COW credentials")
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      44d81433
  5. 05 9月, 2017 2 次提交
  6. 14 7月, 2017 1 次提交
  7. 01 7月, 2017 1 次提交
    • K
      randstruct: Mark various structs for randomization · 3859a271
      Kees Cook 提交于
      This marks many critical kernel structures for randomization. These are
      structures that have been targeted in the past in security exploits, or
      contain functions pointers, pointers to function pointer tables, lists,
      workqueues, ref-counters, credentials, permissions, or are otherwise
      sensitive. This initial list was extracted from Brad Spengler/PaX Team's
      code in the last public patch of grsecurity/PaX based on my understanding
      of the code. Changes or omissions from the original code are mine and
      don't reflect the original grsecurity/PaX code.
      
      Left out of this list is task_struct, which requires special handling
      and will be covered in a subsequent patch.
      Signed-off-by: NKees Cook <keescook@chromium.org>
      3859a271
  8. 20 6月, 2017 1 次提交
    • I
      sched/wait: Split out the wait_bit*() APIs from <linux/wait.h> into <linux/wait_bit.h> · 5dd43ce2
      Ingo Molnar 提交于
      The wait_bit*() types and APIs are mixed into wait.h, but they
      are a pretty orthogonal extension of wait-queues.
      
      Furthermore, only about 50 kernel files use these APIs, while
      over 1000 use the regular wait-queue functionality.
      
      So clean up the main wait.h by moving the wait-bit functionality
      out of it, into a separate .h and .c file:
      
        include/linux/wait_bit.h  for types and APIs
        kernel/sched/wait_bit.c   for the implementation
      
      Update all header dependencies.
      
      This reduces the size of wait.h rather significantly, by about 30%.
      
      Cc: Linus Torvalds <torvalds@linux-foundation.org>
      Cc: Peter Zijlstra <peterz@infradead.org>
      Cc: Thomas Gleixner <tglx@linutronix.de>
      Cc: linux-kernel@vger.kernel.org
      Signed-off-by: NIngo Molnar <mingo@kernel.org>
      5dd43ce2
  9. 09 6月, 2017 16 次提交
    • M
      KEYS: fix refcount_inc() on zero · 92347cfd
      Mark Rutland 提交于
      If a key's refcount is dropped to zero between key_lookup() peeking at
      the refcount and subsequently attempting to increment it, refcount_inc()
      will see a zero refcount.  Here, refcount_inc() will WARN_ONCE(), and
      will *not* increment the refcount, which will remain zero.
      
      Once key_lookup() drops key_serial_lock, it is possible for the key to
      be freed behind our back.
      
      This patch uses refcount_inc_not_zero() to perform the peek and increment
      atomically.
      
      Fixes: fff29291 ("security, keys: convert key.usage from atomic_t to refcount_t")
      Signed-off-by: NMark Rutland <mark.rutland@arm.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      Cc: David Windsor <dwindsor@gmail.com>
      Cc: Elena Reshetova <elena.reshetova@intel.com>
      Cc: Hans Liljestrand <ishkamiel@gmail.com>
      Cc: James Morris <james.l.morris@oracle.com>
      Cc: Kees Cook <keescook@chromium.org>
      Cc: Peter Zijlstra <peterz@infradead.org>
      Signed-off-by: NJames Morris <james.l.morris@oracle.com>
      92347cfd
    • M
      KEYS: Convert KEYCTL_DH_COMPUTE to use the crypto KPP API · 7cbe0932
      Mat Martineau 提交于
      The initial Diffie-Hellman computation made direct use of the MPI
      library because the crypto module did not support DH at the time. Now
      that KPP is implemented, KEYCTL_DH_COMPUTE should use it to get rid of
      duplicate code and leverage possible hardware acceleration.
      
      This fixes an issue whereby the input to the KDF computation would
      include additional uninitialized memory when the result of the
      Diffie-Hellman computation was shorter than the input prime number.
      Signed-off-by: NMat Martineau <mathew.j.martineau@linux.intel.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      Signed-off-by: NJames Morris <james.l.morris@oracle.com>
      7cbe0932
    • E
      KEYS: DH: ensure the KDF counter is properly aligned · 0ddd9f1a
      Eric Biggers 提交于
      Accessing a 'u8[4]' through a '__be32 *' violates alignment rules.  Just
      make the counter a __be32 instead.
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      Acked-by: NStephan Mueller <smueller@chronox.de>
      Signed-off-by: NJames Morris <james.l.morris@oracle.com>
      0ddd9f1a
    • E
      KEYS: DH: don't feed uninitialized "otherinfo" into KDF · 281590b4
      Eric Biggers 提交于
      If userspace called KEYCTL_DH_COMPUTE with kdf_params containing NULL
      otherinfo but nonzero otherinfolen, the kernel would allocate a buffer
      for the otherinfo, then feed it into the KDF without initializing it.
      Fix this by always doing the copy from userspace (which will fail with
      EFAULT in this scenario).
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      Acked-by: NStephan Mueller <smueller@chronox.de>
      Signed-off-by: NJames Morris <james.l.morris@oracle.com>
      281590b4
    • E
      KEYS: DH: forbid using digest_null as the KDF hash · bbe24045
      Eric Biggers 提交于
      Requesting "digest_null" in the keyctl_kdf_params caused an infinite
      loop in kdf_ctr() because the "null" hash has a digest size of 0.  Fix
      it by rejecting hash algorithms with a digest size of 0.
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      Acked-by: NStephan Mueller <smueller@chronox.de>
      Signed-off-by: NJames Morris <james.l.morris@oracle.com>
      bbe24045
    • E
      KEYS: sanitize key structs before freeing · 0620fddb
      Eric Biggers 提交于
      While a 'struct key' itself normally does not contain sensitive
      information, Documentation/security/keys.txt actually encourages this:
      
           "Having a payload is not required; and the payload can, in fact,
           just be a value stored in the struct key itself."
      
      In case someone has taken this advice, or will take this advice in the
      future, zero the key structure before freeing it.  We might as well, and
      as a bonus this could make it a bit more difficult for an adversary to
      determine which keys have recently been in use.
      
      This is safe because the key_jar cache does not use a constructor.
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      Signed-off-by: NJames Morris <james.l.morris@oracle.com>
      0620fddb
    • E
      KEYS: trusted: sanitize all key material · ee618b46
      Eric Biggers 提交于
      As the previous patch did for encrypted-keys, zero sensitive any
      potentially sensitive data related to the "trusted" key type before it
      is freed.  Notably, we were not zeroing the tpm_buf structures in which
      the actual key is stored for TPM seal and unseal, nor were we zeroing
      the trusted_key_payload in certain error paths.
      
      Cc: Mimi Zohar <zohar@linux.vnet.ibm.com>
      Cc: David Safford <safford@us.ibm.com>
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      Signed-off-by: NJames Morris <james.l.morris@oracle.com>
      ee618b46
    • E
      KEYS: encrypted: sanitize all key material · a9dd74b2
      Eric Biggers 提交于
      For keys of type "encrypted", consistently zero sensitive key material
      before freeing it.  This was already being done for the decrypted
      payloads of encrypted keys, but not for the master key and the keys
      derived from the master key.
      
      Out of an abundance of caution and because it is trivial to do so, also
      zero buffers containing the key payload in encrypted form, although
      depending on how the encrypted-keys feature is used such information
      does not necessarily need to be kept secret.
      
      Cc: Mimi Zohar <zohar@linux.vnet.ibm.com>
      Cc: David Safford <safford@us.ibm.com>
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      Signed-off-by: NJames Morris <james.l.morris@oracle.com>
      a9dd74b2
    • E
      KEYS: user_defined: sanitize key payloads · 6966c749
      Eric Biggers 提交于
      Zero the payloads of user and logon keys before freeing them.  This
      prevents sensitive key material from being kept around in the slab
      caches after a key is released.
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      Signed-off-by: NJames Morris <james.l.morris@oracle.com>
      6966c749
    • E
      KEYS: sanitize add_key() and keyctl() key payloads · 57070c85
      Eric Biggers 提交于
      Before returning from add_key() or one of the keyctl() commands that
      takes in a key payload, zero the temporary buffer that was allocated to
      hold the key payload copied from userspace.  This may contain sensitive
      key material that should not be kept around in the slab caches.
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      Signed-off-by: NJames Morris <james.l.morris@oracle.com>
      57070c85
    • E
      KEYS: fix freeing uninitialized memory in key_update() · 63a0b050
      Eric Biggers 提交于
      key_update() freed the key_preparsed_payload even if it was not
      initialized first.  This would cause a crash if userspace called
      keyctl_update() on a key with type like "asymmetric" that has a
      ->preparse() method but not an ->update() method.  Possibly it could
      even be triggered for other key types by racing with keyctl_setperm() to
      make the KEY_NEED_WRITE check fail (the permission was already checked,
      so normally it wouldn't fail there).
      
      Reproducer with key type "asymmetric", given a valid cert.der:
      
      keyctl new_session
      keyid=$(keyctl padd asymmetric desc @s < cert.der)
      keyctl setperm $keyid 0x3f000000
      keyctl update $keyid data
      
      [  150.686666] BUG: unable to handle kernel NULL pointer dereference at 0000000000000001
      [  150.687601] IP: asymmetric_key_free_kids+0x12/0x30
      [  150.688139] PGD 38a3d067
      [  150.688141] PUD 3b3de067
      [  150.688447] PMD 0
      [  150.688745]
      [  150.689160] Oops: 0000 [#1] SMP
      [  150.689455] Modules linked in:
      [  150.689769] CPU: 1 PID: 2478 Comm: keyctl Not tainted 4.11.0-rc4-xfstests-00187-ga9f6b6b8 #742
      [  150.690916] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-20170228_101828-anatol 04/01/2014
      [  150.692199] task: ffff88003b30c480 task.stack: ffffc90000350000
      [  150.692952] RIP: 0010:asymmetric_key_free_kids+0x12/0x30
      [  150.693556] RSP: 0018:ffffc90000353e58 EFLAGS: 00010202
      [  150.694142] RAX: 0000000000000000 RBX: 0000000000000001 RCX: 0000000000000004
      [  150.694845] RDX: ffffffff81ee3920 RSI: ffff88003d4b0700 RDI: 0000000000000001
      [  150.697569] RBP: ffffc90000353e60 R08: ffff88003d5d2140 R09: 0000000000000000
      [  150.702483] R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000001
      [  150.707393] R13: 0000000000000004 R14: ffff880038a4d2d8 R15: 000000000040411f
      [  150.709720] FS:  00007fcbcee35700(0000) GS:ffff88003fd00000(0000) knlGS:0000000000000000
      [  150.711504] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
      [  150.712733] CR2: 0000000000000001 CR3: 0000000039eab000 CR4: 00000000003406e0
      [  150.714487] Call Trace:
      [  150.714975]  asymmetric_key_free_preparse+0x2f/0x40
      [  150.715907]  key_update+0xf7/0x140
      [  150.716560]  ? key_default_cmp+0x20/0x20
      [  150.717319]  keyctl_update_key+0xb0/0xe0
      [  150.718066]  SyS_keyctl+0x109/0x130
      [  150.718663]  entry_SYSCALL_64_fastpath+0x1f/0xc2
      [  150.719440] RIP: 0033:0x7fcbce75ff19
      [  150.719926] RSP: 002b:00007ffd5d167088 EFLAGS: 00000206 ORIG_RAX: 00000000000000fa
      [  150.720918] RAX: ffffffffffffffda RBX: 0000000000404d80 RCX: 00007fcbce75ff19
      [  150.721874] RDX: 00007ffd5d16785e RSI: 000000002866cd36 RDI: 0000000000000002
      [  150.722827] RBP: 0000000000000006 R08: 000000002866cd36 R09: 00007ffd5d16785e
      [  150.723781] R10: 0000000000000004 R11: 0000000000000206 R12: 0000000000404d80
      [  150.724650] R13: 00007ffd5d16784d R14: 00007ffd5d167238 R15: 000000000040411f
      [  150.725447] Code: 83 c4 08 31 c0 5b 41 5c 41 5d 41 5e 41 5f 5d c3 66 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 85 ff 74 23 55 48 89 e5 53 48 89 fb <48> 8b 3f e8 06 21 c5 ff 48 8b 7b 08 e8 fd 20 c5 ff 48 89 df e8
      [  150.727489] RIP: asymmetric_key_free_kids+0x12/0x30 RSP: ffffc90000353e58
      [  150.728117] CR2: 0000000000000001
      [  150.728430] ---[ end trace f7f8fe1da2d5ae8d ]---
      
      Fixes: 4d8c0250 ("KEYS: Call ->free_preparse() even after ->preparse() returns an error")
      Cc: stable@vger.kernel.org # 3.17+
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      Signed-off-by: NJames Morris <james.l.morris@oracle.com>
      63a0b050
    • E
      KEYS: fix dereferencing NULL payload with nonzero length · 5649645d
      Eric Biggers 提交于
      sys_add_key() and the KEYCTL_UPDATE operation of sys_keyctl() allowed a
      NULL payload with nonzero length to be passed to the key type's
      ->preparse(), ->instantiate(), and/or ->update() methods.  Various key
      types including asymmetric, cifs.idmap, cifs.spnego, and pkcs7_test did
      not handle this case, allowing an unprivileged user to trivially cause a
      NULL pointer dereference (kernel oops) if one of these key types was
      present.  Fix it by doing the copy_from_user() when 'plen' is nonzero
      rather than when '_payload' is non-NULL, causing the syscall to fail
      with EFAULT as expected when an invalid buffer is specified.
      
      Cc: stable@vger.kernel.org # 2.6.10+
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      Signed-off-by: NJames Morris <james.l.morris@oracle.com>
      5649645d
    • E
      KEYS: encrypted: use constant-time HMAC comparison · 0f534e4a
      Eric Biggers 提交于
      MACs should, in general, be compared using crypto_memneq() to prevent
      timing attacks.
      
      Cc: Mimi Zohar <zohar@linux.vnet.ibm.com>
      Cc: Herbert Xu <herbert@gondor.apana.org.au>
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      Signed-off-by: NJames Morris <james.l.morris@oracle.com>
      0f534e4a
    • E
      KEYS: encrypted: fix race causing incorrect HMAC calculations · 64d107d3
      Eric Biggers 提交于
      The encrypted-keys module was using a single global HMAC transform,
      which could be rekeyed by multiple threads concurrently operating on
      different keys, causing incorrect HMAC values to be calculated.  Fix
      this by allocating a new HMAC transform whenever we need to calculate a
      HMAC.  Also simplify things a bit by allocating the shash_desc's using
      SHASH_DESC_ON_STACK() for both the HMAC and unkeyed hashes.
      
      The following script reproduces the bug:
      
          keyctl new_session
          keyctl add user master "abcdefghijklmnop" @s
          for i in $(seq 2); do
              (
                  set -e
                  for j in $(seq 1000); do
                      keyid=$(keyctl add encrypted desc$i "new user:master 25" @s)
                      datablob="$(keyctl pipe $keyid)"
                      keyctl unlink $keyid > /dev/null
                      keyid=$(keyctl add encrypted desc$i "load $datablob" @s)
                      keyctl unlink $keyid > /dev/null
                  done
              ) &
          done
      
      Output with bug:
      
          [  439.691094] encrypted_key: bad hmac (-22)
          add_key: Invalid argument
          add_key: Invalid argument
      
      Cc: Mimi Zohar <zohar@linux.vnet.ibm.com>
      Cc: Herbert Xu <herbert@gondor.apana.org.au>
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      Signed-off-by: NJames Morris <james.l.morris@oracle.com>
      64d107d3
    • E
      KEYS: encrypted: fix buffer overread in valid_master_desc() · 794b4bc2
      Eric Biggers 提交于
      With the 'encrypted' key type it was possible for userspace to provide a
      data blob ending with a master key description shorter than expected,
      e.g. 'keyctl add encrypted desc "new x" @s'.  When validating such a
      master key description, validate_master_desc() could read beyond the end
      of the buffer.  Fix this by using strncmp() instead of memcmp().  [Also
      clean up the code to deduplicate some logic.]
      
      Cc: Mimi Zohar <zohar@linux.vnet.ibm.com>
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      Signed-off-by: NJames Morris <james.l.morris@oracle.com>
      794b4bc2
    • E
      KEYS: encrypted: avoid encrypting/decrypting stack buffers · e9ff56ac
      Eric Biggers 提交于
      Since v4.9, the crypto API cannot (normally) be used to encrypt/decrypt
      stack buffers because the stack may be virtually mapped.  Fix this for
      the padding buffers in encrypted-keys by using ZERO_PAGE for the
      encryption padding and by allocating a temporary heap buffer for the
      decryption padding.
      
      Tested with CONFIG_DEBUG_SG=y:
      	keyctl new_session
      	keyctl add user master "abcdefghijklmnop" @s
      	keyid=$(keyctl add encrypted desc "new user:master 25" @s)
      	datablob="$(keyctl pipe $keyid)"
      	keyctl unlink $keyid
      	keyid=$(keyctl add encrypted desc "load $datablob" @s)
      	datablob2="$(keyctl pipe $keyid)"
      	[ "$datablob" = "$datablob2" ] && echo "Success!"
      
      Cc: Andy Lutomirski <luto@kernel.org>
      Cc: Herbert Xu <herbert@gondor.apana.org.au>
      Cc: Mimi Zohar <zohar@linux.vnet.ibm.com>
      Cc: stable@vger.kernel.org # 4.9+
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      Signed-off-by: NJames Morris <james.l.morris@oracle.com>
      e9ff56ac