1. 04 Apr, 2017 1 commit
  2. 11 Aug, 2015 1 commit
  3. 14 Mar, 2014 1 commit
  4. 10 Mar, 2014 1 commit
  5. 02 Dec, 2013 3 commits
    • David Howells's avatar
      KEYS: Fix searching of nested keyrings · 9c5e45df
      David Howells authored
      
      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<=16; i++)); do keyctl newring ring$i $r; done
      	for ((i=0; i<=16; i++)); do keyctl add user a$i a %:ring$i; done
      	for ((i=0; i<=16; i++)); do keyctl search $r user a$i; done
      	for ((i=17; i<=20; i++)); do keyctl search $r user a$i; done
      
      The searches should all complete successfully (or with an error for 17-20),
      but instead one or more of them will hang.
      Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
      Tested-by: default avatarStephen Gallagher <sgallagh@redhat.com>
      9c5e45df
    • David Howells's avatar
      KEYS: Fix multiple key add into associative array · 23fd78d7
      David Howells authored
      
      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; i<=16; i++)); do keyctl newring ring$i $r; done
      
      This should work fine, but oopses when the 17th keyring is added.
      
      Since ops->diff_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: [<ffffffff81191ee4>] hash_key_type_and_desc+0x18/0xb0
      ...
      RIP: 0010:[<ffffffff81191ee4>] hash_key_type_and_desc+0x18/0xb0
      ...
      Call Trace:
       [<ffffffff81191f9d>] keyring_diff_objects+0x21/0xd2
       [<ffffffff811f09ef>] assoc_array_insert+0x3b6/0x908
       [<ffffffff811929a7>] __key_link_begin+0x78/0xe5
       [<ffffffff81191a2e>] key_create_or_update+0x17d/0x36a
       [<ffffffff81192e0a>] SyS_add_key+0x123/0x183
       [<ffffffff81400ddb>] tracesys+0xdd/0xe2
      Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
      Tested-by: default avatarStephen Gallagher <sgallagh@redhat.com>
      23fd78d7
    • David Howells's avatar
      KEYS: Fix the keyring hash function · d54e58b7
      David Howells authored
      
      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<=16; i++)); do keyctl newring ring$i $r; done
      	for ((i=0; i<=16; i++)); do keyctl add user a$i a %:ring$i; done
      	for ((i=0; i<=16; i++)); do keyctl search $r user a$i; done
      
      This creates a sandbox keyring, then creates 17 keyrings therein (labelled
      ring0..ring16).  This causes the root node of the sandbox's associative array
      to overflow and for the tree to have extra nodes inserted.
      
      Each keyring then is given a user key (labelled aN for ringN) for us to search
      for.
      
      We then search for the user keys we added, starting from the sandbox.  If
      working correctly, it should return the same ordered list of key IDs as
      for...keyctl add... did.  Without this patch, it reports ENOKEY "Required key
      not available" for some of the keys.  Just which keys get this depends as the
      kernel pointer to the key type forms part of the hash function.
      Reported-by: default avatarNalin Dahyabhai <nalin@redhat.com>
      Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
      Tested-by: default avatarStephen Gallagher <sgallagh@redhat.com>
      d54e58b7
  6. 14 Nov, 2013 1 commit
    • David Howells's avatar
      KEYS: Fix keyring content gc scanner · 62fe3182
      David Howells authored
      
      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: default avatarDavid Howells <dhowells@redhat.com>
      Acked-by: default avatarSimo Sorce <simo@redhat.com>
      62fe3182
  7. 30 Oct, 2013 2 commits
    • David Howells's avatar
      KEYS: Fix keyring quota misaccounting on key replacement and unlink · 034faeb9
      David Howells authored
      
      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: default avatarStephen Gallagher <sgallagh@redhat.com>
      Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
      034faeb9
    • David Howells's avatar
      KEYS: Fix a race between negating a key and reading the error set · 74792b00
      David Howells authored
      
      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 <dwysocha@redhat.com> and Scott Mayhew
      <smayhew@redhat.com> for tracking this down.
      
      This may be the cause of:
      
      BUG: unable to handle kernel NULL pointer dereference at 0000000000000070
      IP: [<ffffffff81219011>] 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:[<ffffffff81219011>] 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
      <d> 0000000000000000 ffff880a000000d0 ffff880c6ab337a8 000000000000000f
      <d> ffffffffa03afb93 000000000000000f ffff88186c7882c0 0000000000000014
      Call Trace:
       [<ffffffff81219695>] request_key+0x65/0xa0
       [<ffffffffa03a0885>] nfs_idmap_request_key+0xc5/0x170 [nfs]
       [<ffffffffa03a0eb4>] nfs_idmap_lookup_id+0x34/0x80 [nfs]
       [<ffffffffa03a1255>] nfs_map_group_to_gid+0x75/0xa0 [nfs]
       [<ffffffffa039a9ad>] decode_getfattr_attrs+0xbdd/0xfb0 [nfs]
       [<ffffffff81057310>] ? __dequeue_entity+0x30/0x50
       [<ffffffff8100988e>] ? __switch_to+0x26e/0x320
       [<ffffffffa039ae03>] decode_getfattr+0x83/0xe0 [nfs]
       [<ffffffffa039b610>] ? nfs4_xdr_dec_getattr+0x0/0xa0 [nfs]
       [<ffffffffa039b69f>] nfs4_xdr_dec_getattr+0x8f/0xa0 [nfs]
       [<ffffffffa02dada4>] rpcauth_unwrap_resp+0x84/0xb0 [sunrpc]
       [<ffffffffa039b610>] ? nfs4_xdr_dec_getattr+0x0/0xa0 [nfs]
       [<ffffffffa02cf923>] call_decode+0x1b3/0x800 [sunrpc]
       [<ffffffff81096de0>] ? wake_bit_function+0x0/0x50
       [<ffffffffa02cf770>] ? call_decode+0x0/0x800 [sunrpc]
       [<ffffffffa02d99a7>] __rpc_execute+0x77/0x350 [sunrpc]
       [<ffffffff81096c67>] ? bit_waitqueue+0x17/0xd0
       [<ffffffffa02d9ce1>] rpc_execute+0x61/0xa0 [sunrpc]
       [<ffffffffa02d03a5>] rpc_run_task+0x75/0x90 [sunrpc]
       [<ffffffffa02d04c2>] rpc_call_sync+0x42/0x70 [sunrpc]
       [<ffffffffa038ff80>] _nfs4_call_sync+0x30/0x40 [nfs]
       [<ffffffffa038836c>] _nfs4_proc_getattr+0xac/0xc0 [nfs]
       [<ffffffff810aac87>] ? futex_wait+0x227/0x380
       [<ffffffffa038b856>] nfs4_proc_getattr+0x56/0x80 [nfs]
       [<ffffffffa0371403>] __nfs_revalidate_inode+0xe3/0x220 [nfs]
       [<ffffffffa037158e>] nfs_revalidate_mapping+0x4e/0x170 [nfs]
       [<ffffffffa036f147>] nfs_file_read+0x77/0x130 [nfs]
       [<ffffffff811811aa>] do_sync_read+0xfa/0x140
       [<ffffffff81096da0>] ? autoremove_wake_function+0x0/0x40
       [<ffffffff8100bb8e>] ? apic_timer_interrupt+0xe/0x20
       [<ffffffff8100b9ce>] ? common_interrupt+0xe/0x13
       [<ffffffff81228ffb>] ? selinux_file_permission+0xfb/0x150
       [<ffffffff8121bed6>] ? security_file_permission+0x16/0x20
       [<ffffffff81181a95>] vfs_read+0xb5/0x1a0
       [<ffffffff81181bd1>] sys_read+0x51/0x90
       [<ffffffff810dc685>] ? __audit_syscall_exit+0x265/0x290
       [<ffffffff8100b072>] system_call_fastpath+0x16/0x1b
      Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
      cc: Dave Wysochanski <dwysocha@redhat.com>
      cc: Scott Mayhew <smayhew@redhat.com>
      74792b00
  8. 25 Sep, 2013 1 commit
  9. 24 Sep, 2013 6 commits
    • David Howells's avatar
      KEYS: Expand the capacity of a keyring · b2a4df20
      David Howells authored
      
      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: default avatarDavid Howells <dhowells@redhat.com>
      b2a4df20
    • David Howells's avatar
      KEYS: Drop the permissions argument from __keyring_search_one() · e57e8669
      David Howells authored
      
      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: default avatarDavid Howells <dhowells@redhat.com>
      e57e8669
    • David Howells's avatar
      KEYS: Define a __key_get() wrapper to use rather than atomic_inc() · ccc3e6d9
      David Howells authored
      
      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: default avatarDavid Howells <dhowells@redhat.com>
      ccc3e6d9
    • David Howells's avatar
      KEYS: Introduce a search context structure · 4bdf0bc3
      David Howells authored
      
      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: default avatarDavid Howells <dhowells@redhat.com>
      4bdf0bc3
    • David Howells's avatar
      KEYS: Consolidate the concept of an 'index key' for key access · 16feef43
      David Howells authored
      
      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: default avatarDavid Howells <dhowells@redhat.com>
      16feef43
    • David Howells's avatar
      KEYS: Use bool in make_key_ref() and is_key_possessed() · a5b4bd28
      David Howells authored
      
      Make make_key_ref() take a bool possession parameter and make
      is_key_possessed() return a bool.
      Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
      a5b4bd28
  10. 08 Oct, 2012 1 commit
    • David Howells's avatar
      KEYS: Add payload preparsing opportunity prior to key instantiate or update · cf7f601c
      David Howells authored
      
      Give the key type the opportunity to preparse the payload prior to the
      instantiation and update routines being called.  This is done with the
      provision of two new key type operations:
      
      	int (*preparse)(struct key_preparsed_payload *prep);
      	void (*free_preparse)(struct key_preparsed_payload *prep);
      
      If the first operation is present, then it is called before key creation (in
      the add/update case) or before the key semaphore is taken (in the update and
      instantiate cases).  The second operation is called to clean up if the first
      was called.
      
      preparse() is given the opportunity to fill in the following structure:
      
      	struct key_preparsed_payload {
      		char		*description;
      		void		*type_data[2];
      		void		*payload;
      		const void	*data;
      		size_t		datalen;
      		size_t		quotalen;
      	};
      
      Before the preparser is called, the first three fields will have been cleared,
      the payload pointer and size will be stored in data and datalen and the default
      quota size from the key_type struct will be stored into quotalen.
      
      The preparser may parse the payload in any way it likes and may store data in
      the type_data[] and payload fields for use by the instantiate() and update()
      ops.
      
      The preparser may also propose a description for the key by attaching it as a
      string to the description field.  This can be used by passing a NULL or ""
      description to the add_key() system call or the key_create_or_update()
      function.  This cannot work with request_key() as that required the description
      to tell the upcall about the key to be created.
      
      This, for example permits keys that store PGP public keys to generate their own
      name from the user ID and public key fingerprint in the key.
      
      The instantiate() and update() operations are then modified to look like this:
      
      	int (*instantiate)(struct key *key, struct key_preparsed_payload *prep);
      	int (*update)(struct key *key, struct key_preparsed_payload *prep);
      
      and the new payload data is passed in *prep, whether or not it was preparsed.
      Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
      Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
      cf7f601c
  11. 02 Oct, 2012 2 commits
    • David Howells's avatar
      KEYS: Use keyring_alloc() to create special keyrings · f8aa23a5
      David Howells authored
      
      Use keyring_alloc() to create special keyrings now that it has a permissions
      parameter rather than using key_alloc() + key_instantiate_and_link().
      
      Also document and export keyring_alloc() so that modules can use it too.
      Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
      f8aa23a5
    • David Howells's avatar
      KEYS: Reduce initial permissions on keys · 96b5c8fe
      David Howells authored
      
      Reduce the initial permissions on new keys to grant the possessor everything,
      view permission only to the user (so the keys can be seen in /proc/keys) and
      nothing else.
      
      This gives the creator a chance to adjust the permissions mask before other
      processes can access the new key or create a link to it.
      
      To aid with this, keyring_alloc() now takes a permission argument rather than
      setting the permissions itself.
      
      The following permissions are now set:
      
       (1) The user and user-session keyrings grant the user that owns them full
           permissions and grant a possessor everything bar SETATTR.
      
       (2) The process and thread keyrings grant the possessor full permissions but
           only grant the user VIEW.  This permits the user to see them in
           /proc/keys, but not to do anything with them.
      
       (3) Anonymous session keyrings grant the possessor full permissions, but only
           grant the user VIEW and READ.  This means that the user can see them in
           /proc/keys and can list them, but nothing else.  Possibly READ shouldn't
           be provided either.
      
       (4) Named session keyrings grant everything an anonymous session keyring does,
           plus they grant the user LINK permission.  The whole point of named
           session keyrings is that others can also subscribe to them.  Possibly this
           should be a separate permission to LINK.
      
       (5) The temporary session keyring created by call_sbin_request_key() gets the
           same permissions as an anonymous session keyring.
      
       (6) Keys created by add_key() get VIEW, SEARCH, LINK and SETATTR for the
           possessor, plus READ and/or WRITE if the key type supports them.  The used
           only gets VIEW now.
      
       (7) Keys created by request_key() now get the same as those created by
           add_key().
      Reported-by: default avatarLennart Poettering <lennart@poettering.net>
      Reported-by: default avatarStef Walter <stefw@redhat.com>
      Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
      96b5c8fe
  12. 14 Sep, 2012 1 commit
    • Eric W. Biederman's avatar
      userns: Convert security/keys to the new userns infrastructure · 9a56c2db
      Eric W. Biederman authored
      
      - Replace key_user ->user_ns equality checks with kuid_has_mapping checks.
      - Use from_kuid to generate key descriptions
      - Use kuid_t and kgid_t and the associated helpers instead of uid_t and gid_t
      - Avoid potential problems with file descriptor passing by displaying
        keys in the user namespace of the opener of key status proc files.
      
      Cc: linux-security-module@vger.kernel.org
      Cc: keyrings@linux-nfs.org
      Cc: David Howells <dhowells@redhat.com>
      Signed-off-by: default avatarEric W. Biederman <ebiederm@xmission.com>
      9a56c2db
  13. 13 Sep, 2012 1 commit
    • David Howells's avatar
      KEYS: Add payload preparsing opportunity prior to key instantiate or update · d4f65b5d
      David Howells authored
      
      Give the key type the opportunity to preparse the payload prior to the
      instantiation and update routines being called.  This is done with the
      provision of two new key type operations:
      
      	int (*preparse)(struct key_preparsed_payload *prep);
      	void (*free_preparse)(struct key_preparsed_payload *prep);
      
      If the first operation is present, then it is called before key creation (in
      the add/update case) or before the key semaphore is taken (in the update and
      instantiate cases).  The second operation is called to clean up if the first
      was called.
      
      preparse() is given the opportunity to fill in the following structure:
      
      	struct key_preparsed_payload {
      		char		*description;
      		void		*type_data[2];
      		void		*payload;
      		const void	*data;
      		size_t		datalen;
      		size_t		quotalen;
      	};
      
      Before the preparser is called, the first three fields will have been cleared,
      the payload pointer and size will be stored in data and datalen and the default
      quota size from the key_type struct will be stored into quotalen.
      
      The preparser may parse the payload in any way it likes and may store data in
      the type_data[] and payload fields for use by the instantiate() and update()
      ops.
      
      The preparser may also propose a description for the key by attaching it as a
      string to the description field.  This can be used by passing a NULL or ""
      description to the add_key() system call or the key_create_or_update()
      function.  This cannot work with request_key() as that required the description
      to tell the upcall about the key to be created.
      
      This, for example permits keys that store PGP public keys to generate their own
      name from the user ID and public key fingerprint in the key.
      
      The instantiate() and update() operations are then modified to look like this:
      
      	int (*instantiate)(struct key *key, struct key_preparsed_payload *prep);
      	int (*update)(struct key *key, struct key_preparsed_payload *prep);
      
      and the new payload data is passed in *prep, whether or not it was preparsed.
      Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
      d4f65b5d
  14. 25 May, 2012 1 commit
    • David Howells's avatar
      KEYS: Fix some sparse warnings · 423b9788
      David Howells authored
      
      Fix some sparse warnings in the keyrings code:
      
       (1) compat_keyctl_instantiate_key_iov() should be static.
      
       (2) There were a couple of places where a pointer was being compared against
           integer 0 rather than NULL.
      
       (3) keyctl_instantiate_key_common() should not take a __user-labelled iovec
           pointer as the caller must have copied the iovec to kernel space.
      
       (4) __key_link_begin() takes and __key_link_end() releases
           keyring_serialise_link_sem under some circumstances and so this should be
           declared.
      
           Note that adding __acquires() and __releases() for this doesn't help cure
           the warnings messages - something only commenting out both helps.
      Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
      Signed-off-by: default avatarJames Morris <james.l.morris@oracle.com>
      423b9788
  15. 11 May, 2012 3 commits
    • David Howells's avatar
      KEYS: Add invalidation support · fd75815f
      David Howells authored
      
      Add support for invalidating a key - which renders it immediately invisible to
      further searches and causes the garbage collector to immediately wake up,
      remove it from keyrings and then destroy it when it's no longer referenced.
      
      It's better not to do this with keyctl_revoke() as that marks the key to start
      returning -EKEYREVOKED to searches when what is actually desired is to have the
      key refetched.
      
      To invalidate a key the caller must be granted SEARCH permission by the key.
      This may be too strict.  It may be better to also permit invalidation if the
      caller has any of READ, WRITE or SETATTR permission.
      
      The primary use for this is to evict keys that are cached in special keyrings,
      such as the DNS resolver or an ID mapper.
      Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
      fd75815f
    • David Howells's avatar
      KEYS: Do LRU discard in full keyrings · 31d5a79d
      David Howells authored
      
      Do an LRU discard in keyrings that are full rather than returning ENFILE.  To
      perform this, a time_t is added to the key struct and updated by the creation
      of a link to a key and by a key being found as the result of a search.  At the
      completion of a successful search, the keyrings in the path between the root of
      the search and the first found link to it also have their last-used times
      updated.
      
      Note that discarding a link to a key from a keyring does not necessarily
      destroy the key as there may be references held by other places.
      
      An alternate discard method that might suffice is to perform FIFO discard from
      the keyring, using the spare 2-byte hole in the keylist header as the index of
      the next link to be discarded.
      
      This is useful when using a keyring as a cache for DNS results or foreign
      filesystem IDs.
      
      
      This can be tested by the following.  As root do:
      
      	echo 1000 >/proc/sys/kernel/keys/root_maxkeys
      
      	kr=`keyctl newring foo @s`
      	for ((i=0; i<2000; i++)); do keyctl add user a$i a $kr; done
      
      Without this patch ENFILE should be reported when the keyring fills up.  With
      this patch, the keyring discards keys in an LRU fashion.  Note that the stored
      LRU time has a granularity of 1s.
      
      After doing this, /proc/key-users can be observed and should show that most of
      the 2000 keys have been discarded:
      
      	[root@andromeda ~]# cat /proc/key-users
      	    0:   517 516/516 513/1000 5249/20000
      
      The "513/1000" here is the number of quota-accounted keys present for this user
      out of the maximum permitted.
      
      In /proc/keys, the keyring shows the number of keys it has and the number of
      slots it has allocated:
      
      	[root@andromeda ~]# grep foo /proc/keys
      	200c64c4 I--Q--     1 perm 3b3f0000     0     0 keyring   foo: 509/509
      
      The maximum is (PAGE_SIZE - header) / key pointer size.  That's typically 509
      on a 64-bit system and 1020 on a 32-bit system.
      Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
      31d5a79d
    • David Howells's avatar
      KEYS: Permit in-place link replacement in keyring list · 233e4735
      David Howells authored
      
      Make use of the previous patch that makes the garbage collector perform RCU
      synchronisation before destroying defunct keys.  Key pointers can now be
      replaced in-place without creating a new keyring payload and replacing the
      whole thing as the discarded keys will not be destroyed until all currently
      held RCU read locks are released.
      
      If the keyring payload space needs to be expanded or contracted, then a
      replacement will still need allocating, and the original will still have to be
      freed by RCU.
      Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
      233e4735
  16. 17 Jan, 2012 1 commit
  17. 22 Aug, 2011 1 commit
  18. 08 Jul, 2011 1 commit
  19. 17 Mar, 2011 1 commit
    • David Howells's avatar
      KEYS: Improve /proc/keys · 78b7280c
      David Howells authored
      
      Improve /proc/keys by:
      
       (1) Don't attempt to summarise the payload of a negated key.  It won't have
           one.  To this end, a helper function - key_is_instantiated() has been
           added that allows the caller to find out whether the key is positively
           instantiated (as opposed to being uninstantiated or negatively
           instantiated).
      
       (2) Do show keys that are negative, expired or revoked rather than hiding
           them.  This requires an override flag (no_state_check) to be passed to
           search_my_process_keyrings() and keyring_search_aux() to suppress this
           check.
      
           Without this, keys that are possessed by the caller, but only grant
           permissions to the caller if possessed are skipped as the possession check
           fails.
      
           Keys that are visible due to user, group or other checks are visible with
           or without this patch.
      Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
      Signed-off-by: default avatarJames Morris <jmorris@namei.org>
      78b7280c
  20. 08 Mar, 2011 1 commit
  21. 25 Jan, 2011 1 commit
    • David Howells's avatar
      KEYS: Fix __key_link_end() quota fixup on error · ceb73c12
      David Howells authored
      
      Fix __key_link_end()'s attempt to fix up the quota if an error occurs.
      
      There are two erroneous cases: Firstly, we always decrease the quota if
      the preallocated replacement keyring needs cleaning up, irrespective of
      whether or not we should (we may have replaced a pointer rather than
      adding another pointer).
      
      Secondly, we never clean up the quota if we added a pointer without the
      keyring storage being extended (we allocate multiple pointers at a time,
      even if we're not going to use them all immediately).
      
      We handle this by setting the bottom bit of the preallocation pointer in
      __key_link_begin() to indicate that the quota needs fixing up, which is
      then passed to __key_link() (which clears the whole thing) and
      __key_link_end().
      Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
      Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
      ceb73c12
  22. 21 Jan, 2011 2 commits
  23. 25 May, 2010 1 commit
  24. 06 May, 2010 2 commits
  25. 05 May, 2010 2 commits
    • David Howells's avatar
      KEYS: Use RCU dereference wrappers in keyring key type code · f0641cba
      David Howells authored
      
      The keyring key type code should use RCU dereference wrappers, even when it
      holds the keyring's key semaphore.
      Reported-by: default avatarVegard Nossum <vegard.nossum@gmail.com>
      Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
      Acked-by: default avatarSerge Hallyn <serue@us.ibm.com>
      Signed-off-by: default avatarJames Morris <jmorris@namei.org>
      f0641cba
    • Toshiyuki Okajima's avatar
      KEYS: find_keyring_by_name() can gain access to a freed keyring · cea7daa3
      Toshiyuki Okajima authored
      
      find_keyring_by_name() can gain access to a keyring that has had its reference
      count reduced to zero, and is thus ready to be freed.  This then allows the
      dead keyring to be brought back into use whilst it is being destroyed.
      
      The following timeline illustrates the process:
      
      |(cleaner)                           (user)
      |
      | free_user(user)                    sys_keyctl()
      |  |                                  |
      |  key_put(user->session_keyring)     keyctl_get_keyring_ID()
      |  ||	//=> keyring->usage = 0        |
      |  |schedule_work(&key_cleanup_task)   lookup_user_key()
      |  ||                                   |
      |  kmem_cache_free(,user)               |
      |  .                                    |[KEY_SPEC_USER_KEYRING]
      |  .                                    install_user_keyrings()
      |  .                                    ||
      | key_cleanup() [<= worker_thread()]    ||
      |  |                                    ||
      |  [spin_lock(&key_serial_lock)]        |[mutex_lock(&key_user_keyr..mutex)]
      |  |                                    ||
      |  atomic_read() == 0                   ||
      |  |{ rb_ease(&key->serial_node,) }     ||
      |  |                                    ||
      |  [spin_unlock(&key_serial_lock)]      |find_keyring_by_name()
      |  |                                    |||
      |  keyring_destroy(keyring)             ||[read_lock(&keyring_name_lock)]
      |  ||                                   |||
      |  |[write_lock(&keyring_name_lock)]    ||atomic_inc(&keyring->usage)
      |  |.                                   ||| *** GET freeing keyring ***
      |  |.                                   ||[read_unlock(&keyring_name_lock)]
      |  ||                                   ||
      |  |list_del()                          |[mutex_unlock(&key_user_k..mutex)]
      |  ||                                   |
      |  |[write_unlock(&keyring_name_lock)]  ** INVALID keyring is returned **
      |  |                                    .
      |  kmem_cache_free(,keyring)            .
      |                                       .
      |                                       atomic_dec(&keyring->usage)
      v                                         *** DESTROYED ***
      TIME
      
      If CONFIG_SLUB_DEBUG=y then we may see the following message generated:
      
      	=============================================================================
      	BUG key_jar: Poison overwritten
      	-----------------------------------------------------------------------------
      
      	INFO: 0xffff880197a7e200-0xffff880197a7e200. First byte 0x6a instead of 0x6b
      	INFO: Allocated in key_alloc+0x10b/0x35f age=25 cpu=1 pid=5086
      	INFO: Freed in key_cleanup+0xd0/0xd5 age=12 cpu=1 pid=10
      	INFO: Slab 0xffffea000592cb90 objects=16 used=2 fp=0xffff880197a7e200 flags=0x200000000000c3
      	INFO: Object 0xffff880197a7e200 @offset=512 fp=0xffff880197a7e300
      
      	Bytes b4 0xffff880197a7e1f0:  5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a ZZZZZZZZZZZZZZZZ
      	  Object 0xffff880197a7e200:  6a 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b jkkkkkkkkkkkkkkk
      
      Alternatively, we may see a system panic happen, such as:
      
      	BUG: unable to handle kernel NULL pointer dereference at 0000000000000001
      	IP: [<ffffffff810e61a3>] kmem_cache_alloc+0x5b/0xe9
      	PGD 6b2b4067 PUD 6a80d067 PMD 0
      	Oops: 0000 [#1] SMP
      	last sysfs file: /sys/kernel/kexec_crash_loaded
      	CPU 1
      	...
      	Pid: 31245, comm: su Not tainted 2.6.34-rc5-nofixed-nodebug #2 D2089/PRIMERGY
      	RIP: 0010:[<ffffffff810e61a3>]  [<ffffffff810e61a3>] kmem_cache_alloc+0x5b/0xe9
      	RSP: 0018:ffff88006af3bd98  EFLAGS: 00010002
      	RAX: 0000000000000000 RBX: 0000000000000001 RCX: ffff88007d19900b
      	RDX: 0000000100000000 RSI: 00000000000080d0 RDI: ffffffff81828430
      	RBP: ffffffff81828430 R08: ffff88000a293750 R09: 0000000000000000
      	R10: 0000000000000001 R11: 0000000000100000 R12: 00000000000080d0
      	R13: 00000000000080d0 R14: 0000000000000296 R15: ffffffff810f20ce
      	FS:  00007f97116bc700(0000) GS:ffff88000a280000(0000) knlGS:0000000000000000
      	CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
      	CR2: 0000000000000001 CR3: 000000006a91c000 CR4: 00000000000006e0
      	DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
      	DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
      	Process su (pid: 31245, threadinfo ffff88006af3a000, task ffff8800374414c0)
      	Stack:
      	 0000000512e0958e 0000000000008000 ffff880037f8d180 0000000000000001
      	 0000000000000000 0000000000008001 ffff88007d199000 ffffffff810f20ce
      	 0000000000008000 ffff88006af3be48 0000000000000024 ffffffff810face3
      	Call Trace:
      	 [<ffffffff810f20ce>] ? get_empty_filp+0x70/0x12f
      	 [<ffffffff810face3>] ? do_filp_open+0x145/0x590
      	 [<ffffffff810ce208>] ? tlb_finish_mmu+0x2a/0x33
      	 [<ffffffff810ce43c>] ? unmap_region+0xd3/0xe2
      	 [<ffffffff810e4393>] ? virt_to_head_page+0x9/0x2d
      	 [<ffffffff81103916>] ? alloc_fd+0x69/0x10e
      	 [<ffffffff810ef4ed>] ? do_sys_open+0x56/0xfc
      	 [<ffffffff81008a02>] ? system_call_fastpath+0x16/0x1b
      	Code: 0f 1f 44 00 00 49 89 c6 fa 66 0f 1f 44 00 00 65 4c 8b 04 25 60 e8 00 00 48 8b 45 00 49 01 c0 49 8b 18 48 85 db 74 0d 48 63 45 18 <48> 8b 04 03 49 89 00 eb 14 4c 89 f9 83 ca ff 44 89 e6 48 89 ef
      	RIP  [<ffffffff810e61a3>] kmem_cache_alloc+0x5b/0xe9
      
      This problem is that find_keyring_by_name does not confirm that the keyring is
      valid before accepting it.
      
      Skipping keyrings that have been reduced to a zero count seems the way to go.
      To this end, use atomic_inc_not_zero() to increment the usage count and skip
      the candidate keyring if that returns false.
      
      The following script _may_ cause the bug to happen, but there's no guarantee
      as the window of opportunity is small:
      
      	#!/bin/sh
      	LOOP=100000
      	USER=dummy_user
      	/bin/su -c "exit;" $USER || { /usr/sbin/adduser -m $USER; add=1; }
      	for ((i=0; i<LOOP; i++))
      	do
      		/bin/su -c "echo '$i' > /dev/null" $USER
      	done
      	(( add == 1 )) && /usr/sbin/userdel -r $USER
      	exit
      
      Note that the nominated user must not be in use.
      
      An alternative way of testing this may be:
      
      	for ((i=0; i<100000; i++))
      	do
      		keyctl session foo /bin/true || break
      	done >&/dev/null
      
      as that uses a keyring named "foo" rather than relying on the user and
      user-session named keyrings.
      Reported-by: default avatarToshiyuki Okajima <toshi.okajima@jp.fujitsu.com>
      Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
      Tested-by: default avatarToshiyuki Okajima <toshi.okajima@jp.fujitsu.com>
      Acked-by: default avatarSerge Hallyn <serue@us.ibm.com>
      Signed-off-by: default avatarJames Morris <jmorris@namei.org>
      cea7daa3
  26. 27 Apr, 2010 1 commit
    • David Howells's avatar
      keys: don't need to use RCU in keyring_read() as semaphore is held · b59ec78c
      David Howells authored
      
      keyring_read() doesn't need to use rcu_dereference() to access the keyring
      payload as the caller holds the key semaphore to prevent modifications
      from happening whilst the data is read out.
      
      This should solve the following warning:
      
      ===================================================
      [ INFO: suspicious rcu_dereference_check() usage. ]
      ---------------------------------------------------
      security/keys/keyring.c:204 invoked rcu_dereference_check() without protection!
      
      other info that might help us debug this:
      
      rcu_scheduler_active = 1, debug_locks = 0
      1 lock held by keyctl/2144:
       #0:  (&key->sem){+++++.}, at: [<ffffffff81177f7c>] keyctl_read_key+0x9c/0xcf
      
      stack backtrace:
      Pid: 2144, comm: keyctl Not tainted 2.6.34-rc2-cachefs #113
      Call Trace:
       [<ffffffff8105121f>] lockdep_rcu_dereference+0xaa/0xb2
       [<ffffffff811762d5>] keyring_read+0x4d/0xe7
       [<ffffffff81177f8c>] keyctl_read_key+0xac/0xcf
       [<ffffffff811788d4>] sys_keyctl+0x75/0xb9
       [<ffffffff81001eeb>] system_call_fastpath+0x16/0x1b
      Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
      Cc: Herbert Xu <herbert@gondor.apana.org.au>
      Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
      Signed-off-by: default avatarJames Morris <jmorris@namei.org>
      b59ec78c