19 May, 2020

2 commits

  • Since the meaning of combining the KEY_NEED_* constants is undefined, make
    it so that you can't do that by turning them into an enum.

    The enum is also given some extra values to represent special
    circumstances, such as:

    (1) The '0' value is reserved and causes a warning to trap the parameter
    being unset.

    (2) The key is to be unlinked and we require no permissions on it, only
    the keyring, (this replaces the KEY_LOOKUP_FOR_UNLINK flag).

    (3) An override due to CAP_SYS_ADMIN.

    (4) An override due to an instantiation token being present.

    (5) The permissions check is being deferred to later key_permission()
    calls.

    The extra values give the opportunity for LSMs to audit these situations.

    [Note: This really needs overhauling so that lookup_user_key() tells
    key_task_permission() and the LSM what operation is being done and leaves
    it to those functions to decide how to map that onto the available
    permits. However, I don't really want to make these change in the middle
    of the notifications patchset.]

    Signed-off-by: David Howells
    cc: Jarkko Sakkinen
    cc: Paul Moore
    cc: Stephen Smalley
    cc: Casey Schaufler
    cc: keyrings@vger.kernel.org
    cc: selinux@vger.kernel.org

    David Howells
     
  • Add a key/keyring change notification facility whereby notifications about
    changes in key and keyring content and attributes can be received.

    Firstly, an event queue needs to be created:

    pipe2(fds, O_NOTIFICATION_PIPE);
    ioctl(fds[1], IOC_WATCH_QUEUE_SET_SIZE, 256);

    then a notification can be set up to report notifications via that queue:

    struct watch_notification_filter filter = {
    .nr_filters = 1,
    .filters = {
    [0] = {
    .type = WATCH_TYPE_KEY_NOTIFY,
    .subtype_filter[0] = UINT_MAX,
    },
    },
    };
    ioctl(fds[1], IOC_WATCH_QUEUE_SET_FILTER, &filter);
    keyctl_watch_key(KEY_SPEC_SESSION_KEYRING, fds[1], 0x01);

    After that, records will be placed into the queue when events occur in
    which keys are changed in some way. Records are of the following format:

    struct key_notification {
    struct watch_notification watch;
    __u32 key_id;
    __u32 aux;
    } *n;

    Where:

    n->watch.type will be WATCH_TYPE_KEY_NOTIFY.

    n->watch.subtype will indicate the type of event, such as
    NOTIFY_KEY_REVOKED.

    n->watch.info & WATCH_INFO_LENGTH will indicate the length of the
    record.

    n->watch.info & WATCH_INFO_ID will be the second argument to
    keyctl_watch_key(), shifted.

    n->key will be the ID of the affected key.

    n->aux will hold subtype-dependent information, such as the key
    being linked into the keyring specified by n->key in the case of
    NOTIFY_KEY_LINKED.

    Note that it is permissible for event records to be of variable length -
    or, at least, the length may be dependent on the subtype. Note also that
    the queue can be shared between multiple notifications of various types.

    Signed-off-by: David Howells
    Reviewed-by: James Morris

    David Howells
     

02 Sep, 2019

1 commit

  • Provide an RCU-capable key lookup function. We don't want to call
    afs_request_key() in RCU-mode pathwalk as request_key() might sleep, even if
    we don't ask it to construct anything as it might find a key that is currently
    undergoing construction.

    Signed-off-by: David Howells

    David Howells
     

20 Aug, 2019

