diff --git a/Documentation/security/keys.txt b/Documentation/security/keys.txt
index cade1de..b0647a0 100644
--- a/Documentation/security/keys.txt
+++ b/Documentation/security/keys.txt
@@ -418,8 +418,17 @@ The main syscalls are:
      the type. The payload is plen in size, and plen can be zero for an empty
      payload.
 
-     A new keyring can be generated by setting type "keyring", the keyring name
-     as the description (or NULL) and setting the payload to NULL.
+     A new keyring can be generated by setting type "keyring" and the keyring
+     name as the description (or NULL).  The payload can be NULL or contain
+     keyring link restriction parameters using the following format:
+
+	"restrict=<type>:<options>"
+
+     "type" is a registered key type. "options" vary depending on the key type,
+     and are passed to the lookup_restrict function for the requested type.
+     The options may specify a specific method and relevant data for the
+     restriction (such as signature verification or constraints on key
+     payload).
 
      User defined keys can be created by specifying type "user". It is
      recommended that a user defined key's description by prefixed with a type
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index 07f680b..0aefaff 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -23,6 +23,13 @@
 #include "internal.h"
 
 /*
+ * Layout of preparse payload
+ */
+enum {
+	keyring_restrict_link,
+};
+
+/*
  * When plumbing the depths of the key tree, this sets a hard limit
  * set on how deep we're willing to go.
  */
@@ -126,28 +133,103 @@ static void keyring_publish_name(struct key *keyring)
 }
 
 /*
+ * Parse the keyring options and fill in the required keyring members.
+ *
+ * Expected format is: "restrict=<key_type>[:<options>]"
+ *
+ * Returns 0 if the option string is valid (including the empty case),
+ * otherwise -EINVAL.
+ */
+static int keyring_datablob_parse(char *datablob,
+				  struct key_preparsed_payload *prep)
+{
+	char *type_name;
+	struct key_type *restrict_type = NULL;
+	struct key_restriction *restrict_link;
+	int ret = -EINVAL;
+	const char restrict_prefix[] = "restrict=";
+
+	if (*datablob == '\0')
+		return 0;
+
+	if (!strstarts(datablob, restrict_prefix))
+		return -EINVAL;
+
+	datablob += strlen(restrict_prefix);
+
+	type_name = strsep(&datablob, ":");
+
+	restrict_type = key_type_lookup(type_name);
+	if (IS_ERR(restrict_type))
+		return -EINVAL;
+
+	if (!restrict_type->lookup_restrict)
+		goto error;
+
+	restrict_link = restrict_type->lookup_restrict(datablob);
+	if (IS_ERR(restrict_link))
+		goto error;
+
+	prep->payload.data[keyring_restrict_link] = restrict_link;
+	ret = 0;
+
+error:
+	key_type_put(restrict_type);
+
+	return ret;
+}
+
+/*
  * Preparse a keyring payload
  */
 static int keyring_preparse(struct key_preparsed_payload *prep)
 {
-	return prep->datalen != 0 ? -EINVAL : 0;
+	char *datablob;
+	size_t datalen = prep->datalen;
+	int ret = 0;
+
+	if (datalen) {
+		datablob = kmalloc(datalen + 1, GFP_KERNEL);
+		if (!datablob)
+			return -ENOMEM;
+
+		memcpy(datablob, prep->data, datalen);
+		datablob[datalen] = '\0';
+
+		ret = keyring_datablob_parse(datablob, prep);
+
+		kfree(datablob);
+	}
+
+	return ret;
 }
 
 /*
- * Free a preparse of a user defined key payload
+ * Free a preparse of a keyring payload
  */
 static void keyring_free_preparse(struct key_preparsed_payload *prep)
 {
+	struct key_restriction *keyres;
+
+	keyres = prep->payload.data[keyring_restrict_link];
+
+	if (keyres && keyres->free_data) {
+		keyres->free_data(keyres->data);
+		kfree(keyres);
+	}
 }
 
 /*
  * Initialise a keyring.
  *
- * Returns 0 on success, -EINVAL if given any data.
+ * Returns 0 on success.
  */
 static int keyring_instantiate(struct key *keyring,
 			       struct key_preparsed_payload *prep)
 {
+	keyring->restrict_link = prep->payload.data[keyring_restrict_link];
+	prep->payload.data[keyring_restrict_link] = NULL;
+
 	assoc_array_init(&keyring->keys);
 	/* make the keyring available by name if it has one */
 	keyring_publish_name(keyring);
