diff options
author | David Howells <dhowells@redhat.com> | 2005-06-24 01:00:49 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-06-24 03:05:18 -0400 |
commit | 76d8aeabfeb1c42641a81c44280177b9a08670d8 (patch) | |
tree | 0a584439bb44e440717aa77a1398ba9eea24a137 | |
parent | 7286aa9b9ab35f20b1ff16d867f4535701df99b5 (diff) |
[PATCH] keys: Discard key spinlock and use RCU for key payload
The attached patch changes the key implementation in a number of ways:
(1) It removes the spinlock from the key structure.
(2) The key flags are now accessed using atomic bitops instead of
write-locking the key spinlock and using C bitwise operators.
The three instantiation flags are dealt with with the construction
semaphore held during the request_key/instantiate/negate sequence, thus
rendering the spinlock superfluous.
The key flags are also now bit numbers not bit masks.
(3) The key payload is now accessed using RCU. This permits the recursive
keyring search algorithm to be simplified greatly since no locks need be
taken other than the usual RCU preemption disablement. Searching now does
not require any locks or semaphores to be held; merely that the starting
keyring be pinned.
(4) The keyring payload now includes an RCU head so that it can be disposed
of by call_rcu(). This requires that the payload be copied on unlink to
prevent introducing races in copy-down vs search-up.
(5) The user key payload is now a structure with the data following it. It
includes an RCU head like the keyring payload and for the same reason. It
also contains a data length because the data length in the key may be
changed on another CPU whilst an RCU protected read is in progress on the
payload. This would then see the supposed RCU payload and the on-key data
length getting out of sync.
I'm tempted to drop the key's datalen entirely, except that it's used in
conjunction with quota management and so is a little tricky to get rid
of.
(6) Update the keys documentation.
Signed-Off-By: David Howells <dhowells@redhat.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | Documentation/keys.txt | 285 | ||||
-rw-r--r-- | include/linux/key-ui.h | 6 | ||||
-rw-r--r-- | include/linux/key.h | 25 | ||||
-rw-r--r-- | security/keys/key.c | 94 | ||||
-rw-r--r-- | security/keys/keyctl.c | 23 | ||||
-rw-r--r-- | security/keys/keyring.c | 245 | ||||
-rw-r--r-- | security/keys/proc.c | 21 | ||||
-rw-r--r-- | security/keys/process_keys.c | 12 | ||||
-rw-r--r-- | security/keys/request_key.c | 32 | ||||
-rw-r--r-- | security/keys/user_defined.c | 85 |
10 files changed, 480 insertions, 348 deletions
diff --git a/Documentation/keys.txt b/Documentation/keys.txt index 36d80aeeaf2..3df40c1fe15 100644 --- a/Documentation/keys.txt +++ b/Documentation/keys.txt | |||
@@ -22,6 +22,7 @@ This document has the following sections: | |||
22 | - New procfs files | 22 | - New procfs files |
23 | - Userspace system call interface | 23 | - Userspace system call interface |
24 | - Kernel services | 24 | - Kernel services |
25 | - Notes on accessing payload contents | ||
25 | - Defining a key type | 26 | - Defining a key type |
26 | - Request-key callback service | 27 | - Request-key callback service |
27 | - Key access filesystem | 28 | - Key access filesystem |
@@ -45,27 +46,26 @@ Each key has a number of attributes: | |||
45 | - State. | 46 | - State. |
46 | 47 | ||
47 | 48 | ||
48 | (*) Each key is issued a serial number of type key_serial_t that is unique | 49 | (*) Each key is issued a serial number of type key_serial_t that is unique for |
49 | for the lifetime of that key. All serial numbers are positive non-zero | 50 | the lifetime of that key. All serial numbers are positive non-zero 32-bit |
50 | 32-bit integers. | 51 | integers. |
51 | 52 | ||
52 | Userspace programs can use a key's serial numbers as a way to gain access | 53 | Userspace programs can use a key's serial numbers as a way to gain access |
53 | to it, subject to permission checking. | 54 | to it, subject to permission checking. |
54 | 55 | ||
55 | (*) Each key is of a defined "type". Types must be registered inside the | 56 | (*) Each key is of a defined "type". Types must be registered inside the |
56 | kernel by a kernel service (such as a filesystem) before keys of that | 57 | kernel by a kernel service (such as a filesystem) before keys of that type |
57 | type can be added or used. Userspace programs cannot define new types | 58 | can be added or used. Userspace programs cannot define new types directly. |
58 | directly. | ||
59 | 59 | ||
60 | Key types are represented in the kernel by struct key_type. This defines | 60 | Key types are represented in the kernel by struct key_type. This defines a |
61 | a number of operations that can be performed on a key of that type. | 61 | number of operations that can be performed on a key of that type. |
62 | 62 | ||
63 | Should a type be removed from the system, all the keys of that type will | 63 | Should a type be removed from the system, all the keys of that type will |
64 | be invalidated. | 64 | be invalidated. |
65 | 65 | ||
66 | (*) Each key has a description. This should be a printable string. The key | 66 | (*) Each key has a description. This should be a printable string. The key |
67 | type provides an operation to perform a match between the description on | 67 | type provides an operation to perform a match between the description on a |
68 | a key and a criterion string. | 68 | key and a criterion string. |
69 | 69 | ||
70 | (*) Each key has an owner user ID, a group ID and a permissions mask. These | 70 | (*) Each key has an owner user ID, a group ID and a permissions mask. These |
71 | are used to control what a process may do to a key from userspace, and | 71 | are used to control what a process may do to a key from userspace, and |
@@ -74,10 +74,10 @@ Each key has a number of attributes: | |||
74 | (*) Each key can be set to expire at a specific time by the key type's | 74 | (*) Each key can be set to expire at a specific time by the key type's |
75 | instantiation function. Keys can also be immortal. | 75 | instantiation function. Keys can also be immortal. |
76 | 76 | ||
77 | (*) Each key can have a payload. This is a quantity of data that represent | 77 | (*) Each key can have a payload. This is a quantity of data that represent the |
78 | the actual "key". In the case of a keyring, this is a list of keys to | 78 | actual "key". In the case of a keyring, this is a list of keys to which |
79 | which the keyring links; in the case of a user-defined key, it's an | 79 | the keyring links; in the case of a user-defined key, it's an arbitrary |
80 | arbitrary blob of data. | 80 | blob of data. |
81 | 81 | ||
82 | Having a payload is not required; and the payload can, in fact, just be a | 82 | Having a payload is not required; and the payload can, in fact, just be a |
83 | value stored in the struct key itself. | 83 | value stored in the struct key itself. |
@@ -92,8 +92,8 @@ Each key has a number of attributes: | |||
92 | 92 | ||
93 | (*) Each key can be in one of a number of basic states: | 93 | (*) Each key can be in one of a number of basic states: |
94 | 94 | ||
95 | (*) Uninstantiated. The key exists, but does not have any data | 95 | (*) Uninstantiated. The key exists, but does not have any data attached. |
96 | attached. Keys being requested from userspace will be in this state. | 96 | Keys being requested from userspace will be in this state. |
97 | 97 | ||
98 | (*) Instantiated. This is the normal state. The key is fully formed, and | 98 | (*) Instantiated. This is the normal state. The key is fully formed, and |
99 | has data attached. | 99 | has data attached. |
@@ -140,10 +140,10 @@ The key service provides a number of features besides keys: | |||
140 | clone, fork, vfork or execve occurs. A new keyring is created only when | 140 | clone, fork, vfork or execve occurs. A new keyring is created only when |
141 | required. | 141 | required. |
142 | 142 | ||
143 | The process-specific keyring is replaced with an empty one in the child | 143 | The process-specific keyring is replaced with an empty one in the child on |
144 | on clone, fork, vfork unless CLONE_THREAD is supplied, in which case it | 144 | clone, fork, vfork unless CLONE_THREAD is supplied, in which case it is |
145 | is shared. execve also discards the process's process keyring and creates | 145 | shared. execve also discards the process's process keyring and creates a |
146 | a new one. | 146 | new one. |
147 | 147 | ||
148 | The session-specific keyring is persistent across clone, fork, vfork and | 148 | The session-specific keyring is persistent across clone, fork, vfork and |
149 | execve, even when the latter executes a set-UID or set-GID binary. A | 149 | execve, even when the latter executes a set-UID or set-GID binary. A |
@@ -177,11 +177,11 @@ The key service provides a number of features besides keys: | |||
177 | If a system call that modifies a key or keyring in some way would put the | 177 | If a system call that modifies a key or keyring in some way would put the |
178 | user over quota, the operation is refused and error EDQUOT is returned. | 178 | user over quota, the operation is refused and error EDQUOT is returned. |
179 | 179 | ||
180 | (*) There's a system call interface by which userspace programs can create | 180 | (*) There's a system call interface by which userspace programs can create and |
181 | and manipulate keys and keyrings. | 181 | manipulate keys and keyrings. |
182 | 182 | ||
183 | (*) There's a kernel interface by which services can register types and | 183 | (*) There's a kernel interface by which services can register types and search |
184 | search for keys. | 184 | for keys. |
185 | 185 | ||
186 | (*) There's a way for the a search done from the kernel to call back to | 186 | (*) There's a way for the a search done from the kernel to call back to |
187 | userspace to request a key that can't be found in a process's keyrings. | 187 | userspace to request a key that can't be found in a process's keyrings. |
@@ -194,9 +194,9 @@ The key service provides a number of features besides keys: | |||
194 | KEY ACCESS PERMISSIONS | 194 | KEY ACCESS PERMISSIONS |
195 | ====================== | 195 | ====================== |
196 | 196 | ||
197 | Keys have an owner user ID, a group access ID, and a permissions mask. The | 197 | Keys have an owner user ID, a group access ID, and a permissions mask. The mask |
198 | mask has up to eight bits each for user, group and other access. Only five of | 198 | has up to eight bits each for user, group and other access. Only five of each |
199 | each set of eight bits are defined. These permissions granted are: | 199 | set of eight bits are defined. These permissions granted are: |
200 | 200 | ||
201 | (*) View | 201 | (*) View |
202 | 202 | ||
@@ -210,8 +210,8 @@ each set of eight bits are defined. These permissions granted are: | |||
210 | 210 | ||
211 | (*) Write | 211 | (*) Write |
212 | 212 | ||
213 | This permits a key's payload to be instantiated or updated, or it allows | 213 | This permits a key's payload to be instantiated or updated, or it allows a |
214 | a link to be added to or removed from a keyring. | 214 | link to be added to or removed from a keyring. |
215 | 215 | ||
216 | (*) Search | 216 | (*) Search |
217 | 217 | ||
@@ -238,8 +238,8 @@ about the status of the key service: | |||
238 | (*) /proc/keys | 238 | (*) /proc/keys |
239 | 239 | ||
240 | This lists all the keys on the system, giving information about their | 240 | This lists all the keys on the system, giving information about their |
241 | type, description and permissions. The payload of the key is not | 241 | type, description and permissions. The payload of the key is not available |
242 | available this way: | 242 | this way: |
243 | 243 | ||
244 | SERIAL FLAGS USAGE EXPY PERM UID GID TYPE DESCRIPTION: SUMMARY | 244 | SERIAL FLAGS USAGE EXPY PERM UID GID TYPE DESCRIPTION: SUMMARY |
245 | 00000001 I----- 39 perm 1f0000 0 0 keyring _uid_ses.0: 1/4 | 245 | 00000001 I----- 39 perm 1f0000 0 0 keyring _uid_ses.0: 1/4 |
@@ -318,21 +318,21 @@ The main syscalls are: | |||
318 | If a key of the same type and description as that proposed already exists | 318 | If a key of the same type and description as that proposed already exists |
319 | in the keyring, this will try to update it with the given payload, or it | 319 | in the keyring, this will try to update it with the given payload, or it |
320 | will return error EEXIST if that function is not supported by the key | 320 | will return error EEXIST if that function is not supported by the key |
321 | type. The process must also have permission to write to the key to be | 321 | type. The process must also have permission to write to the key to be able |
322 | able to update it. The new key will have all user permissions granted and | 322 | to update it. The new key will have all user permissions granted and no |
323 | no group or third party permissions. | 323 | group or third party permissions. |
324 | 324 | ||
325 | Otherwise, this will attempt to create a new key of the specified type | 325 | Otherwise, this will attempt to create a new key of the specified type and |
326 | and description, and to instantiate it with the supplied payload and | 326 | description, and to instantiate it with the supplied payload and attach it |
327 | attach it to the keyring. In this case, an error will be generated if the | 327 | to the keyring. In this case, an error will be generated if the process |
328 | process does not have permission to write to the keyring. | 328 | does not have permission to write to the keyring. |
329 | 329 | ||
330 | The payload is optional, and the pointer can be NULL if not required by | 330 | The payload is optional, and the pointer can be NULL if not required by |
331 | the type. The payload is plen in size, and plen can be zero for an empty | 331 | the type. The payload is plen in size, and plen can be zero for an empty |
332 | payload. | 332 | payload. |
333 | 333 | ||
334 | A new keyring can be generated by setting type "keyring", the keyring | 334 | A new keyring can be generated by setting type "keyring", the keyring name |
335 | name as the description (or NULL) and setting the payload to NULL. | 335 | as the description (or NULL) and setting the payload to NULL. |
336 | 336 | ||
337 | User defined keys can be created by specifying type "user". It is | 337 | User defined keys can be created by specifying type "user". It is |
338 | recommended that a user defined key's description by prefixed with a type | 338 | recommended that a user defined key's description by prefixed with a type |
@@ -369,9 +369,9 @@ The keyctl syscall functions are: | |||
369 | key_serial_t keyctl(KEYCTL_GET_KEYRING_ID, key_serial_t id, | 369 | key_serial_t keyctl(KEYCTL_GET_KEYRING_ID, key_serial_t id, |
370 | int create); | 370 | int create); |
371 | 371 | ||
372 | The special key specified by "id" is looked up (with the key being | 372 | The special key specified by "id" is looked up (with the key being created |
373 | created if necessary) and the ID of the key or keyring thus found is | 373 | if necessary) and the ID of the key or keyring thus found is returned if |
374 | returned if it exists. | 374 | it exists. |
375 | 375 | ||
376 | If the key does not yet exist, the key will be created if "create" is | 376 | If the key does not yet exist, the key will be created if "create" is |
377 | non-zero; and the error ENOKEY will be returned if "create" is zero. | 377 | non-zero; and the error ENOKEY will be returned if "create" is zero. |
@@ -402,8 +402,8 @@ The keyctl syscall functions are: | |||
402 | 402 | ||
403 | This will try to update the specified key with the given payload, or it | 403 | This will try to update the specified key with the given payload, or it |
404 | will return error EOPNOTSUPP if that function is not supported by the key | 404 | will return error EOPNOTSUPP if that function is not supported by the key |
405 | type. The process must also have permission to write to the key to be | 405 | type. The process must also have permission to write to the key to be able |
406 | able to update it. | 406 | to update it. |
407 | 407 | ||
408 | The payload is of length plen, and may be absent or empty as for | 408 | The payload is of length plen, and may be absent or empty as for |
409 | add_key(). | 409 | add_key(). |
@@ -422,8 +422,8 @@ The keyctl syscall functions are: | |||
422 | 422 | ||
423 | long keyctl(KEYCTL_CHOWN, key_serial_t key, uid_t uid, gid_t gid); | 423 | long keyctl(KEYCTL_CHOWN, key_serial_t key, uid_t uid, gid_t gid); |
424 | 424 | ||
425 | This function permits a key's owner and group ID to be changed. Either | 425 | This function permits a key's owner and group ID to be changed. Either one |
426 | one of uid or gid can be set to -1 to suppress that change. | 426 | of uid or gid can be set to -1 to suppress that change. |
427 | 427 | ||
428 | Only the superuser can change a key's owner to something other than the | 428 | Only the superuser can change a key's owner to something other than the |
429 | key's current owner. Similarly, only the superuser can change a key's | 429 | key's current owner. Similarly, only the superuser can change a key's |
@@ -484,12 +484,12 @@ The keyctl syscall functions are: | |||
484 | 484 | ||
485 | long keyctl(KEYCTL_LINK, key_serial_t keyring, key_serial_t key); | 485 | long keyctl(KEYCTL_LINK, key_serial_t keyring, key_serial_t key); |
486 | 486 | ||
487 | This function creates a link from the keyring to the key. The process | 487 | This function creates a link from the keyring to the key. The process must |
488 | must have write permission on the keyring and must have link permission | 488 | have write permission on the keyring and must have link permission on the |
489 | on the key. | 489 | key. |
490 | 490 | ||
491 | Should the keyring not be a keyring, error ENOTDIR will result; and if | 491 | Should the keyring not be a keyring, error ENOTDIR will result; and if the |
492 | the keyring is full, error ENFILE will result. | 492 | keyring is full, error ENFILE will result. |
493 | 493 | ||
494 | The link procedure checks the nesting of the keyrings, returning ELOOP if | 494 | The link procedure checks the nesting of the keyrings, returning ELOOP if |
495 | it appears to deep or EDEADLK if the link would introduce a cycle. | 495 | it appears to deep or EDEADLK if the link would introduce a cycle. |
@@ -503,8 +503,8 @@ The keyctl syscall functions are: | |||
503 | specified key, and removes it if found. Subsequent links to that key are | 503 | specified key, and removes it if found. Subsequent links to that key are |
504 | ignored. The process must have write permission on the keyring. | 504 | ignored. The process must have write permission on the keyring. |
505 | 505 | ||
506 | If the keyring is not a keyring, error ENOTDIR will result; and if the | 506 | If the keyring is not a keyring, error ENOTDIR will result; and if the key |
507 | key is not present, error ENOENT will be the result. | 507 | is not present, error ENOENT will be the result. |
508 | 508 | ||
509 | 509 | ||
510 | (*) Search a keyring tree for a key: | 510 | (*) Search a keyring tree for a key: |
@@ -513,9 +513,9 @@ The keyctl syscall functions are: | |||
513 | const char *type, const char *description, | 513 | const char *type, const char *description, |
514 | key_serial_t dest_keyring); | 514 | key_serial_t dest_keyring); |
515 | 515 | ||
516 | This searches the keyring tree headed by the specified keyring until a | 516 | This searches the keyring tree headed by the specified keyring until a key |
517 | key is found that matches the type and description criteria. Each keyring | 517 | is found that matches the type and description criteria. Each keyring is |
518 | is checked for keys before recursion into its children occurs. | 518 | checked for keys before recursion into its children occurs. |
519 | 519 | ||
520 | The process must have search permission on the top level keyring, or else | 520 | The process must have search permission on the top level keyring, or else |
521 | error EACCES will result. Only keyrings that the process has search | 521 | error EACCES will result. Only keyrings that the process has search |
@@ -549,8 +549,8 @@ The keyctl syscall functions are: | |||
549 | As much of the data as can be fitted into the buffer will be copied to | 549 | As much of the data as can be fitted into the buffer will be copied to |
550 | userspace if the buffer pointer is not NULL. | 550 | userspace if the buffer pointer is not NULL. |
551 | 551 | ||
552 | On a successful return, the function will always return the amount of | 552 | On a successful return, the function will always return the amount of data |
553 | data available rather than the amount copied. | 553 | available rather than the amount copied. |
554 | 554 | ||
555 | 555 | ||
556 | (*) Instantiate a partially constructed key. | 556 | (*) Instantiate a partially constructed key. |
@@ -568,8 +568,8 @@ The keyctl syscall functions are: | |||
568 | it, and the key must be uninstantiated. | 568 | it, and the key must be uninstantiated. |
569 | 569 | ||
570 | If a keyring is specified (non-zero), the key will also be linked into | 570 | If a keyring is specified (non-zero), the key will also be linked into |
571 | that keyring, however all the constraints applying in KEYCTL_LINK apply | 571 | that keyring, however all the constraints applying in KEYCTL_LINK apply in |
572 | in this case too. | 572 | this case too. |
573 | 573 | ||
574 | The payload and plen arguments describe the payload data as for add_key(). | 574 | The payload and plen arguments describe the payload data as for add_key(). |
575 | 575 | ||
@@ -587,8 +587,8 @@ The keyctl syscall functions are: | |||
587 | it, and the key must be uninstantiated. | 587 | it, and the key must be uninstantiated. |
588 | 588 | ||
589 | If a keyring is specified (non-zero), the key will also be linked into | 589 | If a keyring is specified (non-zero), the key will also be linked into |
590 | that keyring, however all the constraints applying in KEYCTL_LINK apply | 590 | that keyring, however all the constraints applying in KEYCTL_LINK apply in |
591 | in this case too. | 591 | this case too. |
592 | 592 | ||
593 | 593 | ||
594 | =============== | 594 | =============== |
@@ -601,17 +601,14 @@ be broken down into two areas: keys and key types. | |||
601 | Dealing with keys is fairly straightforward. Firstly, the kernel service | 601 | Dealing with keys is fairly straightforward. Firstly, the kernel service |
602 | registers its type, then it searches for a key of that type. It should retain | 602 | registers its type, then it searches for a key of that type. It should retain |
603 | the key as long as it has need of it, and then it should release it. For a | 603 | the key as long as it has need of it, and then it should release it. For a |
604 | filesystem or device file, a search would probably be performed during the | 604 | filesystem or device file, a search would probably be performed during the open |
605 | open call, and the key released upon close. How to deal with conflicting keys | 605 | call, and the key released upon close. How to deal with conflicting keys due to |
606 | due to two different users opening the same file is left to the filesystem | 606 | two different users opening the same file is left to the filesystem author to |
607 | author to solve. | 607 | solve. |
608 | 608 | ||
609 | When accessing a key's payload data, key->lock should be at least read locked, | 609 | When accessing a key's payload contents, certain precautions must be taken to |
610 | or else the data may be changed by an update being performed from userspace | 610 | prevent access vs modification races. See the section "Notes on accessing |
611 | whilst the driver or filesystem is trying to access it. If no update method is | 611 | payload contents" for more information. |
612 | supplied, then the key's payload may be accessed without holding a lock as | ||
613 | there is no way to change it, provided it can be guaranteed that the key's | ||
614 | type definition won't go away. | ||
615 | 612 | ||
616 | (*) To search for a key, call: | 613 | (*) To search for a key, call: |
617 | 614 | ||
@@ -690,6 +687,54 @@ type definition won't go away. | |||
690 | void unregister_key_type(struct key_type *type); | 687 | void unregister_key_type(struct key_type *type); |
691 | 688 | ||
692 | 689 | ||
690 | =================================== | ||
691 | NOTES ON ACCESSING PAYLOAD CONTENTS | ||
692 | =================================== | ||
693 | |||
694 | The simplest payload is just a number in key->payload.value. In this case, | ||
695 | there's no need to indulge in RCU or locking when accessing the payload. | ||
696 | |||
697 | More complex payload contents must be allocated and a pointer to them set in | ||
698 | key->payload.data. One of the following ways must be selected to access the | ||
699 | data: | ||
700 | |||
701 | (1) Unmodifyable key type. | ||
702 | |||
703 | If the key type does not have a modify method, then the key's payload can | ||
704 | be accessed without any form of locking, provided that it's known to be | ||
705 | instantiated (uninstantiated keys cannot be "found"). | ||
706 | |||
707 | (2) The key's semaphore. | ||
708 | |||
709 | The semaphore could be used to govern access to the payload and to control | ||
710 | the payload pointer. It must be write-locked for modifications and would | ||
711 | have to be read-locked for general access. The disadvantage of doing this | ||
712 | is that the accessor may be required to sleep. | ||
713 | |||
714 | (3) RCU. | ||
715 | |||
716 | RCU must be used when the semaphore isn't already held; if the semaphore | ||
717 | is held then the contents can't change under you unexpectedly as the | ||
718 | semaphore must still be used to serialise modifications to the key. The | ||
719 | key management code takes care of this for the key type. | ||
720 | |||
721 | However, this means using: | ||
722 | |||
723 | rcu_read_lock() ... rcu_dereference() ... rcu_read_unlock() | ||
724 | |||
725 | to read the pointer, and: | ||
726 | |||
727 | rcu_dereference() ... rcu_assign_pointer() ... call_rcu() | ||
728 | |||
729 | to set the pointer and dispose of the old contents after a grace period. | ||
730 | Note that only the key type should ever modify a key's payload. | ||
731 | |||
732 | Furthermore, an RCU controlled payload must hold a struct rcu_head for the | ||
733 | use of call_rcu() and, if the payload is of variable size, the length of | ||
734 | the payload. key->datalen cannot be relied upon to be consistent with the | ||
735 | payload just dereferenced if the key's semaphore is not held. | ||
736 | |||
737 | |||
693 | =================== | 738 | =================== |
694 | DEFINING A KEY TYPE | 739 | DEFINING A KEY TYPE |
695 | =================== | 740 | =================== |
@@ -717,15 +762,15 @@ The structure has a number of fields, some of which are mandatory: | |||
717 | 762 | ||
718 | int key_payload_reserve(struct key *key, size_t datalen); | 763 | int key_payload_reserve(struct key *key, size_t datalen); |
719 | 764 | ||
720 | With the revised data length. Error EDQUOT will be returned if this is | 765 | With the revised data length. Error EDQUOT will be returned if this is not |
721 | not viable. | 766 | viable. |
722 | 767 | ||
723 | 768 | ||
724 | (*) int (*instantiate)(struct key *key, const void *data, size_t datalen); | 769 | (*) int (*instantiate)(struct key *key, const void *data, size_t datalen); |
725 | 770 | ||
726 | This method is called to attach a payload to a key during construction. | 771 | This method is called to attach a payload to a key during construction. |
727 | The payload attached need not bear any relation to the data passed to | 772 | The payload attached need not bear any relation to the data passed to this |
728 | this function. | 773 | function. |
729 | 774 | ||
730 | If the amount of data attached to the key differs from the size in | 775 | If the amount of data attached to the key differs from the size in |
731 | keytype->def_datalen, then key_payload_reserve() should be called. | 776 | keytype->def_datalen, then key_payload_reserve() should be called. |
@@ -734,38 +779,47 @@ The structure has a number of fields, some of which are mandatory: | |||
734 | The fact that KEY_FLAG_INSTANTIATED is not set in key->flags prevents | 779 | The fact that KEY_FLAG_INSTANTIATED is not set in key->flags prevents |
735 | anything else from gaining access to the key. | 780 | anything else from gaining access to the key. |
736 | 781 | ||
737 | This method may sleep if it wishes. | 782 | It is safe to sleep in this method. |
738 | 783 | ||
739 | 784 | ||
740 | (*) int (*duplicate)(struct key *key, const struct key *source); | 785 | (*) int (*duplicate)(struct key *key, const struct key *source); |
741 | 786 | ||
742 | If this type of key can be duplicated, then this method should be | 787 | If this type of key can be duplicated, then this method should be |
743 | provided. It is called to copy the payload attached to the source into | 788 | provided. It is called to copy the payload attached to the source into the |
744 | the new key. The data length on the new key will have been updated and | 789 | new key. The data length on the new key will have been updated and the |
745 | the quota adjusted already. | 790 | quota adjusted already. |
746 | 791 | ||
747 | This method will be called with the source key's semaphore read-locked to | 792 | This method will be called with the source key's semaphore read-locked to |
748 | prevent its payload from being changed. It is safe to sleep here. | 793 | prevent its payload from being changed, thus RCU constraints need not be |
794 | applied to the source key. | ||
795 | |||
796 | This method does not have to lock the destination key in order to attach a | ||
797 | payload. The fact that KEY_FLAG_INSTANTIATED is not set in key->flags | ||
798 | prevents anything else from gaining access to the key. | ||
799 | |||
800 | It is safe to sleep in this method. | ||
749 | 801 | ||
750 | 802 | ||
751 | (*) int (*update)(struct key *key, const void *data, size_t datalen); | 803 | (*) int (*update)(struct key *key, const void *data, size_t datalen); |
752 | 804 | ||
753 | If this type of key can be updated, then this method should be | 805 | If this type of key can be updated, then this method should be provided. |
754 | provided. It is called to update a key's payload from the blob of data | 806 | It is called to update a key's payload from the blob of data provided. |
755 | provided. | ||
756 | 807 | ||
757 | key_payload_reserve() should be called if the data length might change | 808 | key_payload_reserve() should be called if the data length might change |
758 | before any changes are actually made. Note that if this succeeds, the | 809 | before any changes are actually made. Note that if this succeeds, the type |
759 | type is committed to changing the key because it's already been altered, | 810 | is committed to changing the key because it's already been altered, so all |
760 | so all memory allocation must be done first. | 811 | memory allocation must be done first. |
812 | |||
813 | The key will have its semaphore write-locked before this method is called, | ||
814 | but this only deters other writers; any changes to the key's payload must | ||
815 | be made under RCU conditions, and call_rcu() must be used to dispose of | ||
816 | the old payload. | ||
761 | 817 | ||
762 | key_payload_reserve() should be called with the key->lock write locked, | 818 | key_payload_reserve() should be called before the changes are made, but |
763 | and the changes to the key's attached payload should be made before the | 819 | after all allocations and other potentially failing function calls are |
764 | key is locked. | 820 | made. |
765 | 821 | ||
766 | The key will have its semaphore write-locked before this method is | 822 | It is safe to sleep in this method. |
767 | called. Any changes to the key should be made with the key's rwlock | ||
768 | write-locked also. It is safe to sleep here. | ||
769 | 823 | ||
770 | 824 | ||
771 | (*) int (*match)(const struct key *key, const void *desc); | 825 | (*) int (*match)(const struct key *key, const void *desc); |
@@ -782,12 +836,12 @@ The structure has a number of fields, some of which are mandatory: | |||
782 | 836 | ||
783 | (*) void (*destroy)(struct key *key); | 837 | (*) void (*destroy)(struct key *key); |
784 | 838 | ||
785 | This method is optional. It is called to discard the payload data on a | 839 | This method is optional. It is called to discard the payload data on a key |
786 | key when it is being destroyed. | 840 | when it is being destroyed. |
787 | 841 | ||
788 | This method does not need to lock the key; it can consider the key as | 842 | This method does not need to lock the key to access the payload; it can |
789 | being inaccessible. Note that the key's type may have changed before this | 843 | consider the key as being inaccessible at this time. Note that the key's |
790 | function is called. | 844 | type may have been changed before this function is called. |
791 | 845 | ||
792 | It is not safe to sleep in this method; the caller may hold spinlocks. | 846 | It is not safe to sleep in this method; the caller may hold spinlocks. |
793 | 847 | ||
@@ -797,26 +851,31 @@ The structure has a number of fields, some of which are mandatory: | |||
797 | This method is optional. It is called during /proc/keys reading to | 851 | This method is optional. It is called during /proc/keys reading to |
798 | summarise a key's description and payload in text form. | 852 | summarise a key's description and payload in text form. |
799 | 853 | ||
800 | This method will be called with the key's rwlock read-locked. This will | 854 | This method will be called with the RCU read lock held. rcu_dereference() |
801 | prevent the key's payload and state changing; also the description should | 855 | should be used to read the payload pointer if the payload is to be |
802 | not change. This also means it is not safe to sleep in this method. | 856 | accessed. key->datalen cannot be trusted to stay consistent with the |
857 | contents of the payload. | ||
858 | |||
859 | The description will not change, though the key's state may. | ||
860 | |||
861 | It is not safe to sleep in this method; the RCU read lock is held by the | ||
862 | caller. | ||
803 | 863 | ||
804 | 864 | ||
805 | (*) long (*read)(const struct key *key, char __user *buffer, size_t buflen); | 865 | (*) long (*read)(const struct key *key, char __user *buffer, size_t buflen); |
806 | 866 | ||
807 | This method is optional. It is called by KEYCTL_READ to translate the | 867 | This method is optional. It is called by KEYCTL_READ to translate the |
808 | key's payload into something a blob of data for userspace to deal | 868 | key's payload into something a blob of data for userspace to deal with. |
809 | with. Ideally, the blob should be in the same format as that passed in to | 869 | Ideally, the blob should be in the same format as that passed in to the |
810 | the instantiate and update methods. | 870 | instantiate and update methods. |
811 | 871 | ||
812 | If successful, the blob size that could be produced should be returned | 872 | If successful, the blob size that could be produced should be returned |
813 | rather than the size copied. | 873 | rather than the size copied. |
814 | 874 | ||
815 | This method will be called with the key's semaphore read-locked. This | 875 | This method will be called with the key's semaphore read-locked. This will |
816 | will prevent the key's payload changing. It is not necessary to also | 876 | prevent the key's payload changing. It is not necessary to use RCU locking |
817 | read-lock key->lock when accessing the key's payload. It is safe to sleep | 877 | when accessing the key's payload. It is safe to sleep in this method, such |
818 | in this method, such as might happen when the userspace buffer is | 878 | as might happen when the userspace buffer is accessed. |
819 | accessed. | ||
820 | 879 | ||
821 | 880 | ||
822 | ============================ | 881 | ============================ |
@@ -853,8 +912,8 @@ If it returns with the key remaining in the unconstructed state, the key will | |||
853 | be marked as being negative, it will be added to the session keyring, and an | 912 | be marked as being negative, it will be added to the session keyring, and an |
854 | error will be returned to the key requestor. | 913 | error will be returned to the key requestor. |
855 | 914 | ||
856 | Supplementary information may be provided from whoever or whatever invoked | 915 | Supplementary information may be provided from whoever or whatever invoked this |
857 | this service. This will be passed as the <callout_info> parameter. If no such | 916 | service. This will be passed as the <callout_info> parameter. If no such |
858 | information was made available, then "-" will be passed as this parameter | 917 | information was made available, then "-" will be passed as this parameter |
859 | instead. | 918 | instead. |
860 | 919 | ||
diff --git a/include/linux/key-ui.h b/include/linux/key-ui.h index 60cc7b762e7..159ca8d54e9 100644 --- a/include/linux/key-ui.h +++ b/include/linux/key-ui.h | |||
@@ -31,8 +31,10 @@ extern spinlock_t key_serial_lock; | |||
31 | * subscribed | 31 | * subscribed |
32 | */ | 32 | */ |
33 | struct keyring_list { | 33 | struct keyring_list { |
34 | unsigned maxkeys; /* max keys this list can hold */ | 34 | struct rcu_head rcu; /* RCU deletion hook */ |
35 | unsigned nkeys; /* number of keys currently held */ | 35 | unsigned short maxkeys; /* max keys this list can hold */ |
36 | unsigned short nkeys; /* number of keys currently held */ | ||
37 | unsigned short delkey; /* key to be unlinked by RCU */ | ||
36 | struct key *keys[0]; | 38 | struct key *keys[0]; |
37 | }; | 39 | }; |
38 | 40 | ||
diff --git a/include/linux/key.h b/include/linux/key.h index 6aa46d0e812..2c24ffaca86 100644 --- a/include/linux/key.h +++ b/include/linux/key.h | |||
@@ -18,7 +18,7 @@ | |||
18 | #include <linux/types.h> | 18 | #include <linux/types.h> |
19 | #include <linux/list.h> | 19 | #include <linux/list.h> |
20 | #include <linux/rbtree.h> | 20 | #include <linux/rbtree.h> |
21 | #include <linux/spinlock.h> | 21 | #include <linux/rcupdate.h> |
22 | #include <asm/atomic.h> | 22 | #include <asm/atomic.h> |
23 | 23 | ||
24 | #ifdef __KERNEL__ | 24 | #ifdef __KERNEL__ |
@@ -78,7 +78,6 @@ struct key { | |||
78 | key_serial_t serial; /* key serial number */ | 78 | key_serial_t serial; /* key serial number */ |
79 | struct rb_node serial_node; | 79 | struct rb_node serial_node; |
80 | struct key_type *type; /* type of key */ | 80 | struct key_type *type; /* type of key */ |
81 | rwlock_t lock; /* examination vs change lock */ | ||
82 | struct rw_semaphore sem; /* change vs change sem */ | 81 | struct rw_semaphore sem; /* change vs change sem */ |
83 | struct key_user *user; /* owner of this key */ | 82 | struct key_user *user; /* owner of this key */ |
84 | time_t expiry; /* time at which key expires (or 0) */ | 83 | time_t expiry; /* time at which key expires (or 0) */ |
@@ -86,14 +85,10 @@ struct key { | |||
86 | gid_t gid; | 85 | gid_t gid; |
87 | key_perm_t perm; /* access permissions */ | 86 | key_perm_t perm; /* access permissions */ |
88 | unsigned short quotalen; /* length added to quota */ | 87 | unsigned short quotalen; /* length added to quota */ |
89 | unsigned short datalen; /* payload data length */ | 88 | unsigned short datalen; /* payload data length |
90 | unsigned short flags; /* status flags (change with lock writelocked) */ | 89 | * - may not match RCU dereferenced payload |
91 | #define KEY_FLAG_INSTANTIATED 0x00000001 /* set if key has been instantiated */ | 90 | * - payload should contain own length |
92 | #define KEY_FLAG_DEAD 0x00000002 /* set if key type has been deleted */ | 91 | */ |
93 | #define KEY_FLAG_REVOKED 0x00000004 /* set if key had been revoked */ | ||
94 | #define KEY_FLAG_IN_QUOTA 0x00000008 /* set if key consumes quota */ | ||
95 | #define KEY_FLAG_USER_CONSTRUCT 0x00000010 /* set if key is being constructed in userspace */ | ||
96 | #define KEY_FLAG_NEGATIVE 0x00000020 /* set if key is negative */ | ||
97 | 92 | ||
98 | #ifdef KEY_DEBUGGING | 93 | #ifdef KEY_DEBUGGING |
99 | unsigned magic; | 94 | unsigned magic; |
@@ -101,6 +96,14 @@ struct key { | |||
101 | #define KEY_DEBUG_MAGIC_X 0xf8e9dacbu | 96 | #define KEY_DEBUG_MAGIC_X 0xf8e9dacbu |
102 | #endif | 97 | #endif |
103 | 98 | ||
99 | unsigned long flags; /* status flags (change with bitops) */ | ||
100 | #define KEY_FLAG_INSTANTIATED 0 /* set if key has been instantiated */ | ||
101 | #define KEY_FLAG_DEAD 1 /* set if key type has been deleted */ | ||
102 | #define KEY_FLAG_REVOKED 2 /* set if key had been revoked */ | ||
103 | #define KEY_FLAG_IN_QUOTA 3 /* set if key consumes quota */ | ||
104 | #define KEY_FLAG_USER_CONSTRUCT 4 /* set if key is being constructed in userspace */ | ||
105 | #define KEY_FLAG_NEGATIVE 5 /* set if key is negative */ | ||
106 | |||
104 | /* the description string | 107 | /* the description string |
105 | * - this is used to match a key against search criteria | 108 | * - this is used to match a key against search criteria |
106 | * - this should be a printable string | 109 | * - this should be a printable string |
@@ -250,6 +253,8 @@ extern int keyring_add_key(struct key *keyring, | |||
250 | 253 | ||
251 | extern struct key *key_lookup(key_serial_t id); | 254 | extern struct key *key_lookup(key_serial_t id); |
252 | 255 | ||
256 | extern void keyring_replace_payload(struct key *key, void *replacement); | ||
257 | |||
253 | #define key_serial(key) ((key) ? (key)->serial : 0) | 258 | #define key_serial(key) ((key) ? (key)->serial : 0) |
254 | 259 | ||
255 | /* | 260 | /* |
diff --git a/security/keys/key.c b/security/keys/key.c index 59402c84320..1fdfccb3fe4 100644 --- a/security/keys/key.c +++ b/security/keys/key.c | |||
@@ -294,7 +294,6 @@ struct key *key_alloc(struct key_type *type, const char *desc, | |||
294 | } | 294 | } |
295 | 295 | ||
296 | atomic_set(&key->usage, 1); | 296 | atomic_set(&key->usage, 1); |
297 | rwlock_init(&key->lock); | ||
298 | init_rwsem(&key->sem); | 297 | init_rwsem(&key->sem); |
299 | key->type = type; | 298 | key->type = type; |
300 | key->user = user; | 299 | key->user = user; |
@@ -308,7 +307,7 @@ struct key *key_alloc(struct key_type *type, const char *desc, | |||
308 | key->payload.data = NULL; | 307 | key->payload.data = NULL; |
309 | 308 | ||
310 | if (!not_in_quota) | 309 | if (!not_in_quota) |
311 | key->flags |= KEY_FLAG_IN_QUOTA; | 310 | key->flags |= 1 << KEY_FLAG_IN_QUOTA; |
312 | 311 | ||
313 | memset(&key->type_data, 0, sizeof(key->type_data)); | 312 | memset(&key->type_data, 0, sizeof(key->type_data)); |
314 | 313 | ||
@@ -359,7 +358,7 @@ int key_payload_reserve(struct key *key, size_t datalen) | |||
359 | key_check(key); | 358 | key_check(key); |
360 | 359 | ||
361 | /* contemplate the quota adjustment */ | 360 | /* contemplate the quota adjustment */ |
362 | if (delta != 0 && key->flags & KEY_FLAG_IN_QUOTA) { | 361 | if (delta != 0 && test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) { |
363 | spin_lock(&key->user->lock); | 362 | spin_lock(&key->user->lock); |
364 | 363 | ||
365 | if (delta > 0 && | 364 | if (delta > 0 && |
@@ -405,23 +404,17 @@ static int __key_instantiate_and_link(struct key *key, | |||
405 | down_write(&key_construction_sem); | 404 | down_write(&key_construction_sem); |
406 | 405 | ||
407 | /* can't instantiate twice */ | 406 | /* can't instantiate twice */ |
408 | if (!(key->flags & KEY_FLAG_INSTANTIATED)) { | 407 | if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) { |
409 | /* instantiate the key */ | 408 | /* instantiate the key */ |
410 | ret = key->type->instantiate(key, data, datalen); | 409 | ret = key->type->instantiate(key, data, datalen); |
411 | 410 | ||
412 | if (ret == 0) { | 411 | if (ret == 0) { |
413 | /* mark the key as being instantiated */ | 412 | /* mark the key as being instantiated */ |
414 | write_lock(&key->lock); | ||
415 | |||
416 | atomic_inc(&key->user->nikeys); | 413 | atomic_inc(&key->user->nikeys); |
417 | key->flags |= KEY_FLAG_INSTANTIATED; | 414 | set_bit(KEY_FLAG_INSTANTIATED, &key->flags); |
418 | 415 | ||
419 | if (key->flags & KEY_FLAG_USER_CONSTRUCT) { | 416 | if (test_and_clear_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags)) |
420 | key->flags &= ~KEY_FLAG_USER_CONSTRUCT; | ||
421 | awaken = 1; | 417 | awaken = 1; |
422 | } | ||
423 | |||
424 | write_unlock(&key->lock); | ||
425 | 418 | ||
426 | /* and link it into the destination keyring */ | 419 | /* and link it into the destination keyring */ |
427 | if (keyring) | 420 | if (keyring) |
@@ -486,21 +479,17 @@ int key_negate_and_link(struct key *key, | |||
486 | down_write(&key_construction_sem); | 479 | down_write(&key_construction_sem); |
487 | 480 | ||
488 | /* can't instantiate twice */ | 481 | /* can't instantiate twice */ |
489 | if (!(key->flags & KEY_FLAG_INSTANTIATED)) { | 482 | if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) { |
490 | /* mark the key as being negatively instantiated */ | 483 | /* mark the key as being negatively instantiated */ |
491 | write_lock(&key->lock); | ||
492 | |||
493 | atomic_inc(&key->user->nikeys); | 484 | atomic_inc(&key->user->nikeys); |
494 | key->flags |= KEY_FLAG_INSTANTIATED | KEY_FLAG_NEGATIVE; | 485 | set_bit(KEY_FLAG_NEGATIVE, &key->flags); |
486 | set_bit(KEY_FLAG_INSTANTIATED, &key->flags); | ||
495 | now = current_kernel_time(); | 487 | now = current_kernel_time(); |
496 | key->expiry = now.tv_sec + timeout; | 488 | key->expiry = now.tv_sec + timeout; |
497 | 489 | ||
498 | if (key->flags & KEY_FLAG_USER_CONSTRUCT) { | 490 | if (test_and_clear_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags)) |
499 | key->flags &= ~KEY_FLAG_USER_CONSTRUCT; | ||
500 | awaken = 1; | 491 | awaken = 1; |
501 | } | ||
502 | 492 | ||
503 | write_unlock(&key->lock); | ||
504 | ret = 0; | 493 | ret = 0; |
505 | 494 | ||
506 | /* and link it into the destination keyring */ | 495 | /* and link it into the destination keyring */ |
@@ -553,8 +542,10 @@ static void key_cleanup(void *data) | |||
553 | rb_erase(&key->serial_node, &key_serial_tree); | 542 | rb_erase(&key->serial_node, &key_serial_tree); |
554 | spin_unlock(&key_serial_lock); | 543 | spin_unlock(&key_serial_lock); |
555 | 544 | ||
545 | key_check(key); | ||
546 | |||
556 | /* deal with the user's key tracking and quota */ | 547 | /* deal with the user's key tracking and quota */ |
557 | if (key->flags & KEY_FLAG_IN_QUOTA) { | 548 | if (test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) { |
558 | spin_lock(&key->user->lock); | 549 | spin_lock(&key->user->lock); |
559 | key->user->qnkeys--; | 550 | key->user->qnkeys--; |
560 | key->user->qnbytes -= key->quotalen; | 551 | key->user->qnbytes -= key->quotalen; |
@@ -562,7 +553,7 @@ static void key_cleanup(void *data) | |||
562 | } | 553 | } |
563 | 554 | ||
564 | atomic_dec(&key->user->nkeys); | 555 | atomic_dec(&key->user->nkeys); |
565 | if (key->flags & KEY_FLAG_INSTANTIATED) | 556 | if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) |
566 | atomic_dec(&key->user->nikeys); | 557 | atomic_dec(&key->user->nikeys); |
567 | 558 | ||
568 | key_user_put(key->user); | 559 | key_user_put(key->user); |
@@ -631,9 +622,9 @@ struct key *key_lookup(key_serial_t id) | |||
631 | goto error; | 622 | goto error; |
632 | 623 | ||
633 | found: | 624 | found: |
634 | /* pretent doesn't exist if it's dead */ | 625 | /* pretend it doesn't exist if it's dead */ |
635 | if (atomic_read(&key->usage) == 0 || | 626 | if (atomic_read(&key->usage) == 0 || |
636 | (key->flags & KEY_FLAG_DEAD) || | 627 | test_bit(KEY_FLAG_DEAD, &key->flags) || |
637 | key->type == &key_type_dead) | 628 | key->type == &key_type_dead) |
638 | goto not_found; | 629 | goto not_found; |
639 | 630 | ||
@@ -708,12 +699,9 @@ static inline struct key *__key_update(struct key *key, const void *payload, | |||
708 | 699 | ||
709 | ret = key->type->update(key, payload, plen); | 700 | ret = key->type->update(key, payload, plen); |
710 | 701 | ||
711 | if (ret == 0) { | 702 | if (ret == 0) |
712 | /* updating a negative key instantiates it */ | 703 | /* updating a negative key instantiates it */ |
713 | write_lock(&key->lock); | 704 | clear_bit(KEY_FLAG_NEGATIVE, &key->flags); |
714 | key->flags &= ~KEY_FLAG_NEGATIVE; | ||
715 | write_unlock(&key->lock); | ||
716 | } | ||
717 | 705 | ||
718 | up_write(&key->sem); | 706 | up_write(&key->sem); |
719 | 707 | ||
@@ -841,12 +829,9 @@ int key_update(struct key *key, const void *payload, size_t plen) | |||
841 | down_write(&key->sem); | 829 | down_write(&key->sem); |
842 | ret = key->type->update(key, payload, plen); | 830 | ret = key->type->update(key, payload, plen); |
843 | 831 | ||
844 | if (ret == 0) { | 832 | if (ret == 0) |
845 | /* updating a negative key instantiates it */ | 833 | /* updating a negative key instantiates it */ |
846 | write_lock(&key->lock); | 834 | clear_bit(KEY_FLAG_NEGATIVE, &key->flags); |
847 | key->flags &= ~KEY_FLAG_NEGATIVE; | ||
848 | write_unlock(&key->lock); | ||
849 | } | ||
850 | 835 | ||
851 | up_write(&key->sem); | 836 | up_write(&key->sem); |
852 | } | 837 | } |
@@ -892,10 +877,7 @@ struct key *key_duplicate(struct key *source, const char *desc) | |||
892 | goto error2; | 877 | goto error2; |
893 | 878 | ||
894 | atomic_inc(&key->user->nikeys); | 879 | atomic_inc(&key->user->nikeys); |
895 | 880 | set_bit(KEY_FLAG_INSTANTIATED, &key->flags); | |
896 | write_lock(&key->lock); | ||
897 | key->flags |= KEY_FLAG_INSTANTIATED; | ||
898 | write_unlock(&key->lock); | ||
899 | 881 | ||
900 | error_k: | 882 | error_k: |
901 | up_read(&key_types_sem); | 883 | up_read(&key_types_sem); |
@@ -922,9 +904,7 @@ void key_revoke(struct key *key) | |||
922 | /* make sure no one's trying to change or use the key when we mark | 904 | /* make sure no one's trying to change or use the key when we mark |
923 | * it */ | 905 | * it */ |
924 | down_write(&key->sem); | 906 | down_write(&key->sem); |
925 | write_lock(&key->lock); | 907 | set_bit(KEY_FLAG_REVOKED, &key->flags); |
926 | key->flags |= KEY_FLAG_REVOKED; | ||
927 | write_unlock(&key->lock); | ||
928 | up_write(&key->sem); | 908 | up_write(&key->sem); |
929 | 909 | ||
930 | } /* end key_revoke() */ | 910 | } /* end key_revoke() */ |
@@ -975,24 +955,33 @@ void unregister_key_type(struct key_type *ktype) | |||
975 | /* withdraw the key type */ | 955 | /* withdraw the key type */ |
976 | list_del_init(&ktype->link); | 956 | list_del_init(&ktype->link); |
977 | 957 | ||
978 | /* need to withdraw all keys of this type */ | 958 | /* mark all the keys of this type dead */ |
979 | spin_lock(&key_serial_lock); | 959 | spin_lock(&key_serial_lock); |
980 | 960 | ||
981 | for (_n = rb_first(&key_serial_tree); _n; _n = rb_next(_n)) { | 961 | for (_n = rb_first(&key_serial_tree); _n; _n = rb_next(_n)) { |
982 | key = rb_entry(_n, struct key, serial_node); | 962 | key = rb_entry(_n, struct key, serial_node); |
983 | 963 | ||
984 | if (key->type != ktype) | 964 | if (key->type == ktype) |
985 | continue; | 965 | key->type = &key_type_dead; |
966 | } | ||
967 | |||
968 | spin_unlock(&key_serial_lock); | ||
969 | |||
970 | /* make sure everyone revalidates their keys */ | ||
971 | synchronize_kernel(); | ||
972 | |||
973 | /* we should now be able to destroy the payloads of all the keys of | ||
974 | * this type with impunity */ | ||
975 | spin_lock(&key_serial_lock); | ||
986 | 976 | ||
987 | write_lock(&key->lock); | 977 | for (_n = rb_first(&key_serial_tree); _n; _n = rb_next(_n)) { |
988 | key->type = &key_type_dead; | 978 | key = rb_entry(_n, struct key, serial_node); |
989 | write_unlock(&key->lock); | ||
990 | 979 | ||
991 | /* there shouldn't be anyone looking at the description or | 980 | if (key->type == ktype) { |
992 | * payload now */ | 981 | if (ktype->destroy) |
993 | if (ktype->destroy) | 982 | ktype->destroy(key); |
994 | ktype->destroy(key); | 983 | memset(&key->payload, 0xbd, sizeof(key->payload)); |
995 | memset(&key->payload, 0xbd, sizeof(key->payload)); | 984 | } |
996 | } | 985 | } |
997 | 986 | ||
998 | spin_unlock(&key_serial_lock); | 987 | spin_unlock(&key_serial_lock); |
@@ -1037,4 +1026,5 @@ void __init key_init(void) | |||
1037 | 1026 | ||
1038 | /* link the two root keyrings together */ | 1027 | /* link the two root keyrings together */ |
1039 | key_link(&root_session_keyring, &root_user_keyring); | 1028 | key_link(&root_session_keyring, &root_user_keyring); |
1029 | |||
1040 | } /* end key_init() */ | 1030 | } /* end key_init() */ |
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index dc0011b3fac..cedb7326de2 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c | |||
@@ -728,7 +728,6 @@ long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid) | |||
728 | /* make the changes with the locks held to prevent chown/chown races */ | 728 | /* make the changes with the locks held to prevent chown/chown races */ |
729 | ret = -EACCES; | 729 | ret = -EACCES; |
730 | down_write(&key->sem); | 730 | down_write(&key->sem); |
731 | write_lock(&key->lock); | ||
732 | 731 | ||
733 | if (!capable(CAP_SYS_ADMIN)) { | 732 | if (!capable(CAP_SYS_ADMIN)) { |
734 | /* only the sysadmin can chown a key to some other UID */ | 733 | /* only the sysadmin can chown a key to some other UID */ |
@@ -755,7 +754,6 @@ long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid) | |||
755 | ret = 0; | 754 | ret = 0; |
756 | 755 | ||
757 | no_access: | 756 | no_access: |
758 | write_unlock(&key->lock); | ||
759 | up_write(&key->sem); | 757 | up_write(&key->sem); |
760 | key_put(key); | 758 | key_put(key); |
761 | error: | 759 | error: |
@@ -784,26 +782,19 @@ long keyctl_setperm_key(key_serial_t id, key_perm_t perm) | |||
784 | goto error; | 782 | goto error; |
785 | } | 783 | } |
786 | 784 | ||
787 | /* make the changes with the locks held to prevent chown/chmod | 785 | /* make the changes with the locks held to prevent chown/chmod races */ |
788 | * races */ | ||
789 | ret = -EACCES; | 786 | ret = -EACCES; |
790 | down_write(&key->sem); | 787 | down_write(&key->sem); |
791 | write_lock(&key->lock); | ||
792 | 788 | ||
793 | /* if we're not the sysadmin, we can only chmod a key that we | 789 | /* if we're not the sysadmin, we can only change a key that we own */ |
794 | * own */ | 790 | if (capable(CAP_SYS_ADMIN) || key->uid == current->fsuid) { |
795 | if (!capable(CAP_SYS_ADMIN) && key->uid != current->fsuid) | 791 | key->perm = perm; |
796 | goto no_access; | 792 | ret = 0; |
797 | 793 | } | |
798 | /* changing the permissions mask */ | ||
799 | key->perm = perm; | ||
800 | ret = 0; | ||
801 | 794 | ||
802 | no_access: | ||
803 | write_unlock(&key->lock); | ||
804 | up_write(&key->sem); | 795 | up_write(&key->sem); |
805 | key_put(key); | 796 | key_put(key); |
806 | error: | 797 | error: |
807 | return ret; | 798 | return ret; |
808 | 799 | ||
809 | } /* end keyctl_setperm_key() */ | 800 | } /* end keyctl_setperm_key() */ |
diff --git a/security/keys/keyring.c b/security/keys/keyring.c index e2ab4f8e748..c9a5de19748 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c | |||
@@ -132,10 +132,17 @@ static int keyring_duplicate(struct key *keyring, const struct key *source) | |||
132 | (PAGE_SIZE - sizeof(*klist)) / sizeof(struct key); | 132 | (PAGE_SIZE - sizeof(*klist)) / sizeof(struct key); |
133 | 133 | ||
134 | ret = 0; | 134 | ret = 0; |
135 | sklist = source->payload.subscriptions; | ||
136 | 135 | ||
137 | if (sklist && sklist->nkeys > 0) { | 136 | /* find out how many keys are currently linked */ |
137 | rcu_read_lock(); | ||
138 | sklist = rcu_dereference(source->payload.subscriptions); | ||
139 | max = 0; | ||
140 | if (sklist) | ||
138 | max = sklist->nkeys; | 141 | max = sklist->nkeys; |
142 | rcu_read_unlock(); | ||
143 | |||
144 | /* allocate a new payload and stuff load with key links */ | ||
145 | if (max > 0) { | ||
139 | BUG_ON(max > limit); | 146 | BUG_ON(max > limit); |
140 | 147 | ||
141 | max = (max + 3) & ~3; | 148 | max = (max + 3) & ~3; |
@@ -148,6 +155,10 @@ static int keyring_duplicate(struct key *keyring, const struct key *source) | |||
148 | if (!klist) | 155 | if (!klist) |
149 | goto error; | 156 | goto error; |
150 | 157 | ||
158 | /* set links */ | ||
159 | rcu_read_lock(); | ||
160 | sklist = rcu_dereference(source->payload.subscriptions); | ||
161 | |||
151 | klist->maxkeys = max; | 162 | klist->maxkeys = max; |
152 | klist->nkeys = sklist->nkeys; | 163 | klist->nkeys = sklist->nkeys; |
153 | memcpy(klist->keys, | 164 | memcpy(klist->keys, |
@@ -157,7 +168,9 @@ static int keyring_duplicate(struct key *keyring, const struct key *source) | |||
157 | for (loop = klist->nkeys - 1; loop >= 0; loop--) | 168 | for (loop = klist->nkeys - 1; loop >= 0; loop--) |
158 | atomic_inc(&klist->keys[loop]->usage); | 169 | atomic_inc(&klist->keys[loop]->usage); |
159 | 170 | ||
160 | keyring->payload.subscriptions = klist; | 171 | rcu_read_unlock(); |
172 | |||
173 | rcu_assign_pointer(keyring->payload.subscriptions, klist); | ||
161 | ret = 0; | 174 | ret = 0; |
162 | } | 175 | } |
163 | 176 | ||
@@ -192,7 +205,7 @@ static void keyring_destroy(struct key *keyring) | |||
192 | write_unlock(&keyring_name_lock); | 205 | write_unlock(&keyring_name_lock); |
193 | } | 206 | } |
194 | 207 | ||
195 | klist = keyring->payload.subscriptions; | 208 | klist = rcu_dereference(keyring->payload.subscriptions); |
196 | if (klist) { | 209 | if (klist) { |
197 | for (loop = klist->nkeys - 1; loop >= 0; loop--) | 210 | for (loop = klist->nkeys - 1; loop >= 0; loop--) |
198 | key_put(klist->keys[loop]); | 211 | key_put(klist->keys[loop]); |
@@ -216,17 +229,20 @@ static void keyring_describe(const struct key *keyring, struct seq_file *m) | |||
216 | seq_puts(m, "[anon]"); | 229 | seq_puts(m, "[anon]"); |
217 | } | 230 | } |
218 | 231 | ||
219 | klist = keyring->payload.subscriptions; | 232 | rcu_read_lock(); |
233 | klist = rcu_dereference(keyring->payload.subscriptions); | ||
220 | if (klist) | 234 | if (klist) |
221 | seq_printf(m, ": %u/%u", klist->nkeys, klist->maxkeys); | 235 | seq_printf(m, ": %u/%u", klist->nkeys, klist->maxkeys); |
222 | else | 236 | else |
223 | seq_puts(m, ": empty"); | 237 | seq_puts(m, ": empty"); |
238 | rcu_read_unlock(); | ||
224 | 239 | ||
225 | } /* end keyring_describe() */ | 240 | } /* end keyring_describe() */ |
226 | 241 | ||
227 | /*****************************************************************************/ | 242 | /*****************************************************************************/ |
228 | /* | 243 | /* |
229 | * read a list of key IDs from the keyring's contents | 244 | * read a list of key IDs from the keyring's contents |
245 | * - the keyring's semaphore is read-locked | ||
230 | */ | 246 | */ |
231 | static long keyring_read(const struct key *keyring, | 247 | static long keyring_read(const struct key *keyring, |
232 | char __user *buffer, size_t buflen) | 248 | char __user *buffer, size_t buflen) |
@@ -237,7 +253,7 @@ static long keyring_read(const struct key *keyring, | |||
237 | int loop, ret; | 253 | int loop, ret; |
238 | 254 | ||
239 | ret = 0; | 255 | ret = 0; |
240 | klist = keyring->payload.subscriptions; | 256 | klist = rcu_dereference(keyring->payload.subscriptions); |
241 | 257 | ||
242 | if (klist) { | 258 | if (klist) { |
243 | /* calculate how much data we could return */ | 259 | /* calculate how much data we could return */ |
@@ -320,7 +336,7 @@ struct key *keyring_search_aux(struct key *keyring, | |||
320 | key_match_func_t match) | 336 | key_match_func_t match) |
321 | { | 337 | { |
322 | struct { | 338 | struct { |
323 | struct key *keyring; | 339 | struct keyring_list *keylist; |
324 | int kix; | 340 | int kix; |
325 | } stack[KEYRING_SEARCH_MAX_DEPTH]; | 341 | } stack[KEYRING_SEARCH_MAX_DEPTH]; |
326 | 342 | ||
@@ -328,10 +344,12 @@ struct key *keyring_search_aux(struct key *keyring, | |||
328 | struct timespec now; | 344 | struct timespec now; |
329 | struct key *key; | 345 | struct key *key; |
330 | long err; | 346 | long err; |
331 | int sp, psp, kix; | 347 | int sp, kix; |
332 | 348 | ||
333 | key_check(keyring); | 349 | key_check(keyring); |
334 | 350 | ||
351 | rcu_read_lock(); | ||
352 | |||
335 | /* top keyring must have search permission to begin the search */ | 353 | /* top keyring must have search permission to begin the search */ |
336 | key = ERR_PTR(-EACCES); | 354 | key = ERR_PTR(-EACCES); |
337 | if (!key_permission(keyring, KEY_SEARCH)) | 355 | if (!key_permission(keyring, KEY_SEARCH)) |
@@ -347,11 +365,10 @@ struct key *keyring_search_aux(struct key *keyring, | |||
347 | 365 | ||
348 | /* start processing a new keyring */ | 366 | /* start processing a new keyring */ |
349 | descend: | 367 | descend: |
350 | read_lock(&keyring->lock); | 368 | if (test_bit(KEY_FLAG_REVOKED, &keyring->flags)) |
351 | if (keyring->flags & KEY_FLAG_REVOKED) | ||
352 | goto not_this_keyring; | 369 | goto not_this_keyring; |
353 | 370 | ||
354 | keylist = keyring->payload.subscriptions; | 371 | keylist = rcu_dereference(keyring->payload.subscriptions); |
355 | if (!keylist) | 372 | if (!keylist) |
356 | goto not_this_keyring; | 373 | goto not_this_keyring; |
357 | 374 | ||
@@ -364,7 +381,7 @@ struct key *keyring_search_aux(struct key *keyring, | |||
364 | continue; | 381 | continue; |
365 | 382 | ||
366 | /* skip revoked keys and expired keys */ | 383 | /* skip revoked keys and expired keys */ |
367 | if (key->flags & KEY_FLAG_REVOKED) | 384 | if (test_bit(KEY_FLAG_REVOKED, &key->flags)) |
368 | continue; | 385 | continue; |
369 | 386 | ||
370 | if (key->expiry && now.tv_sec >= key->expiry) | 387 | if (key->expiry && now.tv_sec >= key->expiry) |
@@ -379,7 +396,7 @@ struct key *keyring_search_aux(struct key *keyring, | |||
379 | continue; | 396 | continue; |
380 | 397 | ||
381 | /* we set a different error code if we find a negative key */ | 398 | /* we set a different error code if we find a negative key */ |
382 | if (key->flags & KEY_FLAG_NEGATIVE) { | 399 | if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) { |
383 | err = -ENOKEY; | 400 | err = -ENOKEY; |
384 | continue; | 401 | continue; |
385 | } | 402 | } |
@@ -390,48 +407,37 @@ struct key *keyring_search_aux(struct key *keyring, | |||
390 | /* search through the keyrings nested in this one */ | 407 | /* search through the keyrings nested in this one */ |
391 | kix = 0; | 408 | kix = 0; |
392 | ascend: | 409 | ascend: |
393 | while (kix < keylist->nkeys) { | 410 | for (; kix < keylist->nkeys; kix++) { |
394 | key = keylist->keys[kix]; | 411 | key = keylist->keys[kix]; |
395 | if (key->type != &key_type_keyring) | 412 | if (key->type != &key_type_keyring) |
396 | goto next; | 413 | continue; |
397 | 414 | ||
398 | /* recursively search nested keyrings | 415 | /* recursively search nested keyrings |
399 | * - only search keyrings for which we have search permission | 416 | * - only search keyrings for which we have search permission |
400 | */ | 417 | */ |
401 | if (sp >= KEYRING_SEARCH_MAX_DEPTH) | 418 | if (sp >= KEYRING_SEARCH_MAX_DEPTH) |
402 | goto next; | 419 | continue; |
403 | 420 | ||
404 | if (!key_permission(key, KEY_SEARCH)) | 421 | if (!key_permission(key, KEY_SEARCH)) |
405 | goto next; | 422 | continue; |
406 | |||
407 | /* evade loops in the keyring tree */ | ||
408 | for (psp = 0; psp < sp; psp++) | ||
409 | if (stack[psp].keyring == keyring) | ||
410 | goto next; | ||
411 | 423 | ||
412 | /* stack the current position */ | 424 | /* stack the current position */ |
413 | stack[sp].keyring = keyring; | 425 | stack[sp].keylist = keylist; |
414 | stack[sp].kix = kix; | 426 | stack[sp].kix = kix; |
415 | sp++; | 427 | sp++; |
416 | 428 | ||
417 | /* begin again with the new keyring */ | 429 | /* begin again with the new keyring */ |
418 | keyring = key; | 430 | keyring = key; |
419 | goto descend; | 431 | goto descend; |
420 | |||
421 | next: | ||
422 | kix++; | ||
423 | } | 432 | } |
424 | 433 | ||
425 | /* the keyring we're looking at was disqualified or didn't contain a | 434 | /* the keyring we're looking at was disqualified or didn't contain a |
426 | * matching key */ | 435 | * matching key */ |
427 | not_this_keyring: | 436 | not_this_keyring: |
428 | read_unlock(&keyring->lock); | ||
429 | |||
430 | if (sp > 0) { | 437 | if (sp > 0) { |
431 | /* resume the processing of a keyring higher up in the tree */ | 438 | /* resume the processing of a keyring higher up in the tree */ |
432 | sp--; | 439 | sp--; |
433 | keyring = stack[sp].keyring; | 440 | keylist = stack[sp].keylist; |
434 | keylist = keyring->payload.subscriptions; | ||
435 | kix = stack[sp].kix + 1; | 441 | kix = stack[sp].kix + 1; |
436 | goto ascend; | 442 | goto ascend; |
437 | } | 443 | } |
@@ -442,16 +448,9 @@ struct key *keyring_search_aux(struct key *keyring, | |||
442 | /* we found a viable match */ | 448 | /* we found a viable match */ |
443 | found: | 449 | found: |
444 | atomic_inc(&key->usage); | 450 | atomic_inc(&key->usage); |
445 | read_unlock(&keyring->lock); | ||
446 | |||
447 | /* unwind the keyring stack */ | ||
448 | while (sp > 0) { | ||
449 | sp--; | ||
450 | read_unlock(&stack[sp].keyring->lock); | ||
451 | } | ||
452 | |||
453 | key_check(key); | 451 | key_check(key); |
454 | error: | 452 | error: |
453 | rcu_read_unlock(); | ||
455 | return key; | 454 | return key; |
456 | 455 | ||
457 | } /* end keyring_search_aux() */ | 456 | } /* end keyring_search_aux() */ |
@@ -489,7 +488,9 @@ struct key *__keyring_search_one(struct key *keyring, | |||
489 | struct key *key; | 488 | struct key *key; |
490 | int loop; | 489 | int loop; |
491 | 490 | ||
492 | klist = keyring->payload.subscriptions; | 491 | rcu_read_lock(); |
492 | |||
493 | klist = rcu_dereference(keyring->payload.subscriptions); | ||
493 | if (klist) { | 494 | if (klist) { |
494 | for (loop = 0; loop < klist->nkeys; loop++) { | 495 | for (loop = 0; loop < klist->nkeys; loop++) { |
495 | key = klist->keys[loop]; | 496 | key = klist->keys[loop]; |
@@ -497,7 +498,7 @@ struct key *__keyring_search_one(struct key *keyring, | |||
497 | if (key->type == ktype && | 498 | if (key->type == ktype && |
498 | key->type->match(key, description) && | 499 | key->type->match(key, description) && |
499 | key_permission(key, perm) && | 500 | key_permission(key, perm) && |
500 | !(key->flags & KEY_FLAG_REVOKED) | 501 | !test_bit(KEY_FLAG_REVOKED, &key->flags) |
501 | ) | 502 | ) |
502 | goto found; | 503 | goto found; |
503 | } | 504 | } |
@@ -509,6 +510,7 @@ struct key *__keyring_search_one(struct key *keyring, | |||
509 | found: | 510 | found: |
510 | atomic_inc(&key->usage); | 511 | atomic_inc(&key->usage); |
511 | error: | 512 | error: |
513 | rcu_read_unlock(); | ||
512 | return key; | 514 | return key; |
513 | 515 | ||
514 | } /* end __keyring_search_one() */ | 516 | } /* end __keyring_search_one() */ |
@@ -540,7 +542,7 @@ struct key *find_keyring_by_name(const char *name, key_serial_t bound) | |||
540 | &keyring_name_hash[bucket], | 542 | &keyring_name_hash[bucket], |
541 | type_data.link | 543 | type_data.link |
542 | ) { | 544 | ) { |
543 | if (keyring->flags & KEY_FLAG_REVOKED) | 545 | if (test_bit(KEY_FLAG_REVOKED, &keyring->flags)) |
544 | continue; | 546 | continue; |
545 | 547 | ||
546 | if (strcmp(keyring->description, name) != 0) | 548 | if (strcmp(keyring->description, name) != 0) |
@@ -579,7 +581,7 @@ struct key *find_keyring_by_name(const char *name, key_serial_t bound) | |||
579 | static int keyring_detect_cycle(struct key *A, struct key *B) | 581 | static int keyring_detect_cycle(struct key *A, struct key *B) |
580 | { | 582 | { |
581 | struct { | 583 | struct { |
582 | struct key *subtree; | 584 | struct keyring_list *keylist; |
583 | int kix; | 585 | int kix; |
584 | } stack[KEYRING_SEARCH_MAX_DEPTH]; | 586 | } stack[KEYRING_SEARCH_MAX_DEPTH]; |
585 | 587 | ||
@@ -587,20 +589,21 @@ static int keyring_detect_cycle(struct key *A, struct key *B) | |||
587 | struct key *subtree, *key; | 589 | struct key *subtree, *key; |
588 | int sp, kix, ret; | 590 | int sp, kix, ret; |
589 | 591 | ||
592 | rcu_read_lock(); | ||
593 | |||
590 | ret = -EDEADLK; | 594 | ret = -EDEADLK; |
591 | if (A == B) | 595 | if (A == B) |
592 | goto error; | 596 | goto cycle_detected; |
593 | 597 | ||
594 | subtree = B; | 598 | subtree = B; |
595 | sp = 0; | 599 | sp = 0; |
596 | 600 | ||
597 | /* start processing a new keyring */ | 601 | /* start processing a new keyring */ |
598 | descend: | 602 | descend: |
599 | read_lock(&subtree->lock); | 603 | if (test_bit(KEY_FLAG_REVOKED, &subtree->flags)) |
600 | if (subtree->flags & KEY_FLAG_REVOKED) | ||
601 | goto not_this_keyring; | 604 | goto not_this_keyring; |
602 | 605 | ||
603 | keylist = subtree->payload.subscriptions; | 606 | keylist = rcu_dereference(subtree->payload.subscriptions); |
604 | if (!keylist) | 607 | if (!keylist) |
605 | goto not_this_keyring; | 608 | goto not_this_keyring; |
606 | kix = 0; | 609 | kix = 0; |
@@ -619,7 +622,7 @@ static int keyring_detect_cycle(struct key *A, struct key *B) | |||
619 | goto too_deep; | 622 | goto too_deep; |
620 | 623 | ||
621 | /* stack the current position */ | 624 | /* stack the current position */ |
622 | stack[sp].subtree = subtree; | 625 | stack[sp].keylist = keylist; |
623 | stack[sp].kix = kix; | 626 | stack[sp].kix = kix; |
624 | sp++; | 627 | sp++; |
625 | 628 | ||
@@ -632,13 +635,10 @@ static int keyring_detect_cycle(struct key *A, struct key *B) | |||
632 | /* the keyring we're looking at was disqualified or didn't contain a | 635 | /* the keyring we're looking at was disqualified or didn't contain a |
633 | * matching key */ | 636 | * matching key */ |
634 | not_this_keyring: | 637 | not_this_keyring: |
635 | read_unlock(&subtree->lock); | ||
636 | |||
637 | if (sp > 0) { | 638 | if (sp > 0) { |
638 | /* resume the checking of a keyring higher up in the tree */ | 639 | /* resume the checking of a keyring higher up in the tree */ |
639 | sp--; | 640 | sp--; |
640 | subtree = stack[sp].subtree; | 641 | keylist = stack[sp].keylist; |
641 | keylist = subtree->payload.subscriptions; | ||
642 | kix = stack[sp].kix + 1; | 642 | kix = stack[sp].kix + 1; |
643 | goto ascend; | 643 | goto ascend; |
644 | } | 644 | } |
@@ -646,30 +646,36 @@ static int keyring_detect_cycle(struct key *A, struct key *B) | |||
646 | ret = 0; /* no cycles detected */ | 646 | ret = 0; /* no cycles detected */ |
647 | 647 | ||
648 | error: | 648 | error: |
649 | rcu_read_unlock(); | ||
649 | return ret; | 650 | return ret; |
650 | 651 | ||
651 | too_deep: | 652 | too_deep: |
652 | ret = -ELOOP; | 653 | ret = -ELOOP; |
653 | goto error_unwind; | 654 | goto error; |
655 | |||
654 | cycle_detected: | 656 | cycle_detected: |
655 | ret = -EDEADLK; | 657 | ret = -EDEADLK; |
656 | error_unwind: | ||
657 | read_unlock(&subtree->lock); | ||
658 | |||
659 | /* unwind the keyring stack */ | ||
660 | while (sp > 0) { | ||
661 | sp--; | ||
662 | read_unlock(&stack[sp].subtree->lock); | ||
663 | } | ||
664 | |||
665 | goto error; | 658 | goto error; |
666 | 659 | ||
667 | } /* end keyring_detect_cycle() */ | 660 | } /* end keyring_detect_cycle() */ |
668 | 661 | ||
669 | /*****************************************************************************/ | 662 | /*****************************************************************************/ |
670 | /* | 663 | /* |
664 | * dispose of a keyring list after the RCU grace period | ||
665 | */ | ||
666 | static void keyring_link_rcu_disposal(struct rcu_head *rcu) | ||
667 | { | ||
668 | struct keyring_list *klist = | ||
669 | container_of(rcu, struct keyring_list, rcu); | ||
670 | |||
671 | kfree(klist); | ||
672 | |||
673 | } /* end keyring_link_rcu_disposal() */ | ||
674 | |||
675 | /*****************************************************************************/ | ||
676 | /* | ||
671 | * link a key into to a keyring | 677 | * link a key into to a keyring |
672 | * - must be called with the keyring's semaphore held | 678 | * - must be called with the keyring's semaphore write-locked |
673 | */ | 679 | */ |
674 | int __key_link(struct key *keyring, struct key *key) | 680 | int __key_link(struct key *keyring, struct key *key) |
675 | { | 681 | { |
@@ -679,7 +685,7 @@ int __key_link(struct key *keyring, struct key *key) | |||
679 | int ret; | 685 | int ret; |
680 | 686 | ||
681 | ret = -EKEYREVOKED; | 687 | ret = -EKEYREVOKED; |
682 | if (keyring->flags & KEY_FLAG_REVOKED) | 688 | if (test_bit(KEY_FLAG_REVOKED, &keyring->flags)) |
683 | goto error; | 689 | goto error; |
684 | 690 | ||
685 | ret = -ENOTDIR; | 691 | ret = -ENOTDIR; |
@@ -710,9 +716,10 @@ int __key_link(struct key *keyring, struct key *key) | |||
710 | /* there's sufficient slack space to add directly */ | 716 | /* there's sufficient slack space to add directly */ |
711 | atomic_inc(&key->usage); | 717 | atomic_inc(&key->usage); |
712 | 718 | ||
713 | write_lock(&keyring->lock); | 719 | klist->keys[klist->nkeys] = key; |
714 | klist->keys[klist->nkeys++] = key; | 720 | smp_wmb(); |
715 | write_unlock(&keyring->lock); | 721 | klist->nkeys++; |
722 | smp_wmb(); | ||
716 | 723 | ||
717 | ret = 0; | 724 | ret = 0; |
718 | } | 725 | } |
@@ -723,6 +730,8 @@ int __key_link(struct key *keyring, struct key *key) | |||
723 | max += klist->maxkeys; | 730 | max += klist->maxkeys; |
724 | 731 | ||
725 | ret = -ENFILE; | 732 | ret = -ENFILE; |
733 | if (max > 65535) | ||
734 | goto error3; | ||
726 | size = sizeof(*klist) + sizeof(*key) * max; | 735 | size = sizeof(*klist) + sizeof(*key) * max; |
727 | if (size > PAGE_SIZE) | 736 | if (size > PAGE_SIZE) |
728 | goto error3; | 737 | goto error3; |
@@ -743,14 +752,13 @@ int __key_link(struct key *keyring, struct key *key) | |||
743 | 752 | ||
744 | /* add the key into the new space */ | 753 | /* add the key into the new space */ |
745 | atomic_inc(&key->usage); | 754 | atomic_inc(&key->usage); |
746 | |||
747 | write_lock(&keyring->lock); | ||
748 | keyring->payload.subscriptions = nklist; | ||
749 | nklist->keys[nklist->nkeys++] = key; | 755 | nklist->keys[nklist->nkeys++] = key; |
750 | write_unlock(&keyring->lock); | 756 | |
757 | rcu_assign_pointer(keyring->payload.subscriptions, nklist); | ||
751 | 758 | ||
752 | /* dispose of the old keyring list */ | 759 | /* dispose of the old keyring list */ |
753 | kfree(klist); | 760 | if (klist) |
761 | call_rcu(&klist->rcu, keyring_link_rcu_disposal); | ||
754 | 762 | ||
755 | ret = 0; | 763 | ret = 0; |
756 | } | 764 | } |
@@ -791,11 +799,26 @@ EXPORT_SYMBOL(key_link); | |||
791 | 799 | ||
792 | /*****************************************************************************/ | 800 | /*****************************************************************************/ |
793 | /* | 801 | /* |
802 | * dispose of a keyring list after the RCU grace period, freeing the unlinked | ||
803 | * key | ||
804 | */ | ||
805 | static void keyring_unlink_rcu_disposal(struct rcu_head *rcu) | ||
806 | { | ||
807 | struct keyring_list *klist = | ||
808 | container_of(rcu, struct keyring_list, rcu); | ||
809 | |||
810 | key_put(klist->keys[klist->delkey]); | ||
811 | kfree(klist); | ||
812 | |||
813 | } /* end keyring_unlink_rcu_disposal() */ | ||
814 | |||
815 | /*****************************************************************************/ | ||
816 | /* | ||
794 | * unlink the first link to a key from a keyring | 817 | * unlink the first link to a key from a keyring |
795 | */ | 818 | */ |
796 | int key_unlink(struct key *keyring, struct key *key) | 819 | int key_unlink(struct key *keyring, struct key *key) |
797 | { | 820 | { |
798 | struct keyring_list *klist; | 821 | struct keyring_list *klist, *nklist; |
799 | int loop, ret; | 822 | int loop, ret; |
800 | 823 | ||
801 | key_check(keyring); | 824 | key_check(keyring); |
@@ -819,31 +842,45 @@ int key_unlink(struct key *keyring, struct key *key) | |||
819 | ret = -ENOENT; | 842 | ret = -ENOENT; |
820 | goto error; | 843 | goto error; |
821 | 844 | ||
822 | key_is_present: | 845 | key_is_present: |
846 | /* we need to copy the key list for RCU purposes */ | ||
847 | nklist = kmalloc(sizeof(*klist) + sizeof(*key) * klist->maxkeys, | ||
848 | GFP_KERNEL); | ||
849 | if (!nklist) | ||
850 | goto nomem; | ||
851 | nklist->maxkeys = klist->maxkeys; | ||
852 | nklist->nkeys = klist->nkeys - 1; | ||
853 | |||
854 | if (loop > 0) | ||
855 | memcpy(&nklist->keys[0], | ||
856 | &klist->keys[0], | ||
857 | loop * sizeof(klist->keys[0])); | ||
858 | |||
859 | if (loop < nklist->nkeys) | ||
860 | memcpy(&nklist->keys[loop], | ||
861 | &klist->keys[loop + 1], | ||
862 | (nklist->nkeys - loop) * sizeof(klist->keys[0])); | ||
863 | |||
823 | /* adjust the user's quota */ | 864 | /* adjust the user's quota */ |
824 | key_payload_reserve(keyring, | 865 | key_payload_reserve(keyring, |
825 | keyring->datalen - KEYQUOTA_LINK_BYTES); | 866 | keyring->datalen - KEYQUOTA_LINK_BYTES); |
826 | 867 | ||
827 | /* shuffle down the key pointers | 868 | rcu_assign_pointer(keyring->payload.subscriptions, nklist); |
828 | * - it might be worth shrinking the allocated memory, but that runs | ||
829 | * the risk of ENOMEM as we would have to copy | ||
830 | */ | ||
831 | write_lock(&keyring->lock); | ||
832 | 869 | ||
833 | klist->nkeys--; | 870 | up_write(&keyring->sem); |
834 | if (loop < klist->nkeys) | ||
835 | memcpy(&klist->keys[loop], | ||
836 | &klist->keys[loop + 1], | ||
837 | (klist->nkeys - loop) * sizeof(struct key *)); | ||
838 | 871 | ||
839 | write_unlock(&keyring->lock); | 872 | /* schedule for later cleanup */ |
873 | klist->delkey = loop; | ||
874 | call_rcu(&klist->rcu, keyring_unlink_rcu_disposal); | ||
840 | 875 | ||
841 | up_write(&keyring->sem); | ||
842 | key_put(key); | ||
843 | ret = 0; | 876 | ret = 0; |
844 | 877 | ||
845 | error: | 878 | error: |
846 | return ret; | 879 | return ret; |
880 | nomem: | ||
881 | ret = -ENOMEM; | ||
882 | up_write(&keyring->sem); | ||
883 | goto error; | ||
847 | 884 | ||
848 | } /* end key_unlink() */ | 885 | } /* end key_unlink() */ |
849 | 886 | ||
@@ -851,13 +888,32 @@ EXPORT_SYMBOL(key_unlink); | |||
851 | 888 | ||
852 | /*****************************************************************************/ | 889 | /*****************************************************************************/ |
853 | /* | 890 | /* |
891 | * dispose of a keyring list after the RCU grace period, releasing the keys it | ||
892 | * links to | ||
893 | */ | ||
894 | static void keyring_clear_rcu_disposal(struct rcu_head *rcu) | ||
895 | { | ||
896 | struct keyring_list *klist; | ||
897 | int loop; | ||
898 | |||
899 | klist = container_of(rcu, struct keyring_list, rcu); | ||
900 | |||
901 | for (loop = klist->nkeys - 1; loop >= 0; loop--) | ||
902 | key_put(klist->keys[loop]); | ||
903 | |||
904 | kfree(klist); | ||
905 | |||
906 | } /* end keyring_clear_rcu_disposal() */ | ||
907 | |||
908 | /*****************************************************************************/ | ||
909 | /* | ||
854 | * clear the specified process keyring | 910 | * clear the specified process keyring |
855 | * - implements keyctl(KEYCTL_CLEAR) | 911 | * - implements keyctl(KEYCTL_CLEAR) |
856 | */ | 912 | */ |
857 | int keyring_clear(struct key *keyring) | 913 | int keyring_clear(struct key *keyring) |
858 | { | 914 | { |
859 | struct keyring_list *klist; | 915 | struct keyring_list *klist; |
860 | int loop, ret; | 916 | int ret; |
861 | 917 | ||
862 | ret = -ENOTDIR; | 918 | ret = -ENOTDIR; |
863 | if (keyring->type == &key_type_keyring) { | 919 | if (keyring->type == &key_type_keyring) { |
@@ -870,20 +926,15 @@ int keyring_clear(struct key *keyring) | |||
870 | key_payload_reserve(keyring, | 926 | key_payload_reserve(keyring, |
871 | sizeof(struct keyring_list)); | 927 | sizeof(struct keyring_list)); |
872 | 928 | ||
873 | write_lock(&keyring->lock); | 929 | rcu_assign_pointer(keyring->payload.subscriptions, |
874 | keyring->payload.subscriptions = NULL; | 930 | NULL); |
875 | write_unlock(&keyring->lock); | ||
876 | } | 931 | } |
877 | 932 | ||
878 | up_write(&keyring->sem); | 933 | up_write(&keyring->sem); |
879 | 934 | ||
880 | /* free the keys after the locks have been dropped */ | 935 | /* free the keys after the locks have been dropped */ |
881 | if (klist) { | 936 | if (klist) |
882 | for (loop = klist->nkeys - 1; loop >= 0; loop--) | 937 | call_rcu(&klist->rcu, keyring_clear_rcu_disposal); |
883 | key_put(klist->keys[loop]); | ||
884 | |||
885 | kfree(klist); | ||
886 | } | ||
887 | 938 | ||
888 | ret = 0; | 939 | ret = 0; |
889 | } | 940 | } |
diff --git a/security/keys/proc.c b/security/keys/proc.c index 91343b85c39..c55cf1fd082 100644 --- a/security/keys/proc.c +++ b/security/keys/proc.c | |||
@@ -140,7 +140,7 @@ static int proc_keys_show(struct seq_file *m, void *v) | |||
140 | 140 | ||
141 | now = current_kernel_time(); | 141 | now = current_kernel_time(); |
142 | 142 | ||
143 | read_lock(&key->lock); | 143 | rcu_read_lock(); |
144 | 144 | ||
145 | /* come up with a suitable timeout value */ | 145 | /* come up with a suitable timeout value */ |
146 | if (key->expiry == 0) { | 146 | if (key->expiry == 0) { |
@@ -164,14 +164,17 @@ static int proc_keys_show(struct seq_file *m, void *v) | |||
164 | sprintf(xbuf, "%luw", timo / (60*60*24*7)); | 164 | sprintf(xbuf, "%luw", timo / (60*60*24*7)); |
165 | } | 165 | } |
166 | 166 | ||
167 | #define showflag(KEY, LETTER, FLAG) \ | ||
168 | (test_bit(FLAG, &(KEY)->flags) ? LETTER : '-') | ||
169 | |||
167 | seq_printf(m, "%08x %c%c%c%c%c%c %5d %4s %06x %5d %5d %-9.9s ", | 170 | seq_printf(m, "%08x %c%c%c%c%c%c %5d %4s %06x %5d %5d %-9.9s ", |
168 | key->serial, | 171 | key->serial, |
169 | key->flags & KEY_FLAG_INSTANTIATED ? 'I' : '-', | 172 | showflag(key, 'I', KEY_FLAG_INSTANTIATED), |
170 | key->flags & KEY_FLAG_REVOKED ? 'R' : '-', | 173 | showflag(key, 'R', KEY_FLAG_REVOKED), |
171 | key->flags & KEY_FLAG_DEAD ? 'D' : '-', | 174 | showflag(key, 'D', KEY_FLAG_DEAD), |
172 | key->flags & KEY_FLAG_IN_QUOTA ? 'Q' : '-', | 175 | showflag(key, 'Q', KEY_FLAG_IN_QUOTA), |
173 | key->flags & KEY_FLAG_USER_CONSTRUCT ? 'U' : '-', | 176 | showflag(key, 'U', KEY_FLAG_USER_CONSTRUCT), |
174 | key->flags & KEY_FLAG_NEGATIVE ? 'N' : '-', | 177 | showflag(key, 'N', KEY_FLAG_NEGATIVE), |
175 | atomic_read(&key->usage), | 178 | atomic_read(&key->usage), |
176 | xbuf, | 179 | xbuf, |
177 | key->perm, | 180 | key->perm, |
@@ -179,11 +182,13 @@ static int proc_keys_show(struct seq_file *m, void *v) | |||
179 | key->gid, | 182 | key->gid, |
180 | key->type->name); | 183 | key->type->name); |
181 | 184 | ||
185 | #undef showflag | ||
186 | |||
182 | if (key->type->describe) | 187 | if (key->type->describe) |
183 | key->type->describe(key, m); | 188 | key->type->describe(key, m); |
184 | seq_putc(m, '\n'); | 189 | seq_putc(m, '\n'); |
185 | 190 | ||
186 | read_unlock(&key->lock); | 191 | rcu_read_unlock(); |
187 | 192 | ||
188 | return 0; | 193 | return 0; |
189 | 194 | ||
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index 2eb0e471cd4..059c350cac4 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c | |||
@@ -38,10 +38,9 @@ struct key root_user_keyring = { | |||
38 | .serial = 2, | 38 | .serial = 2, |
39 | .type = &key_type_keyring, | 39 | .type = &key_type_keyring, |
40 | .user = &root_key_user, | 40 | .user = &root_key_user, |
41 | .lock = RW_LOCK_UNLOCKED, | ||
42 | .sem = __RWSEM_INITIALIZER(root_user_keyring.sem), | 41 | .sem = __RWSEM_INITIALIZER(root_user_keyring.sem), |
43 | .perm = KEY_USR_ALL, | 42 | .perm = KEY_USR_ALL, |
44 | .flags = KEY_FLAG_INSTANTIATED, | 43 | .flags = 1 << KEY_FLAG_INSTANTIATED, |
45 | .description = "_uid.0", | 44 | .description = "_uid.0", |
46 | #ifdef KEY_DEBUGGING | 45 | #ifdef KEY_DEBUGGING |
47 | .magic = KEY_DEBUG_MAGIC, | 46 | .magic = KEY_DEBUG_MAGIC, |
@@ -54,10 +53,9 @@ struct key root_session_keyring = { | |||
54 | .serial = 1, | 53 | .serial = 1, |
55 | .type = &key_type_keyring, | 54 | .type = &key_type_keyring, |
56 | .user = &root_key_user, | 55 | .user = &root_key_user, |
57 | .lock = RW_LOCK_UNLOCKED, | ||
58 | .sem = __RWSEM_INITIALIZER(root_session_keyring.sem), | 56 | .sem = __RWSEM_INITIALIZER(root_session_keyring.sem), |
59 | .perm = KEY_USR_ALL, | 57 | .perm = KEY_USR_ALL, |
60 | .flags = KEY_FLAG_INSTANTIATED, | 58 | .flags = 1 << KEY_FLAG_INSTANTIATED, |
61 | .description = "_uid_ses.0", | 59 | .description = "_uid_ses.0", |
62 | #ifdef KEY_DEBUGGING | 60 | #ifdef KEY_DEBUGGING |
63 | .magic = KEY_DEBUG_MAGIC, | 61 | .magic = KEY_DEBUG_MAGIC, |
@@ -349,9 +347,7 @@ void key_fsuid_changed(struct task_struct *tsk) | |||
349 | /* update the ownership of the thread keyring */ | 347 | /* update the ownership of the thread keyring */ |
350 | if (tsk->thread_keyring) { | 348 | if (tsk->thread_keyring) { |
351 | down_write(&tsk->thread_keyring->sem); | 349 | down_write(&tsk->thread_keyring->sem); |
352 | write_lock(&tsk->thread_keyring->lock); | ||
353 | tsk->thread_keyring->uid = tsk->fsuid; | 350 | tsk->thread_keyring->uid = tsk->fsuid; |
354 | write_unlock(&tsk->thread_keyring->lock); | ||
355 | up_write(&tsk->thread_keyring->sem); | 351 | up_write(&tsk->thread_keyring->sem); |
356 | } | 352 | } |
357 | 353 | ||
@@ -366,9 +362,7 @@ void key_fsgid_changed(struct task_struct *tsk) | |||
366 | /* update the ownership of the thread keyring */ | 362 | /* update the ownership of the thread keyring */ |
367 | if (tsk->thread_keyring) { | 363 | if (tsk->thread_keyring) { |
368 | down_write(&tsk->thread_keyring->sem); | 364 | down_write(&tsk->thread_keyring->sem); |
369 | write_lock(&tsk->thread_keyring->lock); | ||
370 | tsk->thread_keyring->gid = tsk->fsgid; | 365 | tsk->thread_keyring->gid = tsk->fsgid; |
371 | write_unlock(&tsk->thread_keyring->lock); | ||
372 | up_write(&tsk->thread_keyring->sem); | 366 | up_write(&tsk->thread_keyring->sem); |
373 | } | 367 | } |
374 | 368 | ||
@@ -588,7 +582,7 @@ struct key *lookup_user_key(key_serial_t id, int create, int partial, | |||
588 | } | 582 | } |
589 | 583 | ||
590 | ret = -EIO; | 584 | ret = -EIO; |
591 | if (!partial && !(key->flags & KEY_FLAG_INSTANTIATED)) | 585 | if (!partial && !test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) |
592 | goto invalid_key; | 586 | goto invalid_key; |
593 | 587 | ||
594 | ret = -EACCES; | 588 | ret = -EACCES; |
diff --git a/security/keys/request_key.c b/security/keys/request_key.c index 9705b1aeba5..1f6c0940297 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c | |||
@@ -105,7 +105,7 @@ static struct key *__request_key_construction(struct key_type *type, | |||
105 | struct key_construction cons; | 105 | struct key_construction cons; |
106 | struct timespec now; | 106 | struct timespec now; |
107 | struct key *key; | 107 | struct key *key; |
108 | int ret, negative; | 108 | int ret, negated; |
109 | 109 | ||
110 | /* create a key and add it to the queue */ | 110 | /* create a key and add it to the queue */ |
111 | key = key_alloc(type, description, | 111 | key = key_alloc(type, description, |
@@ -113,9 +113,7 @@ static struct key *__request_key_construction(struct key_type *type, | |||
113 | if (IS_ERR(key)) | 113 | if (IS_ERR(key)) |
114 | goto alloc_failed; | 114 | goto alloc_failed; |
115 | 115 | ||
116 | write_lock(&key->lock); | 116 | set_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags); |
117 | key->flags |= KEY_FLAG_USER_CONSTRUCT; | ||
118 | write_unlock(&key->lock); | ||
119 | 117 | ||
120 | cons.key = key; | 118 | cons.key = key; |
121 | list_add_tail(&cons.link, &key->user->consq); | 119 | list_add_tail(&cons.link, &key->user->consq); |
@@ -130,7 +128,7 @@ static struct key *__request_key_construction(struct key_type *type, | |||
130 | 128 | ||
131 | /* if the key wasn't instantiated, then we want to give an error */ | 129 | /* if the key wasn't instantiated, then we want to give an error */ |
132 | ret = -ENOKEY; | 130 | ret = -ENOKEY; |
133 | if (!(key->flags & KEY_FLAG_INSTANTIATED)) | 131 | if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) |
134 | goto request_failed; | 132 | goto request_failed; |
135 | 133 | ||
136 | down_write(&key_construction_sem); | 134 | down_write(&key_construction_sem); |
@@ -139,7 +137,7 @@ static struct key *__request_key_construction(struct key_type *type, | |||
139 | 137 | ||
140 | /* also give an error if the key was negatively instantiated */ | 138 | /* also give an error if the key was negatively instantiated */ |
141 | check_not_negative: | 139 | check_not_negative: |
142 | if (key->flags & KEY_FLAG_NEGATIVE) { | 140 | if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) { |
143 | key_put(key); | 141 | key_put(key); |
144 | key = ERR_PTR(-ENOKEY); | 142 | key = ERR_PTR(-ENOKEY); |
145 | } | 143 | } |
@@ -152,24 +150,23 @@ static struct key *__request_key_construction(struct key_type *type, | |||
152 | * - remove from construction queue | 150 | * - remove from construction queue |
153 | * - mark the key as dead | 151 | * - mark the key as dead |
154 | */ | 152 | */ |
155 | negative = 0; | 153 | negated = 0; |
156 | down_write(&key_construction_sem); | 154 | down_write(&key_construction_sem); |
157 | 155 | ||
158 | list_del(&cons.link); | 156 | list_del(&cons.link); |
159 | 157 | ||
160 | write_lock(&key->lock); | ||
161 | key->flags &= ~KEY_FLAG_USER_CONSTRUCT; | ||
162 | |||
163 | /* check it didn't get instantiated between the check and the down */ | 158 | /* check it didn't get instantiated between the check and the down */ |
164 | if (!(key->flags & KEY_FLAG_INSTANTIATED)) { | 159 | if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) { |
165 | key->flags |= KEY_FLAG_INSTANTIATED | KEY_FLAG_NEGATIVE; | 160 | set_bit(KEY_FLAG_NEGATIVE, &key->flags); |
166 | negative = 1; | 161 | set_bit(KEY_FLAG_INSTANTIATED, &key->flags); |
162 | negated = 1; | ||
167 | } | 163 | } |
168 | 164 | ||
169 | write_unlock(&key->lock); | 165 | clear_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags); |
166 | |||
170 | up_write(&key_construction_sem); | 167 | up_write(&key_construction_sem); |
171 | 168 | ||
172 | if (!negative) | 169 | if (!negated) |
173 | goto check_not_negative; /* surprisingly, the key got | 170 | goto check_not_negative; /* surprisingly, the key got |
174 | * instantiated */ | 171 | * instantiated */ |
175 | 172 | ||
@@ -250,7 +247,7 @@ static struct key *request_key_construction(struct key_type *type, | |||
250 | 247 | ||
251 | for (;;) { | 248 | for (;;) { |
252 | set_current_state(TASK_UNINTERRUPTIBLE); | 249 | set_current_state(TASK_UNINTERRUPTIBLE); |
253 | if (!(ckey->flags & KEY_FLAG_USER_CONSTRUCT)) | 250 | if (!test_bit(KEY_FLAG_USER_CONSTRUCT, &ckey->flags)) |
254 | break; | 251 | break; |
255 | schedule(); | 252 | schedule(); |
256 | } | 253 | } |
@@ -339,7 +336,8 @@ int key_validate(struct key *key) | |||
339 | if (key) { | 336 | if (key) { |
340 | /* check it's still accessible */ | 337 | /* check it's still accessible */ |
341 | ret = -EKEYREVOKED; | 338 | ret = -EKEYREVOKED; |
342 | if (key->flags & (KEY_FLAG_REVOKED | KEY_FLAG_DEAD)) | 339 | if (test_bit(KEY_FLAG_REVOKED, &key->flags) || |
340 | test_bit(KEY_FLAG_DEAD, &key->flags)) | ||
343 | goto error; | 341 | goto error; |
344 | 342 | ||
345 | /* check it hasn't expired */ | 343 | /* check it hasn't expired */ |
diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c index 8d65b3a2812..c33d3614a0d 100644 --- a/security/keys/user_defined.c +++ b/security/keys/user_defined.c | |||
@@ -42,12 +42,19 @@ struct key_type key_type_user = { | |||
42 | .read = user_read, | 42 | .read = user_read, |
43 | }; | 43 | }; |
44 | 44 | ||
45 | struct user_key_payload { | ||
46 | struct rcu_head rcu; /* RCU destructor */ | ||
47 | unsigned short datalen; /* length of this data */ | ||
48 | char data[0]; /* actual data */ | ||
49 | }; | ||
50 | |||
45 | /*****************************************************************************/ | 51 | /*****************************************************************************/ |
46 | /* | 52 | /* |
47 | * instantiate a user defined key | 53 | * instantiate a user defined key |
48 | */ | 54 | */ |
49 | static int user_instantiate(struct key *key, const void *data, size_t datalen) | 55 | static int user_instantiate(struct key *key, const void *data, size_t datalen) |
50 | { | 56 | { |
57 | struct user_key_payload *upayload; | ||
51 | int ret; | 58 | int ret; |
52 | 59 | ||
53 | ret = -EINVAL; | 60 | ret = -EINVAL; |
@@ -58,13 +65,15 @@ static int user_instantiate(struct key *key, const void *data, size_t datalen) | |||
58 | if (ret < 0) | 65 | if (ret < 0) |
59 | goto error; | 66 | goto error; |
60 | 67 | ||
61 | /* attach the data */ | ||
62 | ret = -ENOMEM; | 68 | ret = -ENOMEM; |
63 | key->payload.data = kmalloc(datalen, GFP_KERNEL); | 69 | upayload = kmalloc(sizeof(*upayload) + datalen, GFP_KERNEL); |
64 | if (!key->payload.data) | 70 | if (!upayload) |
65 | goto error; | 71 | goto error; |
66 | 72 | ||
67 | memcpy(key->payload.data, data, datalen); | 73 | /* attach the data */ |
74 | upayload->datalen = datalen; | ||
75 | memcpy(upayload->data, data, datalen); | ||
76 | rcu_assign_pointer(key->payload.data, upayload); | ||
68 | ret = 0; | 77 | ret = 0; |
69 | 78 | ||
70 | error: | 79 | error: |
@@ -75,18 +84,25 @@ static int user_instantiate(struct key *key, const void *data, size_t datalen) | |||
75 | /*****************************************************************************/ | 84 | /*****************************************************************************/ |
76 | /* | 85 | /* |
77 | * duplicate a user defined key | 86 | * duplicate a user defined key |
87 | * - both keys' semaphores are locked against further modification | ||
88 | * - the new key cannot yet be accessed | ||
78 | */ | 89 | */ |
79 | static int user_duplicate(struct key *key, const struct key *source) | 90 | static int user_duplicate(struct key *key, const struct key *source) |
80 | { | 91 | { |
92 | struct user_key_payload *upayload, *spayload; | ||
81 | int ret; | 93 | int ret; |
82 | 94 | ||
83 | /* just copy the payload */ | 95 | /* just copy the payload */ |
84 | ret = -ENOMEM; | 96 | ret = -ENOMEM; |
85 | key->payload.data = kmalloc(source->datalen, GFP_KERNEL); | 97 | upayload = kmalloc(sizeof(*upayload) + source->datalen, GFP_KERNEL); |
98 | if (upayload) { | ||
99 | spayload = rcu_dereference(source->payload.data); | ||
100 | BUG_ON(source->datalen != spayload->datalen); | ||
86 | 101 | ||
87 | if (key->payload.data) { | 102 | upayload->datalen = key->datalen = spayload->datalen; |
88 | key->datalen = source->datalen; | 103 | memcpy(upayload->data, spayload->data, key->datalen); |
89 | memcpy(key->payload.data, source->payload.data, source->datalen); | 104 | |
105 | key->payload.data = upayload; | ||
90 | ret = 0; | 106 | ret = 0; |
91 | } | 107 | } |
92 | 108 | ||
@@ -96,40 +112,54 @@ static int user_duplicate(struct key *key, const struct key *source) | |||
96 | 112 | ||
97 | /*****************************************************************************/ | 113 | /*****************************************************************************/ |
98 | /* | 114 | /* |
115 | * dispose of the old data from an updated user defined key | ||
116 | */ | ||
117 | static void user_update_rcu_disposal(struct rcu_head *rcu) | ||
118 | { | ||
119 | struct user_key_payload *upayload; | ||
120 | |||
121 | upayload = container_of(rcu, struct user_key_payload, rcu); | ||
122 | |||
123 | kfree(upayload); | ||
124 | |||
125 | } /* end user_update_rcu_disposal() */ | ||
126 | |||
127 | /*****************************************************************************/ | ||
128 | /* | ||
99 | * update a user defined key | 129 | * update a user defined key |
130 | * - the key's semaphore is write-locked | ||
100 | */ | 131 | */ |
101 | static int user_update(struct key *key, const void *data, size_t datalen) | 132 | static int user_update(struct key *key, const void *data, size_t datalen) |
102 | { | 133 | { |
103 | void *new, *zap; | 134 | struct user_key_payload *upayload, *zap; |
104 | int ret; | 135 | int ret; |
105 | 136 | ||
106 | ret = -EINVAL; | 137 | ret = -EINVAL; |
107 | if (datalen <= 0 || datalen > 32767 || !data) | 138 | if (datalen <= 0 || datalen > 32767 || !data) |
108 | goto error; | 139 | goto error; |
109 | 140 | ||
110 | /* copy the data */ | 141 | /* construct a replacement payload */ |
111 | ret = -ENOMEM; | 142 | ret = -ENOMEM; |
112 | new = kmalloc(datalen, GFP_KERNEL); | 143 | upayload = kmalloc(sizeof(*upayload) + datalen, GFP_KERNEL); |
113 | if (!new) | 144 | if (!upayload) |
114 | goto error; | 145 | goto error; |
115 | 146 | ||
116 | memcpy(new, data, datalen); | 147 | upayload->datalen = datalen; |
148 | memcpy(upayload->data, data, datalen); | ||
117 | 149 | ||
118 | /* check the quota and attach the new data */ | 150 | /* check the quota and attach the new data */ |
119 | zap = new; | 151 | zap = upayload; |
120 | write_lock(&key->lock); | ||
121 | 152 | ||
122 | ret = key_payload_reserve(key, datalen); | 153 | ret = key_payload_reserve(key, datalen); |
123 | 154 | ||
124 | if (ret == 0) { | 155 | if (ret == 0) { |
125 | /* attach the new data, displacing the old */ | 156 | /* attach the new data, displacing the old */ |
126 | zap = key->payload.data; | 157 | zap = key->payload.data; |
127 | key->payload.data = new; | 158 | rcu_assign_pointer(key->payload.data, upayload); |
128 | key->expiry = 0; | 159 | key->expiry = 0; |
129 | } | 160 | } |
130 | 161 | ||
131 | write_unlock(&key->lock); | 162 | call_rcu(&zap->rcu, user_update_rcu_disposal); |
132 | kfree(zap); | ||
133 | 163 | ||
134 | error: | 164 | error: |
135 | return ret; | 165 | return ret; |
@@ -152,13 +182,15 @@ static int user_match(const struct key *key, const void *description) | |||
152 | */ | 182 | */ |
153 | static void user_destroy(struct key *key) | 183 | static void user_destroy(struct key *key) |
154 | { | 184 | { |
155 | kfree(key->payload.data); | 185 | struct user_key_payload *upayload = key->payload.data; |
186 | |||
187 | kfree(upayload); | ||
156 | 188 | ||
157 | } /* end user_destroy() */ | 189 | } /* end user_destroy() */ |
158 | 190 | ||
159 | /*****************************************************************************/ | 191 | /*****************************************************************************/ |
160 | /* | 192 | /* |
161 | * describe the user | 193 | * describe the user key |
162 | */ | 194 | */ |
163 | static void user_describe(const struct key *key, struct seq_file *m) | 195 | static void user_describe(const struct key *key, struct seq_file *m) |
164 | { | 196 | { |
@@ -171,18 +203,23 @@ static void user_describe(const struct key *key, struct seq_file *m) | |||
171 | /*****************************************************************************/ | 203 | /*****************************************************************************/ |
172 | /* | 204 | /* |
173 | * read the key data | 205 | * read the key data |
206 | * - the key's semaphore is read-locked | ||
174 | */ | 207 | */ |
175 | static long user_read(const struct key *key, | 208 | static long user_read(const struct key *key, |
176 | char __user *buffer, size_t buflen) | 209 | char __user *buffer, size_t buflen) |
177 | { | 210 | { |
178 | long ret = key->datalen; | 211 | struct user_key_payload *upayload; |
212 | long ret; | ||
213 | |||
214 | upayload = rcu_dereference(key->payload.data); | ||
215 | ret = upayload->datalen; | ||
179 | 216 | ||
180 | /* we can return the data as is */ | 217 | /* we can return the data as is */ |
181 | if (buffer && buflen > 0) { | 218 | if (buffer && buflen > 0) { |
182 | if (buflen > key->datalen) | 219 | if (buflen > upayload->datalen) |
183 | buflen = key->datalen; | 220 | buflen = upayload->datalen; |
184 | 221 | ||
185 | if (copy_to_user(buffer, key->payload.data, buflen) != 0) | 222 | if (copy_to_user(buffer, upayload->data, buflen) != 0) |
186 | ret = -EFAULT; | 223 | ret = -EFAULT; |
187 | } | 224 | } |
188 | 225 | ||