1 commit

  • The maximum key description size is 4095. Commit f771fde82051 ("keys:
    Simplify key description management") inadvertantly reduced that to 255
    and made sizes between 256 and 4095 work weirdly, and any size whereby
    size & 255 == 0 would cause an assertion in __key_link_begin() at the
    following line:

    BUG_ON(index_key->desc_len == 0);

    This can be fixed by simply increasing the size of desc_len in struct
    keyring_index_key to a u16.

    Note the argument length test in keyutils only checked empty
    descriptions and descriptions with a size around the limit (ie. 4095)
    and not for all the values in between, so it missed this. This has been
    addressed and

    https://git.kernel.org/pub/scm/linux/kernel/git/dhowells/keyutils.git/commit/?id=066bf56807c26cd3045a25f355b34c1d8a20a5aa

    now exhaustively tests all possible lengths of type, description and
    payload and then some.

    The assertion failure looks something like:

    kernel BUG at security/keys/keyring.c:1245!
    ...
    RIP: 0010:__key_link_begin+0x88/0xa0
    ...
    Call Trace:
    key_create_or_update+0x211/0x4b0
    __x64_sys_add_key+0x101/0x200
    do_syscall_64+0x5b/0x1e0
    entry_SYSCALL_64_after_hwframe+0x44/0xa9

    It can be triggered by:

    keyctl add user "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" a @s

    Fixes: f771fde82051 ("keys: Simplify key description management")
    Reported-by: kernel test robot
    Signed-off-by: David Howells
    Signed-off-by: Linus Torvalds

    David Howells
     

11 Jul, 2019

1 commit

  • …el/git/dhowells/linux-fs"

    This reverts merge 0f75ef6a9cff49ff612f7ce0578bced9d0b38325 (and thus
    effectively commits

    7a1ade847596 ("keys: Provide KEYCTL_GRANT_PERMISSION")
    2e12256b9a76 ("keys: Replace uid/gid/perm permissions checking with an ACL")

    that the merge brought in).

    It turns out that it breaks booting with an encrypted volume, and Eric
    biggers reports that it also breaks the fscrypt tests [1] and loading of
    in-kernel X.509 certificates [2].

    The root cause of all the breakage is likely the same, but David Howells
    is off email so rather than try to work it out it's getting reverted in
    order to not impact the rest of the merge window.

    [1] https://lore.kernel.org/lkml/20190710011559.GA7973@sol.localdomain/
    [2] https://lore.kernel.org/lkml/20190710013225.GB7973@sol.localdomain/

    Link: https://lore.kernel.org/lkml/CAHk-=wjxoeMJfeBahnWH=9zShKp2bsVy527vo3_y8HfOdhwAAw@mail.gmail.com/
    Reported-by: Eric Biggers <ebiggers@kernel.org>
    Cc: David Howells <dhowells@redhat.com>
    Cc: James Morris <jmorris@namei.org>
    Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

    Linus Torvalds
     

09 Jul, 2019

4 commits

  • Pull keyring ACL support from David Howells:
    "This changes the permissions model used by keys and keyrings to be
    based on an internal ACL by the following means:

    - Replace the permissions mask internally with an ACL that contains a
    list of ACEs, each with a specific subject with a permissions mask.
    Potted default ACLs are available for new keys and keyrings.

    ACE subjects can be macroised to indicate the UID and GID specified
    on the key (which remain). Future commits will be able to add
    additional subject types, such as specific UIDs or domain
    tags/namespaces.

    Also split a number of permissions to give finer control. Examples
    include splitting the revocation permit from the change-attributes
    permit, thereby allowing someone to be granted permission to revoke
    a key without allowing them to change the owner; also the ability
    to join a keyring is split from the ability to link to it, thereby
    stopping a process accessing a keyring by joining it and thus
    acquiring use of possessor permits.

    - Provide a keyctl to allow the granting or denial of one or more
    permits to a specific subject. Direct access to the ACL is not
    granted, and the ACL cannot be viewed"

    * tag 'keys-acl-20190703' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs:
    keys: Provide KEYCTL_GRANT_PERMISSION
    keys: Replace uid/gid/perm permissions checking with an ACL

    Linus Torvalds
     
  • …/git/dhowells/linux-fs

    Pull keyring namespacing from David Howells:
    "These patches help make keys and keyrings more namespace aware.

    Firstly some miscellaneous patches to make the process easier:

    - Simplify key index_key handling so that the word-sized chunks
    assoc_array requires don't have to be shifted about, making it
    easier to add more bits into the key.

    - Cache the hash value in the key so that we don't have to calculate
    on every key we examine during a search (it involves a bunch of
    multiplications).

    - Allow keying_search() to search non-recursively.

    Then the main patches:

    - Make it so that keyring names are per-user_namespace from the point
    of view of KEYCTL_JOIN_SESSION_KEYRING so that they're not
    accessible cross-user_namespace.

    keyctl_capabilities() shows KEYCTL_CAPS1_NS_KEYRING_NAME for this.

    - Move the user and user-session keyrings to the user_namespace
    rather than the user_struct. This prevents them propagating
    directly across user_namespaces boundaries (ie. the KEY_SPEC_*
    flags will only pick from the current user_namespace).

    - Make it possible to include the target namespace in which the key
    shall operate in the index_key. This will allow the possibility of
    multiple keys with the same description, but different target
    domains to be held in the same keyring.

    keyctl_capabilities() shows KEYCTL_CAPS1_NS_KEY_TAG for this.

    - Make it so that keys are implicitly invalidated by removal of a
    domain tag, causing them to be garbage collected.

    - Institute a network namespace domain tag that allows keys to be
    differentiated by the network namespace in which they operate. New
    keys that are of a type marked 'KEY_TYPE_NET_DOMAIN' are assigned
    the network domain in force when they are created.

    - Make it so that the desired network namespace can be handed down
    into the request_key() mechanism. This allows AFS, NFS, etc. to
    request keys specific to the network namespace of the superblock.

    This also means that the keys in the DNS record cache are
    thenceforth namespaced, provided network filesystems pass the
    appropriate network namespace down into dns_query().

    For DNS, AFS and NFS are good, whilst CIFS and Ceph are not. Other
    cache keyrings, such as idmapper keyrings, also need to set the
    domain tag - for which they need access to the network namespace of
    the superblock"

    * tag 'keys-namespace-20190627' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs:
    keys: Pass the network namespace into request_key mechanism
    keys: Network namespace domain tag
    keys: Garbage collect keys for which the domain has been removed
    keys: Include target namespace in match criteria
    keys: Move the user and user-session keyrings to the user_namespace
    keys: Namespace keyring names
    keys: Add a 'recurse' flag for keyring searches
    keys: Cache the hash value to avoid lots of recalculation
    keys: Simplify key description management

    Linus Torvalds
     
  • Pull request_key improvements from David Howells:
    "These are all request_key()-related, including a fix and some improvements:

    - Fix the lack of a Link permission check on a key found by
    request_key(), thereby enabling request_key() to link keys that
    don't grant this permission to the target keyring (which must still
    grant Write permission).

    Note that the key must be in the caller's keyrings already to be
    found.

    - Invalidate used request_key authentication keys rather than
    revoking them, so that they get cleaned up immediately rather than
    hanging around till the expiry time is passed.

    - Move the RCU locks outwards from the keyring search functions so
    that a request_key_rcu() can be provided. This can be called in RCU
    mode, so it can't sleep and can't upcall - but it can be called
    from LOOKUP_RCU pathwalk mode.

    - Cache the latest positive result of request_key*() temporarily in
    task_struct so that filesystems that make a lot of request_key()
    calls during pathwalk can take advantage of it to avoid having to
    redo the searching. This requires CONFIG_KEYS_REQUEST_CACHE=y.

    It is assumed that the key just found is likely to be used multiple
    times in each step in an RCU pathwalk, and is likely to be reused
    for the next step too.

    Note that the cleanup of the cache is done on TIF_NOTIFY_RESUME,
    just before userspace resumes, and on exit"

    * tag 'keys-request-20190626' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs:
    keys: Kill off request_key_async{,_with_auxdata}
    keys: Cache result of request_key*() temporarily in task_struct
    keys: Provide request_key_rcu()
    keys: Move the RCU locks outwards from the keyring search functions
    keys: Invalidate used request_key authentication keys
    keys: Fix request_key() lack of Link perm check on found key

    Linus Torvalds
     
  • Pull misc keyring updates from David Howells:
    "These are some miscellaneous keyrings fixes and improvements:

    - Fix a bunch of warnings from sparse, including missing RCU bits and
    kdoc-function argument mismatches

    - Implement a keyctl to allow a key to be moved from one keyring to
    another, with the option of prohibiting key replacement in the
    destination keyring.

    - Grant Link permission to possessors of request_key_auth tokens so
    that upcall servicing daemons can more easily arrange things such
    that only the necessary auth key is passed to the actual service
    program, and not all the auth keys a daemon might possesss.

    - Improvement in lookup_user_key().

    - Implement a keyctl to allow keyrings subsystem capabilities to be
    queried.

    The keyutils next branch has commits to make available, document and
    test the move-key and capabilities code:

    https://git.kernel.org/pub/scm/linux/kernel/git/dhowells/keyutils.git/log

    They're currently on the 'next' branch"

    * tag 'keys-misc-20190619' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs:
    keys: Add capability-checking keyctl function
    keys: Reuse keyring_index_key::desc_len in lookup_user_key()
    keys: Grant Link permission to possessers of request_key auth keys
    keys: Add a keyctl to move a key between keyrings
    keys: Hoist locking out of __key_link_begin()
    keys: Break bits out of key_unlink()
    keys: Change keyring_serialise_link_sem to a mutex
    keys: sparse: Fix kdoc mismatches
    keys: sparse: Fix incorrect RCU accesses
    keys: sparse: Fix key_fs[ug]id_changed()

    Linus Torvalds
     

