diff options
| author | David Howells <dhowells@redhat.com> | 2005-10-07 10:04:52 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-10-08 17:53:31 -0400 |
| commit | f1a9badcf6ecad9975240d94514721cb93932151 (patch) | |
| tree | dc37fe427d645dd84331b7385523b39efa41ffad /Documentation | |
| parent | 74fd92c511bd4a0771ac0faaaef38bb1be3a29f6 (diff) | |
[PATCH] Keys: Add request-key process documentation
The attached patch adds documentation for the process by which request-key
works, including how it permits helper processes to gain access to the
requestor's keyrings.
Signed-Off-By: David Howells <dhowells@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'Documentation')
| -rw-r--r-- | Documentation/keys-request-key.txt | 161 | ||||
| -rw-r--r-- | Documentation/keys.txt | 18 |
2 files changed, 172 insertions, 7 deletions
diff --git a/Documentation/keys-request-key.txt b/Documentation/keys-request-key.txt new file mode 100644 index 000000000000..5f2b9c5edbb5 --- /dev/null +++ b/Documentation/keys-request-key.txt | |||
| @@ -0,0 +1,161 @@ | |||
| 1 | =================== | ||
| 2 | KEY REQUEST SERVICE | ||
| 3 | =================== | ||
| 4 | |||
| 5 | The key request service is part of the key retention service (refer to | ||
| 6 | Documentation/keys.txt). This document explains more fully how that the | ||
| 7 | requesting algorithm works. | ||
| 8 | |||
| 9 | The process starts by either the kernel requesting a service by calling | ||
| 10 | request_key(): | ||
| 11 | |||
| 12 | struct key *request_key(const struct key_type *type, | ||
| 13 | const char *description, | ||
| 14 | const char *callout_string); | ||
| 15 | |||
| 16 | Or by userspace invoking the request_key system call: | ||
| 17 | |||
| 18 | key_serial_t request_key(const char *type, | ||
| 19 | const char *description, | ||
| 20 | const char *callout_info, | ||
| 21 | key_serial_t dest_keyring); | ||
| 22 | |||
| 23 | The main difference between the two access points is that the in-kernel | ||
| 24 | interface does not need to link the key to a keyring to prevent it from being | ||
| 25 | immediately destroyed. The kernel interface returns a pointer directly to the | ||
| 26 | key, and it's up to the caller to destroy the key. | ||
| 27 | |||
| 28 | The userspace interface links the key to a keyring associated with the process | ||
| 29 | to prevent the key from going away, and returns the serial number of the key to | ||
| 30 | the caller. | ||
| 31 | |||
| 32 | |||
| 33 | =========== | ||
| 34 | THE PROCESS | ||
| 35 | =========== | ||
| 36 | |||
| 37 | A request proceeds in the following manner: | ||
| 38 | |||
| 39 | (1) Process A calls request_key() [the userspace syscall calls the kernel | ||
| 40 | interface]. | ||
| 41 | |||
| 42 | (2) request_key() searches the process's subscribed keyrings to see if there's | ||
| 43 | a suitable key there. If there is, it returns the key. If there isn't, and | ||
| 44 | callout_info is not set, an error is returned. Otherwise the process | ||
| 45 | proceeds to the next step. | ||
| 46 | |||
| 47 | (3) request_key() sees that A doesn't have the desired key yet, so it creates | ||
| 48 | two things: | ||
| 49 | |||
| 50 | (a) An uninstantiated key U of requested type and description. | ||
| 51 | |||
| 52 | (b) An authorisation key V that refers to key U and notes that process A | ||
| 53 | is the context in which key U should be instantiated and secured, and | ||
| 54 | from which associated key requests may be satisfied. | ||
| 55 | |||
| 56 | (4) request_key() then forks and executes /sbin/request-key with a new session | ||
| 57 | keyring that contains a link to auth key V. | ||
| 58 | |||
| 59 | (5) /sbin/request-key execs an appropriate program to perform the actual | ||
| 60 | instantiation. | ||
| 61 | |||
| 62 | (6) The program may want to access another key from A's context (say a | ||
| 63 | Kerberos TGT key). It just requests the appropriate key, and the keyring | ||
| 64 | search notes that the session keyring has auth key V in its bottom level. | ||
| 65 | |||
| 66 | This will permit it to then search the keyrings of process A with the | ||
| 67 | UID, GID, groups and security info of process A as if it was process A, | ||
| 68 | and come up with key W. | ||
| 69 | |||
| 70 | (7) The program then does what it must to get the data with which to | ||
| 71 | instantiate key U, using key W as a reference (perhaps it contacts a | ||
| 72 | Kerberos server using the TGT) and then instantiates key U. | ||
| 73 | |||
| 74 | (8) Upon instantiating key U, auth key V is automatically revoked so that it | ||
| 75 | may not be used again. | ||
| 76 | |||
| 77 | (9) The program then exits 0 and request_key() deletes key V and returns key | ||
| 78 | U to the caller. | ||
| 79 | |||
| 80 | This also extends further. If key W (step 5 above) didn't exist, key W would be | ||
| 81 | created uninstantiated, another auth key (X) would be created [as per step 3] | ||
| 82 | and another copy of /sbin/request-key spawned [as per step 4]; but the context | ||
| 83 | specified by auth key X will still be process A, as it was in auth key V. | ||
| 84 | |||
| 85 | This is because process A's keyrings can't simply be attached to | ||
| 86 | /sbin/request-key at the appropriate places because (a) execve will discard two | ||
| 87 | of them, and (b) it requires the same UID/GID/Groups all the way through. | ||
| 88 | |||
| 89 | |||
| 90 | ====================== | ||
| 91 | NEGATIVE INSTANTIATION | ||
| 92 | ====================== | ||
| 93 | |||
| 94 | Rather than instantiating a key, it is possible for the possessor of an | ||
| 95 | authorisation key to negatively instantiate a key that's under construction. | ||
| 96 | This is a short duration placeholder that causes any attempt at re-requesting | ||
| 97 | the key whilst it exists to fail with error ENOKEY. | ||
| 98 | |||
| 99 | This is provided to prevent excessive repeated spawning of /sbin/request-key | ||
| 100 | processes for a key that will never be obtainable. | ||
| 101 | |||
| 102 | Should the /sbin/request-key process exit anything other than 0 or die on a | ||
| 103 | signal, the key under construction will be automatically negatively | ||
| 104 | instantiated for a short amount of time. | ||
| 105 | |||
| 106 | |||
| 107 | ==================== | ||
| 108 | THE SEARCH ALGORITHM | ||
| 109 | ==================== | ||
| 110 | |||
| 111 | A search of any particular keyring proceeds in the following fashion: | ||
| 112 | |||
| 113 | (1) When the key management code searches for a key (keyring_search_aux) it | ||
| 114 | firstly calls key_permission(SEARCH) on the keyring it's starting with, | ||
| 115 | if this denies permission, it doesn't search further. | ||
| 116 | |||
| 117 | (2) It considers all the non-keyring keys within that keyring and, if any key | ||
| 118 | matches the criteria specified, calls key_permission(SEARCH) on it to see | ||
| 119 | if the key is allowed to be found. If it is, that key is returned; if | ||
| 120 | not, the search continues, and the error code is retained if of higher | ||
| 121 | priority than the one currently set. | ||
| 122 | |||
| 123 | (3) It then considers all the keyring-type keys in the keyring it's currently | ||
| 124 | searching. It calls key_permission(SEARCH) on each keyring, and if this | ||
| 125 | grants permission, it recurses, executing steps (2) and (3) on that | ||
| 126 | keyring. | ||
| 127 | |||
| 128 | The process stops immediately a valid key is found with permission granted to | ||
| 129 | use it. Any error from a previous match attempt is discarded and the key is | ||
| 130 | returned. | ||
| 131 | |||
| 132 | When search_process_keyrings() is invoked, it performs the following searches | ||
| 133 | until one succeeds: | ||
| 134 | |||
| 135 | (1) If extant, the process's thread keyring is searched. | ||
| 136 | |||
| 137 | (2) If extant, the process's process keyring is searched. | ||
| 138 | |||
| 139 | (3) The process's session keyring is searched. | ||
| 140 | |||
| 141 | (4) If the process has a request_key() authorisation key in its session | ||
| 142 | keyring then: | ||
| 143 | |||
| 144 | (a) If extant, the calling process's thread keyring is searched. | ||
| 145 | |||
| 146 | (b) If extant, the calling process's process keyring is searched. | ||
| 147 | |||
| 148 | (c) The calling process's session keyring is searched. | ||
| 149 | |||
| 150 | The moment one succeeds, all pending errors are discarded and the found key is | ||
| 151 | returned. | ||
| 152 | |||
| 153 | Only if all these fail does the whole thing fail with the highest priority | ||
| 154 | error. Note that several errors may have come from LSM. | ||
| 155 | |||
| 156 | The error priority is: | ||
| 157 | |||
| 158 | EKEYREVOKED > EKEYEXPIRED > ENOKEY | ||
| 159 | |||
| 160 | EACCES/EPERM are only returned on a direct search of a specific keyring where | ||
| 161 | the basal keyring does not grant Search permission. | ||
diff --git a/Documentation/keys.txt b/Documentation/keys.txt index b22e7c8d059a..4afe03a58c5b 100644 --- a/Documentation/keys.txt +++ b/Documentation/keys.txt | |||
| @@ -361,6 +361,8 @@ The main syscalls are: | |||
| 361 | /sbin/request-key will be invoked in an attempt to obtain a key. The | 361 | /sbin/request-key will be invoked in an attempt to obtain a key. The |
| 362 | callout_info string will be passed as an argument to the program. | 362 | callout_info string will be passed as an argument to the program. |
| 363 | 363 | ||
| 364 | See also Documentation/keys-request-key.txt. | ||
| 365 | |||
| 364 | 366 | ||
| 365 | The keyctl syscall functions are: | 367 | The keyctl syscall functions are: |
| 366 | 368 | ||
| @@ -533,8 +535,8 @@ The keyctl syscall functions are: | |||
| 533 | 535 | ||
| 534 | (*) Read the payload data from a key: | 536 | (*) Read the payload data from a key: |
| 535 | 537 | ||
| 536 | key_serial_t keyctl(KEYCTL_READ, key_serial_t keyring, char *buffer, | 538 | long keyctl(KEYCTL_READ, key_serial_t keyring, char *buffer, |
| 537 | size_t buflen); | 539 | size_t buflen); |
| 538 | 540 | ||
| 539 | This function attempts to read the payload data from the specified key | 541 | This function attempts to read the payload data from the specified key |
| 540 | into the buffer. The process must have read permission on the key to | 542 | into the buffer. The process must have read permission on the key to |
| @@ -555,9 +557,9 @@ The keyctl syscall functions are: | |||
| 555 | 557 | ||
| 556 | (*) Instantiate a partially constructed key. | 558 | (*) Instantiate a partially constructed key. |
| 557 | 559 | ||
| 558 | key_serial_t keyctl(KEYCTL_INSTANTIATE, key_serial_t key, | 560 | long keyctl(KEYCTL_INSTANTIATE, key_serial_t key, |
| 559 | const void *payload, size_t plen, | 561 | const void *payload, size_t plen, |
| 560 | key_serial_t keyring); | 562 | key_serial_t keyring); |
| 561 | 563 | ||
| 562 | If the kernel calls back to userspace to complete the instantiation of a | 564 | If the kernel calls back to userspace to complete the instantiation of a |
| 563 | key, userspace should use this call to supply data for the key before the | 565 | key, userspace should use this call to supply data for the key before the |
| @@ -576,8 +578,8 @@ The keyctl syscall functions are: | |||
| 576 | 578 | ||
| 577 | (*) Negatively instantiate a partially constructed key. | 579 | (*) Negatively instantiate a partially constructed key. |
| 578 | 580 | ||
| 579 | key_serial_t keyctl(KEYCTL_NEGATE, key_serial_t key, | 581 | long keyctl(KEYCTL_NEGATE, key_serial_t key, |
| 580 | unsigned timeout, key_serial_t keyring); | 582 | unsigned timeout, key_serial_t keyring); |
| 581 | 583 | ||
| 582 | If the kernel calls back to userspace to complete the instantiation of a | 584 | If the kernel calls back to userspace to complete the instantiation of a |
| 583 | key, userspace should use this call mark the key as negative before the | 585 | key, userspace should use this call mark the key as negative before the |
| @@ -688,6 +690,8 @@ payload contents" for more information. | |||
| 688 | If successful, the key will have been attached to the default keyring for | 690 | If successful, the key will have been attached to the default keyring for |
| 689 | implicitly obtained request-key keys, as set by KEYCTL_SET_REQKEY_KEYRING. | 691 | implicitly obtained request-key keys, as set by KEYCTL_SET_REQKEY_KEYRING. |
| 690 | 692 | ||
| 693 | See also Documentation/keys-request-key.txt. | ||
| 694 | |||
| 691 | 695 | ||
| 692 | (*) When it is no longer required, the key should be released using: | 696 | (*) When it is no longer required, the key should be released using: |
| 693 | 697 | ||
