The proposed NFS key type uses its own method of passing key requests touserspace (upcalling) rather than invoking /sbin/request-key. This is becausethe responsible userspace daemon should already be running and will becontacted through rpc_pipefs.

This patch permits the NFS filesystem to pass auxiliary data to the upcalloperation (struct key_type::request_key) so that the upcaller can use apre-existing communications channel more easily.

The key request service is part of the key retention service (refer to-Documentation/keys.txt). This document explains more fully how that the-requesting algorithm works.+Documentation/keys.txt). This document explains more fully how the requesting+algorithm works.

The process starts by either the kernel requesting a service by calling-request_key():+request_key*():

-The main difference between the two access points is that the in-kernel-interface does not need to link the key to a keyring to prevent it from being-immediately destroyed. The kernel interface returns a pointer directly to the-key, and it's up to the caller to destroy the key.+The main difference between the access points is that the in-kernel interface+does not need to link the key to a keyring to prevent it from being immediately+destroyed. The kernel interface returns a pointer directly to the key, and+it's up to the caller to destroy the key.++The request_key2() call is like the request_key() call in the kernel, except+that it permits auxiliary data to be passed to the upcaller (the default is+NULL). This is only useful for those key types that define their own upcall+mechanism rather than using /sbin/request-key.

The userspace interface links the key to a keyring associated with the process to prevent the key from going away, and returns the serial number of the key to the caller.

+The following example assumes that the key types involved don't define their+own upcall mechanisms. If they do, then those should be substituted for the+forking and execution of /sbin/request-key.++ =========== THE PROCESS ===========@@ -40,8 +57,8 @@ A request proceeds in the following mann interface].

(2) request_key() searches the process's subscribed keyrings to see if there's- a suitable key there. If there is, it returns the key. If there isn't, and- callout_info is not set, an error is returned. Otherwise the process+ a suitable key there. If there is, it returns the key. If there isn't,+ and callout_info is not set, an error is returned. Otherwise the process proceeds to the next step.

(3) request_key() sees that A doesn't have the desired key yet, so it creates@@ -62,7 +79,7 @@ A request proceeds in the following mann instantiation.

(7) The program may want to access another key from A's context (say a- Kerberos TGT key). It just requests the appropriate key, and the keyring+ Kerberos TGT key). It just requests the appropriate key, and the keyring search notes that the session keyring has auth key V in its bottom level.

This will permit it to then search the keyrings of process A with the@@ -79,10 +96,11 @@ A request proceeds in the following mann (10) The program then exits 0 and request_key() deletes key V and returns key U to the caller.

-This also extends further. If key W (step 7 above) didn't exist, key W would be-created uninstantiated, another auth key (X) would be created (as per step 3)-and another copy of /sbin/request-key spawned (as per step 4); but the context-specified by auth key X will still be process A, as it was in auth key V.+This also extends further. If key W (step 7 above) didn't exist, key W would+be created uninstantiated, another auth key (X) would be created (as per step+3) and another copy of /sbin/request-key spawned (as per step 4); but the+context specified by auth key X will still be process A, as it was in auth key+V.

This is because process A's keyrings can't simply be attached to /sbin/request-key at the appropriate places because (a) execve will discard two@@ -118,17 +136,17 @@ A search of any particular keyring proce

(2) It considers all the non-keyring keys within that keyring and, if any key matches the criteria specified, calls key_permission(SEARCH) on it to see- if the key is allowed to be found. If it is, that key is returned; if+ if the key is allowed to be found. If it is, that key is returned; if not, the search continues, and the error code is retained if of higher priority than the one currently set.

(3) It then considers all the keyring-type keys in the keyring it's currently- searching. It calls key_permission(SEARCH) on each keyring, and if this+ searching. It calls key_permission(SEARCH) on each keyring, and if this grants permission, it recurses, executing steps (2) and (3) on that keyring.

The process stops immediately a valid key is found with permission granted to-use it. Any error from a previous match attempt is discarded and the key is+use it. Any error from a previous match attempt is discarded and the key is returned.

When search_process_keyrings() is invoked, it performs the following searches@@ -153,7 +171,7 @@ The moment one succeeds, all pending err returned.

Only if all these fail does the whole thing fail with the highest priority-error. Note that several errors may have come from LSM.+error. Note that several errors may have come from LSM.

+(*) To search for a key, passing auxiliary data to the upcaller, call:++ struct key *request_key2(const struct key_type *type,+ const char *description,+ const char *callout_string,+ void *aux);++ This is identical to request_key(), except that the auxiliary data is+ passed to the key_type->request_key() op if it exists.++ (*) When it is no longer required, the key should be released using:

void key_put(struct key *key);@@ -1031,6 +1042,23 @@ The structure has a number of fields, so as might happen when the userspace buffer is accessed.

+ (*) int (*request_key)(struct key *key, struct key *authkey, const char *op,+ void *aux);++ This method is optional. If provided, request_key() and request_key2()+ will invoke this function rather than upcalling to /sbin/request-key to+ operate upon a key of this type.++ The aux parameter is as passed to request_key2() or is NULL otherwise.+ Also passed are the key to be operated upon, the authorisation key for+ this operation and the operation type (currently only "create").++ This function should return only when the upcall is complete. Upon return+ the authorisation key will be revoked, and the target key will be+ negatively instantiated if it is still uninstantiated. The error will be+ returned to the caller of request_key*().++ ============================ REQUEST-KEY CALLBACK SERVICE ============================diff --git a/include/linux/key.h b/include/linux/key.hindex e693e72..fadad7f 100644--- a/include/linux/key.h+++ b/include/linux/key.h@@ -177,7 +177,8 @@ #define KEY_FLAG_NEGATIVE 5 /* set if ke /* * kernel managed key type definition */-typedef int (*request_key_actor_t)(struct key *key, struct key *authkey, const char *op);+typedef int (*request_key_actor_t)(struct key *key, struct key *authkey,+ const char *op, void *aux);