28 Jun, 2019

2 commits

  • Replace the uid/gid/perm permissions checking on a key with an ACL to allow
    the SETATTR and SEARCH permissions to be split. This will also allow a
    greater range of subjects to represented.

    ============
    WHY DO THIS?
    ============

    The problem is that SETATTR and SEARCH cover a slew of actions, not all of
    which should be grouped together.

    For SETATTR, this includes actions that are about controlling access to a
    key:

    (1) Changing a key's ownership.

    (2) Changing a key's security information.

    (3) Setting a keyring's restriction.

    And actions that are about managing a key's lifetime:

    (4) Setting an expiry time.

    (5) Revoking a key.

    and (proposed) managing a key as part of a cache:

    (6) Invalidating a key.

    Managing a key's lifetime doesn't really have anything to do with
    controlling access to that key.

    Expiry time is awkward since it's more about the lifetime of the content
    and so, in some ways goes better with WRITE permission. It can, however,
    be set unconditionally by a process with an appropriate authorisation token
    for instantiating a key, and can also be set by the key type driver when a
    key is instantiated, so lumping it with the access-controlling actions is
    probably okay.

    As for SEARCH permission, that currently covers:

    (1) Finding keys in a keyring tree during a search.

    (2) Permitting keyrings to be joined.

    (3) Invalidation.

    But these don't really belong together either, since these actions really
    need to be controlled separately.

    Finally, there are number of special cases to do with granting the
    administrator special rights to invalidate or clear keys that I would like
    to handle with the ACL rather than key flags and special checks.

    ===============
    WHAT IS CHANGED
    ===============

    The SETATTR permission is split to create two new permissions:

    (1) SET_SECURITY - which allows the key's owner, group and ACL to be
    changed and a restriction to be placed on a keyring.

    (2) REVOKE - which allows a key to be revoked.

    The SEARCH permission is split to create:

    (1) SEARCH - which allows a keyring to be search and a key to be found.

    (2) JOIN - which allows a keyring to be joined as a session keyring.

    (3) INVAL - which allows a key to be invalidated.

    The WRITE permission is also split to create:

    (1) WRITE - which allows a key's content to be altered and links to be
    added, removed and replaced in a keyring.

    (2) CLEAR - which allows a keyring to be cleared completely. This is
    split out to make it possible to give just this to an administrator.

    (3) REVOKE - see above.

    Keys acquire ACLs which consist of a series of ACEs, and all that apply are
    unioned together. An ACE specifies a subject, such as:

    (*) Possessor - permitted to anyone who 'possesses' a key
    (*) Owner - permitted to the key owner
    (*) Group - permitted to the key group
    (*) Everyone - permitted to everyone

    Note that 'Other' has been replaced with 'Everyone' on the assumption that
    you wouldn't grant a permit to 'Other' that you wouldn't also grant to
    everyone else.

    Further subjects may be made available by later patches.

    The ACE also specifies a permissions mask. The set of permissions is now:

    VIEW Can view the key metadata
    READ Can read the key content
    WRITE Can update/modify the key content
    SEARCH Can find the key by searching/requesting
    LINK Can make a link to the key
    SET_SECURITY Can change owner, ACL, expiry
    INVAL Can invalidate
    REVOKE Can revoke
    JOIN Can join this keyring
    CLEAR Can clear this keyring

    The KEYCTL_SETPERM function is then deprecated.

    The KEYCTL_SET_TIMEOUT function then is permitted if SET_SECURITY is set,
    or if the caller has a valid instantiation auth token.

    The KEYCTL_INVALIDATE function then requires INVAL.

    The KEYCTL_REVOKE function then requires REVOKE.

    The KEYCTL_JOIN_SESSION_KEYRING function then requires JOIN to join an
    existing keyring.

    The JOIN permission is enabled by default for session keyrings and manually
    created keyrings only.

    ======================
    BACKWARD COMPATIBILITY
    ======================

    To maintain backward compatibility, KEYCTL_SETPERM will translate the
    permissions mask it is given into a new ACL for a key - unless
    KEYCTL_SET_ACL has been called on that key, in which case an error will be
    returned.

    It will convert possessor, owner, group and other permissions into separate
    ACEs, if each portion of the mask is non-zero.

    SETATTR permission turns on all of INVAL, REVOKE and SET_SECURITY. WRITE
    permission turns on WRITE, REVOKE and, if a keyring, CLEAR. JOIN is turned
    on if a keyring is being altered.

    The KEYCTL_DESCRIBE function translates the ACL back into a permissions
    mask to return depending on possessor, owner, group and everyone ACEs.

    It will make the following mappings:

    (1) INVAL, JOIN -> SEARCH

    (2) SET_SECURITY -> SETATTR

    (3) REVOKE -> WRITE if SETATTR isn't already set

    (4) CLEAR -> WRITE

    Note that the value subsequently returned by KEYCTL_DESCRIBE may not match
    the value set with KEYCTL_SETATTR.

    =======
    TESTING
    =======

    This passes the keyutils testsuite for all but a couple of tests:

    (1) tests/keyctl/dh_compute/badargs: The first wrong-key-type test now
    returns EOPNOTSUPP rather than ENOKEY as READ permission isn't removed
    if the type doesn't have ->read(). You still can't actually read the
    key.

    (2) tests/keyctl/permitting/valid: The view-other-permissions test doesn't
    work as Other has been replaced with Everyone in the ACL.

    Signed-off-by: David Howells

    David Howells
     
  • Create a request_key_net() function and use it to pass the network
    namespace domain tag into DNS revolver keys and rxrpc/AFS keys so that keys
    for different domains can coexist in the same keyring.

    Signed-off-by: David Howells
    cc: netdev@vger.kernel.org
    cc: linux-nfs@vger.kernel.org
    cc: linux-cifs@vger.kernel.org
    cc: linux-afs@lists.infradead.org

    David Howells
     

