1. 02 3月, 2017 1 次提交
    • D
      KEYS: Differentiate uses of rcu_dereference_key() and user_key_payload() · 0837e49a
      David Howells 提交于
      rcu_dereference_key() and user_key_payload() are currently being used in
      two different, incompatible ways:
      
       (1) As a wrapper to rcu_dereference() - when only the RCU read lock used
           to protect the key.
      
       (2) As a wrapper to rcu_dereference_protected() - when the key semaphor is
           used to protect the key and the may be being modified.
      
      Fix this by splitting both of the key wrappers to produce:
      
       (1) RCU accessors for keys when caller has the key semaphore locked:
      
      	dereference_key_locked()
      	user_key_payload_locked()
      
       (2) RCU accessors for keys when caller holds the RCU read lock:
      
      	dereference_key_rcu()
      	user_key_payload_rcu()
      
      This should fix following warning in the NFS idmapper
      
        ===============================
        [ INFO: suspicious RCU usage. ]
        4.10.0 #1 Tainted: G        W
        -------------------------------
        ./include/keys/user-type.h:53 suspicious rcu_dereference_protected() usage!
        other info that might help us debug this:
        rcu_scheduler_active = 2, debug_locks = 0
        1 lock held by mount.nfs/5987:
          #0:  (rcu_read_lock){......}, at: [<d000000002527abc>] nfs_idmap_get_key+0x15c/0x420 [nfsv4]
        stack backtrace:
        CPU: 1 PID: 5987 Comm: mount.nfs Tainted: G        W       4.10.0 #1
        Call Trace:
          dump_stack+0xe8/0x154 (unreliable)
          lockdep_rcu_suspicious+0x140/0x190
          nfs_idmap_get_key+0x380/0x420 [nfsv4]
          nfs_map_name_to_uid+0x2a0/0x3b0 [nfsv4]
          decode_getfattr_attrs+0xfac/0x16b0 [nfsv4]
          decode_getfattr_generic.constprop.106+0xbc/0x150 [nfsv4]
          nfs4_xdr_dec_lookup_root+0xac/0xb0 [nfsv4]
          rpcauth_unwrap_resp+0xe8/0x140 [sunrpc]
          call_decode+0x29c/0x910 [sunrpc]
          __rpc_execute+0x140/0x8f0 [sunrpc]
          rpc_run_task+0x170/0x200 [sunrpc]
          nfs4_call_sync_sequence+0x68/0xa0 [nfsv4]
          _nfs4_lookup_root.isra.44+0xd0/0xf0 [nfsv4]
          nfs4_lookup_root+0xe0/0x350 [nfsv4]
          nfs4_lookup_root_sec+0x70/0xa0 [nfsv4]
          nfs4_find_root_sec+0xc4/0x100 [nfsv4]
          nfs4_proc_get_rootfh+0x5c/0xf0 [nfsv4]
          nfs4_get_rootfh+0x6c/0x190 [nfsv4]
          nfs4_server_common_setup+0xc4/0x260 [nfsv4]
          nfs4_create_server+0x278/0x3c0 [nfsv4]
          nfs4_remote_mount+0x50/0xb0 [nfsv4]
          mount_fs+0x74/0x210
          vfs_kern_mount+0x78/0x220
          nfs_do_root_mount+0xb0/0x140 [nfsv4]
          nfs4_try_mount+0x60/0x100 [nfsv4]
          nfs_fs_mount+0x5ec/0xda0 [nfs]
          mount_fs+0x74/0x210
          vfs_kern_mount+0x78/0x220
          do_mount+0x254/0xf70
          SyS_mount+0x94/0x100
          system_call+0x38/0xe0
      Reported-by: NJan Stancek <jstancek@redhat.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      Tested-by: NJan Stancek <jstancek@redhat.com>
      Signed-off-by: NJames Morris <james.l.morris@oracle.com>
      0837e49a
  2. 12 4月, 2016 1 次提交
    • D
      KEYS: Add a facility to restrict new links into a keyring · 5ac7eace
      David Howells 提交于
      Add a facility whereby proposed new links to be added to a keyring can be
      vetted, permitting them to be rejected if necessary.  This can be used to
      block public keys from which the signature cannot be verified or for which
      the signature verification fails.  It could also be used to provide
      blacklisting.
      
      This affects operations like add_key(), KEYCTL_LINK and KEYCTL_INSTANTIATE.
      
      To this end:
      
       (1) A function pointer is added to the key struct that, if set, points to
           the vetting function.  This is called as:
      
      	int (*restrict_link)(struct key *keyring,
      			     const struct key_type *key_type,
      			     unsigned long key_flags,
      			     const union key_payload *key_payload),
      
           where 'keyring' will be the keyring being added to, key_type and
           key_payload will describe the key being added and key_flags[*] can be
           AND'ed with KEY_FLAG_TRUSTED.
      
           [*] This parameter will be removed in a later patch when
           	 KEY_FLAG_TRUSTED is removed.
      
           The function should return 0 to allow the link to take place or an
           error (typically -ENOKEY, -ENOPKG or -EKEYREJECTED) to reject the
           link.
      
           The pointer should not be set directly, but rather should be set
           through keyring_alloc().
      
           Note that if called during add_key(), preparse is called before this
           method, but a key isn't actually allocated until after this function
           is called.
      
       (2) KEY_ALLOC_BYPASS_RESTRICTION is added.  This can be passed to
           key_create_or_update() or key_instantiate_and_link() to bypass the
           restriction check.
      
       (3) KEY_FLAG_TRUSTED_ONLY is removed.  The entire contents of a keyring
           with this restriction emplaced can be considered 'trustworthy' by
           virtue of being in the keyring when that keyring is consulted.
      
       (4) key_alloc() and keyring_alloc() take an extra argument that will be
           used to set restrict_link in the new key.  This ensures that the
           pointer is set before the key is published, thus preventing a window
           of unrestrictedness.  Normally this argument will be NULL.
      
       (5) As a temporary affair, keyring_restrict_trusted_only() is added.  It
           should be passed to keyring_alloc() as the extra argument instead of
           setting KEY_FLAG_TRUSTED_ONLY on a keyring.  This will be replaced in
           a later patch with functions that look in the appropriate places for
           authoritative keys.
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      Reviewed-by: NMimi Zohar <zohar@linux.vnet.ibm.com>
      5ac7eace
  3. 19 11月, 2015 1 次提交
  4. 21 10月, 2015 1 次提交
    • D
      KEYS: Merge the type-specific data with the payload data · 146aa8b1
      David Howells 提交于
      Merge the type-specific data with the payload data into one four-word chunk
      as it seems pointless to keep them separate.
      
      Use user_key_payload() for accessing the payloads of overloaded
      user-defined keys.
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      cc: linux-cifs@vger.kernel.org
      cc: ecryptfs@vger.kernel.org
      cc: linux-ext4@vger.kernel.org
      cc: linux-f2fs-devel@lists.sourceforge.net
      cc: linux-nfs@vger.kernel.org
      cc: ceph-devel@vger.kernel.org
      cc: linux-ima-devel@lists.sourceforge.net
      146aa8b1
  5. 17 9月, 2014 3 次提交
  6. 23 7月, 2014 1 次提交
  7. 21 7月, 2014 1 次提交
  8. 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
  9. 11 6月, 2014 1 次提交
  10. 05 6月, 2014 1 次提交
  11. 07 12月, 2013 1 次提交
  12. 13 7月, 2013 1 次提交
  13. 08 10月, 2012 1 次提交
    • D
      KEYS: Add payload preparsing opportunity prior to key instantiate or update · cf7f601c
      David Howells 提交于
      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: NDavid Howells <dhowells@redhat.com>
      Signed-off-by: NRusty Russell <rusty@rustcorp.com.au>
      cf7f601c
  14. 03 10月, 2012 1 次提交
  15. 14 9月, 2012 1 次提交
  16. 13 9月, 2012 1 次提交
    • D
      KEYS: Add payload preparsing opportunity prior to key instantiate or update · d4f65b5d
      David Howells 提交于
      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: NDavid Howells <dhowells@redhat.com>
      d4f65b5d
  17. 11 5月, 2012 1 次提交
  18. 16 4月, 2012 1 次提交
  19. 19 1月, 2012 1 次提交
  20. 17 3月, 2011 1 次提交
    • D
      KEYS: Improve /proc/keys · 78b7280c
      David Howells 提交于
      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: NDavid Howells <dhowells@redhat.com>
      Signed-off-by: NJames Morris <jmorris@namei.org>
      78b7280c
  21. 04 3月, 2011 1 次提交
    • D
      DNS: Fix a NULL pointer deref when trying to read an error key [CVE-2011-1076] · 1362fa07
      David Howells 提交于
      When a DNS resolver key is instantiated with an error indication, attempts to
      read that key will result in an oops because user_read() is expecting there to
      be a payload - and there isn't one [CVE-2011-1076].
      
      Give the DNS resolver key its own read handler that returns the error cached in
      key->type_data.x[0] as an error rather than crashing.
      
      Also make the kenter() at the beginning of dns_resolver_instantiate() limit the
      amount of data it prints, since the data is not necessarily NUL-terminated.
      
      The buggy code was added in:
      
      	commit 4a2d7892
      	Author: Wang Lei <wang840925@gmail.com>
      	Date:   Wed Aug 11 09:37:58 2010 +0100
      	Subject: DNS: If the DNS server returns an error, allow that to be cached [ver #2]
      
      This can trivially be reproduced by any user with the following program
      compiled with -lkeyutils:
      
      	#include <stdlib.h>
      	#include <keyutils.h>
      	#include <err.h>
      	static char payload[] = "#dnserror=6";
      	int main()
      	{
      		key_serial_t key;
      		key = add_key("dns_resolver", "a", payload, sizeof(payload),
      			      KEY_SPEC_SESSION_KEYRING);
      		if (key == -1)
      			err(1, "add_key");
      		if (keyctl_read(key, NULL, 0) == -1)
      			err(1, "read_key");
      		return 0;
      	}
      
      What should happen is that keyctl_read() reports error 6 (ENXIO) to the user:
      
      	dns-break: read_key: No such device or address
      
      but instead the kernel oopses.
      
      This cannot be reproduced with the 'keyutils add' or 'keyutils padd' commands
      as both of those cut the data down below the NUL termination that must be
      included in the data.  Without this dns_resolver_instantiate() will return
      -EINVAL and the key will not be instantiated such that it can be read.
      
      The oops looks like:
      
      BUG: unable to handle kernel NULL pointer dereference at 0000000000000010
      IP: [<ffffffff811b99f7>] user_read+0x4f/0x8f
      PGD 3bdf8067 PUD 385b9067 PMD 0
      Oops: 0000 [#1] SMP
      last sysfs file: /sys/devices/pci0000:00/0000:00:19.0/irq
      CPU 0
      Modules linked in:
      
      Pid: 2150, comm: dns-break Not tainted 2.6.38-rc7-cachefs+ #468                  /DG965RY
      RIP: 0010:[<ffffffff811b99f7>]  [<ffffffff811b99f7>] user_read+0x4f/0x8f
      RSP: 0018:ffff88003bf47f08  EFLAGS: 00010246
      RAX: 0000000000000001 RBX: ffff88003b5ea378 RCX: ffffffff81972368
      RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff88003b5ea378
      RBP: ffff88003bf47f28 R08: ffff88003be56620 R09: 0000000000000000
      R10: 0000000000000395 R11: 0000000000000002 R12: 0000000000000000
      R13: 0000000000000000 R14: 0000000000000000 R15: ffffffffffffffa1
      FS:  00007feab5751700(0000) GS:ffff88003e000000(0000) knlGS:0000000000000000
      CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
      CR2: 0000000000000010 CR3: 000000003de40000 CR4: 00000000000006f0
      DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
      DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
      Process dns-break (pid: 2150, threadinfo ffff88003bf46000, task ffff88003be56090)
      Stack:
       ffff88003b5ea378 ffff88003b5ea3a0 0000000000000000 0000000000000000
       ffff88003bf47f68 ffffffff811b708e ffff88003c442bc8 0000000000000000
       00000000004005a0 00007fffba368060 0000000000000000 0000000000000000
      Call Trace:
       [<ffffffff811b708e>] keyctl_read_key+0xac/0xcf
       [<ffffffff811b7c07>] sys_keyctl+0x75/0xb6
       [<ffffffff81001f7b>] system_call_fastpath+0x16/0x1b
      Code: 75 1f 48 83 7b 28 00 75 18 c6 05 58 2b fb 00 01 be bb 00 00 00 48 c7 c7 76 1c 75 81 e8 13 c2 e9 ff 4c 8b b3 e0 00 00 00 4d 85 ed <41> 0f b7 5e 10 74 2d 4d 85 e4 74 28 e8 98 79 ee ff 49 39 dd 48
      RIP  [<ffffffff811b99f7>] user_read+0x4f/0x8f
       RSP <ffff88003bf47f08>
      CR2: 0000000000000010
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      Acked-by: NJeff Layton <jlayton@redhat.com>
      cc: Wang Lei <wang840925@gmail.com>
      Signed-off-by: NJames Morris <jmorris@namei.org>
      1362fa07
  22. 23 11月, 2010 1 次提交
  23. 12 8月, 2010 1 次提交
    • W
      DNS: If the DNS server returns an error, allow that to be cached [ver #2] · 4a2d7892
      Wang Lei 提交于
      If the DNS server returns an error, allow that to be cached in the DNS resolver
      key in lieu of a value.  Userspace passes the desired error number as an option
      in the payload:
      
      	"#dnserror=<number>"
      
      Userspace must map h_errno from the name resolution routines to an appropriate
      Linux error before passing it up.  Something like the following mapping is
      recommended:
      
      	[HOST_NOT_FOUND]	= ENODATA,
      	[TRY_AGAIN]		= EAGAIN,
      	[NO_RECOVERY]		= ECONNREFUSED,
      	[NO_DATA]		= ENODATA,
      
      in lieu of Linux errors specifically for representing name service errors.  The
      filesystem must map these errors appropropriately before passing them to
      userspace.  AFS is made to map ENODATA and EAGAIN to EDESTADDRREQ for the
      return to userspace; ECONNREFUSED is allowed to stand as is.
      
      The error can be seen in /proc/keys as a negative number after the description
      of the key.  Compare, for example, the following key entries:
      
      2f97238c I--Q--     1  53s 3f010000     0     0 dns_resol afsdb:grand.centrall.org: -61
      338bfbbe I--Q--     1  59m 3f010000     0     0 dns_resol afsdb:grand.central.org: 37
      
      If the error option is supplied in the payload, the main part of the payload is
      discarded.  The key should have an expiry time set by userspace.
      Signed-off-by: NWang Lei <wang840925@gmail.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      Acked-by: NJeff Layton <jlayton@redhat.com>
      Signed-off-by: NSteve French <sfrench@us.ibm.com>
      4a2d7892
  24. 06 8月, 2010 4 次提交
    • S
      [DNS RESOLVER] Minor typo correction · 5227bbb0
      Steve French 提交于
      CC: Dave Howells <dhowells@redhat.com>
      Signed-off-by: NSteve French <sfrench@us.ibm.com>
      5227bbb0
    • D
      DNS: Fixes for the DNS query module · ff9517a6
      David Howells 提交于
      Fixes for the DNS query module, including:
      
       (1) Use 'negative' instead of '-ve' in the documentation.
      
       (2) Mark the kdoc comment with '/**' on dns_query().
      Reported-by: NRandy Dunlap <randy.dunlap@oracle.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      Signed-off-by: NSteve French <sfrench@us.ibm.com>
      ff9517a6
    • S
      cifs: Include linux/err.h for IS_ERR and PTR_ERR · af352fe9
      Stephen Rothwell 提交于
      Fixes build errors:
      
      net/dns_resolver/dns_key.c: In function 'init_dns_resolver':
      net/dns_resolver/dns_key.c:170: error: implicit declaration of function 'IS_ERR'
      net/dns_resolver/dns_key.c:171: error: implicit declaration of function 'PTR_ERR'
      net/dns_resolver/dns_query.c: In function 'dns_query':
      net/dns_resolver/dns_query.c:126: error: implicit declaration of function 'IS_ERR'
      net/dns_resolver/dns_query.c:127: error: implicit declaration of function 'PTR_ERR'
      Signed-off-by: NStephen Rothwell <sfr@canb.auug.org.au>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      Signed-off-by: NSteve French <sfrench@us.ibm.com>
      af352fe9
    • W
      DNS: Separate out CIFS DNS Resolver code · 1a4240f4
      Wang Lei 提交于
      Separate out the DNS resolver key type from the CIFS filesystem into its own
      module so that it can be made available for general use, including the AFS
      filesystem module.
      
      This facility makes it possible for the kernel to upcall to userspace to have
      it issue DNS requests, package up the replies and present them to the kernel
      in a useful form.  The kernel is then able to cache the DNS replies as keys
      can be retained in keyrings.
      
      Resolver keys are of type "dns_resolver" and have a case-insensitive
      description that is of the form "[<type>:]<domain_name>".  The optional <type>
      indicates the particular DNS lookup and packaging that's required.  The
      <domain_name> is the query to be made.
      
      If <type> isn't given, a basic hostname to IP address lookup is made, and the
      result is stored in the key in the form of a printable string consisting of a
      comma-separated list of IPv4 and IPv6 addresses.
      
      This key type is supported by userspace helpers driven from /sbin/request-key
      and configured through /etc/request-key.conf.  The cifs.upcall utility is
      invoked for UNC path server name to IP address resolution.
      
      The CIFS functionality is encapsulated by the dns_resolve_unc_to_ip() function,
      which is used to resolve a UNC path to an IP address for CIFS filesystem.  This
      part remains in the CIFS module for now.
      
      See the added Documentation/networking/dns_resolver.txt for more information.
      Signed-off-by: NWang Lei <wang840925@gmail.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      Acked-by: NJeff Layton <jlayton@redhat.com>
      Signed-off-by: NSteve French <sfrench@us.ibm.com>
      1a4240f4