1. 17 9月, 2014 3 次提交
  2. 28 7月, 2014 1 次提交
  3. 23 7月, 2014 7 次提交
  4. 19 7月, 2014 1 次提交
  5. 18 7月, 2014 1 次提交
    • D
      KEYS: Allow special keys (eg. DNS results) to be invalidated by CAP_SYS_ADMIN · 0c7774ab
      David Howells 提交于
      Special kernel keys, such as those used to hold DNS results for AFS, CIFS and
      NFS and those used to hold idmapper results for NFS, used to be
      'invalidateable' with key_revoke().  However, since the default permissions for
      keys were reduced:
      
      	Commit: 96b5c8fe
      	KEYS: Reduce initial permissions on keys
      
      it has become impossible to do this.
      
      Add a key flag (KEY_FLAG_ROOT_CAN_INVAL) that will permit a key to be
      invalidated by root.  This should not be used for system keyrings as the
      garbage collector will try and remove any invalidate key.  For system keyrings,
      KEY_FLAG_ROOT_CAN_CLEAR can be used instead.
      
      After this, from userspace, keyctl_invalidate() and "keyctl invalidate" can be
      used by any possessor of CAP_SYS_ADMIN (typically root) to invalidate DNS and
      idmapper keys.  Invalidated keys are immediately garbage collected and will be
      immediately rerequested if needed again.
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      Tested-by: NSteve Dickson <steved@redhat.com>
      0c7774ab
  6. 17 7月, 2014 1 次提交
  7. 15 4月, 2014 1 次提交
  8. 15 3月, 2014 1 次提交
  9. 10 3月, 2014 1 次提交
  10. 06 3月, 2014 1 次提交
  11. 06 2月, 2014 1 次提交
  12. 02 12月, 2013 5 次提交
    • E
      security: shmem: implement kernel private shmem inodes · c7277090
      Eric Paris 提交于
      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: NEric Paris <eparis@redhat.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      cc: Hugh Dickins <hughd@google.com>
      cc: linux-mm@kvack.org
      c7277090
    • D
      KEYS: Fix searching of nested keyrings · 9c5e45df
      David Howells 提交于
      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: NDavid Howells <dhowells@redhat.com>
      Tested-by: NStephen Gallagher <sgallagh@redhat.com>
      9c5e45df
    • D
      KEYS: Fix multiple key add into associative array · 23fd78d7
      David Howells 提交于
      If sufficient keys (or keyrings) are added into a keyring such that a node in
      the associative array's tree overflows (each node has a capacity N, currently
      16) and such that all N+1 keys have the same index key segment for that level
      of the tree (the level'th nibble of the index key), then assoc_array_insert()
      calls ops->diff_objects() to indicate at which bit position the two index keys
      vary.
      
      However, __key_link_begin() passes a NULL object to assoc_array_insert() with
      the intention of supplying the correct pointer later before we commit the
      change.  This means that keyring_diff_objects() is given a NULL pointer as one
      of its arguments which it does not expect.  This results in an oops like the
      attached.
      
      With the previous patch to fix the keyring hash function, this can be forced
      much more easily by creating a keyring and only adding keyrings to it.  Add any
      other sort of key and a different insertion path is taken - all 16+1 objects
      must want to cluster in the same node slot.
      
      This can be tested by:
      
      	r=`keyctl newring sandbox @s`
      	for ((i=0; 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: NDavid Howells <dhowells@redhat.com>
      Tested-by: NStephen Gallagher <sgallagh@redhat.com>
      23fd78d7
    • D
      KEYS: Fix the keyring hash function · d54e58b7
      David Howells 提交于
      The keyring hash function (used by the associative array) is supposed to clear
      the bottommost nibble of the index key (where the hash value resides) for
      keyrings and make sure it is non-zero for non-keyrings.  This is done to make
      keyrings cluster together on one branch of the tree separately to other keys.
      
      Unfortunately, the wrong mask is used, so only the bottom two bits are
      examined and cleared and not the whole bottom nibble.  This means that keys
      and keyrings can still be successfully searched for under most circumstances
      as the hash is consistent in its miscalculation, but if a keyring's
      associative array bottom node gets filled up then approx 75% of the keyrings
      will not be put into the 0 branch.
      
      The consequence of this is that a key in a keyring linked to by another
      keyring, ie.
      
      	keyring A -> keyring B -> key
      
      may not be found if the search starts at keyring A and then descends into
      keyring B because search_nested_keyrings() only searches up the 0 branch (as it
      "knows" all keyrings must be there and not elsewhere in the tree).
      
      The fix is to use the right mask.
      
      This can be tested with:
      
      	r=`keyctl newring sandbox @s`
      	for ((i=0; i<=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: NNalin Dahyabhai <nalin@redhat.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      Tested-by: NStephen Gallagher <sgallagh@redhat.com>
      d54e58b7
    • D
      KEYS: Pre-clear struct key on allocation · 2480f57f
      David Howells 提交于
      The second word of key->payload does not get initialised in key_alloc(), but
      the big_key type is relying on it having been cleared.  The problem comes when
      big_key fails to instantiate a large key and doesn't then set the payload.  The
      big_key_destroy() op is called from the garbage collector and this assumes that
      the dentry pointer stored in the second word will be NULL if instantiation did
      not complete.
      
      Therefore just pre-clear the entire struct key on allocation rather than trying
      to be clever and only initialising to 0 only those bits that aren't otherwise
      initialised.
      
      The lack of initialisation can lead to a bug report like the following if
      big_key failed to initialise its file:
      
      	general protection fault: 0000 [#1] SMP
      	Modules linked in: ...
      	CPU: 0 PID: 51 Comm: kworker/0:1 Not tainted 3.10.0-53.el7.x86_64 #1
      	Hardware name: Dell Inc. PowerEdge 1955/0HC513, BIOS 1.4.4 12/09/2008
      	Workqueue: events key_garbage_collector
      	task: ffff8801294f5680 ti: ffff8801296e2000 task.ti: ffff8801296e2000
      	RIP: 0010:[<ffffffff811b4a51>] dput+0x21/0x2d0
      	...
      	Call Trace:
      	 [<ffffffff811a7b06>] path_put+0x16/0x30
      	 [<ffffffff81235604>] big_key_destroy+0x44/0x60
      	 [<ffffffff8122dc4b>] key_gc_unused_keys.constprop.2+0x5b/0xe0
      	 [<ffffffff8122df2f>] key_garbage_collector+0x1df/0x3c0
      	 [<ffffffff8107759b>] process_one_work+0x17b/0x460
      	 [<ffffffff8107834b>] worker_thread+0x11b/0x400
      	 [<ffffffff81078230>] ? rescuer_thread+0x3e0/0x3e0
      	 [<ffffffff8107eb00>] kthread+0xc0/0xd0
      	 [<ffffffff8107ea40>] ? kthread_create_on_node+0x110/0x110
      	 [<ffffffff815c4bec>] ret_from_fork+0x7c/0xb0
      	 [<ffffffff8107ea40>] ? kthread_create_on_node+0x110/0x110
      Reported-by: NPatrik Kis <pkis@redhat.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      Reviewed-by: NStephen Gallagher <sgallagh@redhat.com>
      2480f57f
  13. 14 11月, 2013 2 次提交
    • D
      KEYS: Fix keyring content gc scanner · 62fe3182
      David Howells 提交于
      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: NDavid Howells <dhowells@redhat.com>
      Acked-by: NSimo Sorce <simo@redhat.com>
      62fe3182
    • D
      KEYS: Fix error handling in big_key instantiation · 97826c82
      David Howells 提交于
      In the big_key_instantiate() function we return 0 if kernel_write() returns us
      an error rather than returning an error.  This can potentially lead to
      dentry_open() giving a BUG when called from big_key_read() with an unset
      tmpfile path.
      
      	------------[ cut here ]------------
      	kernel BUG at fs/open.c:798!
      	...
      	RIP: 0010:[<ffffffff8119bbd1>] dentry_open+0xd1/0xe0
      	...
      	Call Trace:
      	 [<ffffffff812350c5>] big_key_read+0x55/0x100
      	 [<ffffffff81231084>] keyctl_read_key+0xb4/0xe0
      	 [<ffffffff81231e58>] SyS_keyctl+0xf8/0x1d0
      	 [<ffffffff815bb799>] system_call_fastpath+0x16/0x1b
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      Reviewed-by: NStephen Gallagher <sgallagh@redhat.com>
      97826c82
  14. 06 11月, 2013 1 次提交
    • D
      KEYS: Fix UID check in keyctl_get_persistent() · fbf8c53f
      David Howells 提交于
      If the UID is specified by userspace when calling the KEYCTL_GET_PERSISTENT
      function and the process does not have the CAP_SETUID capability, then the
      function will return -EPERM if the current process's uid, suid, euid and fsuid
      all match the requested UID.  This is incorrect.
      
      Fix it such that when a non-privileged caller requests a persistent keyring by
      a specific UID they can only request their own (ie. the specified UID matches
      either then process's UID or the process's EUID).
      
      This can be tested by logging in as the user and doing:
      
      	keyctl get_persistent @p
      	keyctl get_persistent @p `id -u`
      	keyctl get_persistent @p 0
      
      The first two should successfully print the same key ID.  The third should do
      the same if called by UID 0 or indicate Operation Not Permitted otherwise.
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      Acked-by: NStephen Gallagher <sgallagh@redhat.com>
      fbf8c53f
  15. 30 10月, 2013 4 次提交
    • W
      KEYS: fix error return code in big_key_instantiate() · d2b86970
      Wei Yongjun 提交于
      Fix to return a negative error code from the error handling
      case instead of 0, as done elsewhere in this function.
      Signed-off-by: NWei Yongjun <yongjun_wei@trendmicro.com.cn>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      d2b86970
    • D
      KEYS: Fix keyring quota misaccounting on key replacement and unlink · 034faeb9
      David Howells 提交于
      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: NStephen Gallagher <sgallagh@redhat.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      034faeb9
    • D
      KEYS: Fix a race between negating a key and reading the error set · 74792b00
      David Howells 提交于
      key_reject_and_link() marking a key as negative and setting the error with
      which it was negated races with keyring searches and other things that read
      that error.
      
      The fix is to switch the order in which the assignments are done in
      key_reject_and_link() and to use memory barriers.
      
      Kudos to Dave Wysochanski <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: NDavid Howells <dhowells@redhat.com>
      cc: Dave Wysochanski <dwysocha@redhat.com>
      cc: Scott Mayhew <smayhew@redhat.com>
      74792b00
    • J
      KEYS: Make BIG_KEYS boolean · 2eaf6b5d
      Josh Boyer 提交于
      Having the big_keys functionality as a module is very marginally useful.
      The userspace code that would use this functionality will get odd error
      messages from the keys layer if the module isn't loaded.  The code itself
      is fairly small, so just have this as a boolean option and not a tristate.
      Signed-off-by: NJosh Boyer <jwboyer@fedoraproject.org>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      2eaf6b5d
  16. 26 9月, 2013 2 次提交
  17. 24 9月, 2013 7 次提交
    • D
      KEYS: Add per-user_namespace registers for persistent per-UID kerberos caches · f36f8c75
      David Howells 提交于
      Add support for per-user_namespace registers of persistent per-UID kerberos
      caches held within the kernel.
      
      This allows the kerberos cache to be retained beyond the life of all a user's
      processes so that the user's cron jobs can work.
      
      The kerberos cache is envisioned as a keyring/key tree looking something like:
      
      	struct user_namespace
      	  \___ .krb_cache keyring		- The register
      		\___ _krb.0 keyring		- Root's Kerberos cache
      		\___ _krb.5000 keyring		- User 5000's Kerberos cache
      		\___ _krb.5001 keyring		- User 5001's Kerberos cache
      			\___ tkt785 big_key	- A ccache blob
      			\___ tkt12345 big_key	- Another ccache blob
      
      Or possibly:
      
      	struct user_namespace
      	  \___ .krb_cache keyring		- The register
      		\___ _krb.0 keyring		- Root's Kerberos cache
      		\___ _krb.5000 keyring		- User 5000's Kerberos cache
      		\___ _krb.5001 keyring		- User 5001's Kerberos cache
      			\___ tkt785 keyring	- A ccache
      				\___ krbtgt/REDHAT.COM@REDHAT.COM big_key
      				\___ http/REDHAT.COM@REDHAT.COM user
      				\___ afs/REDHAT.COM@REDHAT.COM user
      				\___ nfs/REDHAT.COM@REDHAT.COM user
      				\___ krbtgt/KERNEL.ORG@KERNEL.ORG big_key
      				\___ http/KERNEL.ORG@KERNEL.ORG big_key
      
      What goes into a particular Kerberos cache is entirely up to userspace.  Kernel
      support is limited to giving you the Kerberos cache keyring that you want.
      
      The user asks for their Kerberos cache by:
      
      	krb_cache = keyctl_get_krbcache(uid, dest_keyring);
      
      The uid is -1 or the user's own UID for the user's own cache or the uid of some
      other user's cache (requires CAP_SETUID).  This permits rpc.gssd or whatever to
      mess with the cache.
      
      The cache returned is a keyring named "_krb.<uid>" that the possessor can read,
      search, clear, invalidate, unlink from and add links to.  Active LSMs get a
      chance to rule on whether the caller is permitted to make a link.
      
      Each uid's cache keyring is created when it first accessed and is given a
      timeout that is extended each time this function is called so that the keyring
      goes away after a while.  The timeout is configurable by sysctl but defaults to
      three days.
      
      Each user_namespace struct gets a lazily-created keyring that serves as the
      register.  The cache keyrings are added to it.  This means that standard key
      search and garbage collection facilities are available.
      
      The user_namespace struct's register goes away when it does and anything left
      in it is then automatically gc'd.
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      Tested-by: NSimo Sorce <simo@redhat.com>
      cc: Serge E. Hallyn <serge.hallyn@ubuntu.com>
      cc: Eric W. Biederman <ebiederm@xmission.com>
      f36f8c75
    • D
      KEYS: Implement a big key type that can save to tmpfs · ab3c3587
      David Howells 提交于
      Implement a big key type that can save its contents to tmpfs and thus
      swapspace when memory is tight.  This is useful for Kerberos ticket caches.
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      Tested-by: NSimo Sorce <simo@redhat.com>
      ab3c3587
    • D
      KEYS: Expand the capacity of a keyring · b2a4df20
      David Howells 提交于
      Expand the capacity of a keyring to be able to hold a lot more keys by using
      the previously added associative array implementation.  Currently the maximum
      capacity is:
      
      	(PAGE_SIZE - sizeof(header)) / sizeof(struct key *)
      
      which, on a 64-bit system, is a little more 500.  However, since this is being
      used for the NFS uid mapper, we need more than that.  The new implementation
      gives us effectively unlimited capacity.
      
      With some alterations, the keyutils testsuite runs successfully to completion
      after this patch is applied.  The alterations are because (a) keyrings that
      are simply added to no longer appear ordered and (b) some of the errors have
      changed a bit.
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      b2a4df20
    • D
      KEYS: Drop the permissions argument from __keyring_search_one() · e57e8669
      David Howells 提交于
      Drop the permissions argument from __keyring_search_one() as the only caller
      passes 0 here - which causes all checks to be skipped.
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      e57e8669
    • D
      KEYS: Define a __key_get() wrapper to use rather than atomic_inc() · ccc3e6d9
      David Howells 提交于
      Define a __key_get() wrapper to use rather than atomic_inc() on the key usage
      count as this makes it easier to hook in refcount error debugging.
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      ccc3e6d9
    • D
      KEYS: Search for auth-key by name rather than target key ID · d0a059ca
      David Howells 提交于
      Search for auth-key by name rather than by target key ID as, in a future
      patch, we'll by searching directly by index key in preference to iteration
      over all keys.
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      d0a059ca
    • D
      KEYS: Introduce a search context structure · 4bdf0bc3
      David Howells 提交于
      Search functions pass around a bunch of arguments, each of which gets copied
      with each call.  Introduce a search context structure to hold these.
      
      Whilst we're at it, create a search flag that indicates whether the search
      should be directly to the description or whether it should iterate through all
      keys looking for a non-description match.
      
      This will be useful when keyrings use a generic data struct with generic
      routines to manage their content as the search terms can just be passed
      through to the iterator callback function.
      
      Also, for future use, the data to be supplied to the match function is
      separated from the description pointer in the search context.  This makes it
      clear which is being supplied.
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      4bdf0bc3