27 Jun, 2019

7 commits

  • If a key operation domain (such as a network namespace) has been removed
    then attempt to garbage collect all the keys that use it.

    Signed-off-by: David Howells

    David Howells
     
  • Currently a key has a standard matching criteria of { type, description }
    and this is used to only allow keys with unique criteria in a keyring.
    This means, however, that you cannot have keys with the same type and
    description but a different target namespace in the same keyring.

    This is a potential problem for a containerised environment where, say, a
    container is made up of some parts of its mount space involving netfs
    superblocks from two different network namespaces.

    This is also a problem for shared system management keyrings such as the
    DNS records keyring or the NFS idmapper keyring that might contain keys
    from different network namespaces.

    Fix this by including a namespace component in a key's matching criteria.
    Keyring types are marked to indicate which, if any, namespace is relevant
    to keys of that type, and that namespace is set when the key is created
    from the current task's namespace set.

    The capability bit KEYCTL_CAPS1_NS_KEY_TAG is set if the kernel is
    employing this feature.

    Signed-off-by: David Howells

    David Howells
     
  • Keyring names are held in a single global list that any process can pick
    from by means of keyctl_join_session_keyring (provided the keyring grants
    Search permission). This isn't very container friendly, however.

    Make the following changes:

    (1) Make default session, process and thread keyring names begin with a
    '.' instead of '_'.

    (2) Keyrings whose names begin with a '.' aren't added to the list. Such
    keyrings are system specials.

    (3) Replace the global list with per-user_namespace lists. A keyring adds
    its name to the list for the user_namespace that it is currently in.

    (4) When a user_namespace is deleted, it just removes itself from the
    keyring name list.

    The global keyring_name_lock is retained for accessing the name lists.
    This allows (4) to work.

    This can be tested by:

    # keyctl newring foo @s
    995906392
    # unshare -U
    $ keyctl show
    ...
    995906392 --alswrv 65534 65534 \_ keyring: foo
    ...
    $ keyctl session foo
    Joined session keyring: 935622349

    As can be seen, a new session keyring was created.

    The capability bit KEYCTL_CAPS1_NS_KEYRING_NAME is set if the kernel is
    employing this feature.

    Signed-off-by: David Howells
    cc: Eric W. Biederman

    David Howells
     
  • Add a 'recurse' flag for keyring searches so that the flag can be omitted
    and recursion disabled, thereby allowing just the nominated keyring to be
    searched and none of the children.

    Signed-off-by: David Howells

    David Howells
     
  • Cache the hash of the key's type and description in the index key so that
    we're not recalculating it every time we look at a key during a search.
    The hash function does a bunch of multiplications, so evading those is
    probably worthwhile - especially as this is done for every key examined
    during a search.

    This also allows the methods used by assoc_array to get chunks of index-key
    to be simplified.

    Signed-off-by: David Howells

    David Howells
     
  • Simplify key description management by cramming the word containing the
    length with the first few chars of the description also. This simplifies
    the code that generates the index-key used by assoc_array. It should speed
    up key searching a bit too.

    Signed-off-by: David Howells

    David Howells
     
  • Kill off request_key_async{,_with_auxdata}() as they're not currently used.

    Signed-off-by: David Howells

    David Howells
     

19 Jun, 2019

1 commit

  • Provide a request_key_rcu() function that can be used to request a key
    under RCU conditions. It can only search and check permissions; it cannot
    allocate a new key, upcall or wait for an upcall to complete. It may
    return a partially constructed key.

    Signed-off-by: David Howells

    David Howells
     

31 May, 2019

2 commits

  • Add a keyctl to atomically move a link to a key from one keyring to
    another. The key must exist in "from" keyring and a flag can be given to
    cause the operation to fail if there's a matching key already in the "to"
    keyring.

    This can be done with:

    keyctl(KEYCTL_MOVE,
    key_serial_t key,
    key_serial_t from_keyring,
    key_serial_t to_keyring,
    unsigned int flags);

    The key being moved must grant Link permission and both keyrings must grant
    Write permission.

    flags should be 0 or KEYCTL_MOVE_EXCL, with the latter preventing
    displacement of a matching key from the "to" keyring.

    Signed-off-by: David Howells

    David Howells
     
  • Based on 1 normalized pattern(s):

    this program is free software you can redistribute it and or modify
    it under the terms of the gnu general public license as published by
    the free software foundation either version 2 of the license or at
    your option any later version

    extracted by the scancode license scanner the SPDX license identifier

    GPL-2.0-or-later

    has been chosen to replace the boilerplate/reference in 3029 file(s).

    Signed-off-by: Thomas Gleixner
    Reviewed-by: Allison Randal
    Cc: linux-spdx@vger.kernel.org
    Link: https://lkml.kernel.org/r/20190527070032.746973796@linutronix.de
    Signed-off-by: Greg Kroah-Hartman

    Thomas Gleixner
     

22 May, 2019

1 commit

  • Sparse warnings are incurred by key_fs[ug]id_changed() due to unprotected
    accesses of tsk->cred, which is marked __rcu.

    Fix this by passing the new cred struct to these functions from
    commit_creds() rather than the task pointer.

    Signed-off-by: David Howells
    Reviewed-by: James Morris

    David Howells
     

14 Dec, 2018

1 commit


16 Nov, 2017

1 commit

  • The 'struct key' will use 'time_t' which we try to remove in the
    kernel, since 'time_t' is not year 2038 safe on 32bit systems.
    Also the 'struct keyring_search_context' will use 'timespec' type
    to record current time, which is also not year 2038 safe on 32bit
    systems.

    Thus this patch replaces 'time_t' with 'time64_t' which is year 2038
    safe for 'struct key', and replace 'timespec' with 'time64_t' for the
    'struct keyring_search_context', since we only look at the the seconds
    part of 'timespec' variable. Moreover we also change the codes where
    using the 'time_t' and 'timespec', and we can get current time by
    ktime_get_real_seconds() instead of current_kernel_time(), and use
    'TIME64_MAX' macro to initialize the 'time64_t' type variable.

    Especially in proc.c file, we have replaced 'unsigned long' and 'timespec'
    type with 'u64' and 'time64_t' type to save the timeout value, which means
    user will get one 'u64' type timeout value by issuing proc_keys_show()
    function.

    Signed-off-by: Baolin Wang
    Reviewed-by: Arnd Bergmann
    Signed-off-by: David Howells
    Reviewed-by: James Morris

    Baolin Wang
     

18 Oct, 2017

1 commit

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

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

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

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

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

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

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

    Additionally, barriering is included:

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

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

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

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

    David Howells
     

25 Sep, 2017

1 commit

  • It was possible for an unprivileged user to create the user and user
    session keyrings for another user. For example:

    sudo -u '#3000' sh -c 'keyctl add keyring _uid.4000 "" @u
    keyctl add keyring _uid_ses.4000 "" @u
    sleep 15' &
    sleep 1
    sudo -u '#4000' keyctl describe @u
    sudo -u '#4000' keyctl describe @us

    This is problematic because these "fake" keyrings won't have the right
    permissions. In particular, the user who created them first will own
    them and will have full access to them via the possessor permissions,
    which can be used to compromise the security of a user's keys:

    -4: alswrv-----v------------ 3000 0 keyring: _uid.4000
    -5: alswrv-----v------------ 3000 0 keyring: _uid_ses.4000

    Fix it by marking user and user session keyrings with a flag
    KEY_FLAG_UID_KEYRING. Then, when searching for a user or user session
    keyring by name, skip all keyrings that don't have the flag set.

    Fixes: 69664cf16af4 ("keys: don't generate user and user session keyrings unless they're accessed")
    Cc: [v2.6.26+]
    Signed-off-by: Eric Biggers
    Signed-off-by: David Howells

    Eric Biggers
     

04 Jul, 2017

1 commit

  • Pull documentation updates from Jonathan Corbet:
    "There has been a fair amount of activity in the docs tree this time
    around. Highlights include:

    - Conversion of a bunch of security documentation into RST

    - The conversion of the remaining DocBook templates by The Amazing
    Mauro Machine. We can now drop the entire DocBook build chain.

    - The usual collection of fixes and minor updates"

    * tag 'docs-4.13' of git://git.lwn.net/linux: (90 commits)
    scripts/kernel-doc: handle DECLARE_HASHTABLE
    Documentation: atomic_ops.txt is core-api/atomic_ops.rst
    Docs: clean up some DocBook loose ends
    Make the main documentation title less Geocities
    Docs: Use kernel-figure in vidioc-g-selection.rst
    Docs: fix table problems in ras.rst
    Docs: Fix breakage with Sphinx 1.5 and upper
    Docs: Include the Latex "ifthen" package
    doc/kokr/howto: Only send regression fixes after -rc1
    docs-rst: fix broken links to dynamic-debug-howto in kernel-parameters
    doc: Document suitability of IBM Verse for kernel development
    Doc: fix a markup error in coding-style.rst
    docs: driver-api: i2c: remove some outdated information
    Documentation: DMA API: fix a typo in a function name
    Docs: Insert missing space to separate link from text
    doc/ko_KR/memory-barriers: Update control-dependencies example
    Documentation, kbuild: fix typo "minimun" -> "minimum"
    docs: Fix some formatting issues in request-key.rst
    doc: ReSTify keys-trusted-encrypted.txt
    doc: ReSTify keys-request-key.txt
    ...

    Linus Torvalds
     

09 Jun, 2017

1 commit

  • While a 'struct key' itself normally does not contain sensitive
    information, Documentation/security/keys.txt actually encourages this:

    "Having a payload is not required; and the payload can, in fact,
    just be a value stored in the struct key itself."

    In case someone has taken this advice, or will take this advice in the
    future, zero the key structure before freeing it. We might as well, and
    as a bonus this could make it a bit more difficult for an adversary to
    determine which keys have recently been in use.

    This is safe because the key_jar cache does not use a constructor.

    Signed-off-by: Eric Biggers
    Signed-off-by: David Howells
    Signed-off-by: James Morris

    Eric Biggers
     

19 May, 2017

1 commit

  • This creates a new section in the security development index for kernel
    keys, and adjusts for ReST markup.

    Cc: David Howells
    Signed-off-by: Kees Cook
    Signed-off-by: Jonathan Corbet

    Kees Cook
     

05 Apr, 2017

2 commits

  • Keyrings recently gained restrict_link capabilities that allow
    individual keys to be validated prior to linking. This functionality
    was only available using internal kernel APIs.

    With the KEYCTL_RESTRICT_KEYRING command existing keyrings can be
    configured to check the content of keys before they are linked, and
    then allow or disallow linkage of that key to the keyring.

    To restrict a keyring, call:

    keyctl(KEYCTL_RESTRICT_KEYRING, key_serial_t keyring, const char *type,
    const char *restriction)

    where 'type' is the name of a registered key type and 'restriction' is a
    string describing how key linkage is to be restricted. The restriction
    option syntax is specific to each key type.

    Signed-off-by: Mat Martineau

    Mat Martineau
     
  • Replace struct key's restrict_link function pointer with a pointer to
    the new struct key_restriction. The structure contains pointers to the
    restriction function as well as relevant data for evaluating the
    restriction.

    The garbage collector checks restrict_link->keytype when key types are
    unregistered. Restrictions involving a removed key type are converted
    to use restrict_link_reject so that restrictions cannot be removed by
    unregistering key types.

    Signed-off-by: Mat Martineau

    Mat Martineau
     

04 Apr, 2017

3 commits

  • Key link restrictions require restriction-specific data as well as a
    restriction-specific function pointer. As a first step toward replacing
    the restrict_link pointer in struct key, define a more general
    key_restriction structure that captures the required function, key, and
    key type pointers. Key type modules should not be pinned on account of
    this key type pointer because the pointer will be cleared by the garbage
    collector if the key type is unregistered.

    Signed-off-by: Mat Martineau

    Mat Martineau
     
  • The first argument to the restrict_link_func_t functions was a keyring
    pointer. These functions are called by the key subsystem with this
    argument set to the destination keyring, but restrict_link_by_signature
    expects a pointer to the relevant trusted keyring.

    Restrict functions may need something other than a single struct key
    pointer to allow or reject key linkage, so the data used to make that
    decision (such as the trust keyring) is moved to a new, fourth
    argument. The first argument is now always the destination keyring.

    Signed-off-by: Mat Martineau

    Mat Martineau
     
  • This pointer type needs to be returned from a lookup function, and
    without a typedef the syntax gets cumbersome.

    Signed-off-by: Mat Martineau

    Mat Martineau
     

03 Apr, 2017

1 commit

  • refcount_t type and corresponding API should be
    used instead of atomic_t when the variable is used as
    a reference counter. This allows to avoid accidental
    refcounter overflows that might lead to use-after-free
    situations.

    Signed-off-by: Elena Reshetova
    Signed-off-by: Hans Liljestrand
    Signed-off-by: Kees Cook
    Signed-off-by: David Windsor
    Acked-by: David Howells
    Signed-off-by: James Morris

    Elena Reshetova
     

02 Mar, 2017

1 commit

  • 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: [] 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: Jan Stancek
    Signed-off-by: David Howells
    Tested-by: Jan Stancek
    Signed-off-by: James Morris

    David Howells
     

12 Apr, 2016

2 commits

  • Remove KEY_FLAG_TRUSTED and KEY_ALLOC_TRUSTED as they're no longer
    meaningful. Also we can drop the trusted flag from the preparse structure.

    Given this, we no longer need to pass the key flags through to
    restrict_link().

    Further, we can now get rid of keyring_restrict_trusted_only() also.

    Signed-off-by: David Howells

    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: David Howells
    Reviewed-by: Mimi Zohar

    David Howells
     

10 Feb, 2016

1 commit


15 Dec, 2015

1 commit

  • Userspace should not be allowed to remove keys from certain keyrings
    (eg. blacklist), though the keys themselves can expire.

    This patch defines a new key flag named KEY_FLAG_KEEP to prevent
    userspace from being able to unlink, revoke, invalidate or timed
    out a key on a keyring. When this flag is set on the keyring, all
    keys subsequently added are flagged.

    In addition, when this flag is set, the keyring itself can not be
    cleared.

    Signed-off-by: Mimi Zohar
    Cc: David Howells

    Mimi Zohar