Commit 1f5a018c authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'fixes-v5.1-rc6' of...

Merge branch 'fixes-v5.1-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security

Pull keys fixes from James Morris:

 - Handle quotas better, allowing full quota to be reached.

 - Fix the creation of shortcuts in the assoc_array internal
   representation when the index key needs to be an exact multiple of
   the machine word size.

 - Fix a dependency loop between the request_key contruction record and
   the request_key authentication key. The construction record isn't
   really necessary and can be dispensed with.

 - Set the timestamp on a new key rather than leaving it as 0. This
   would ordinarily be fine - provided the system clock is never set to
   a time before 1970

* 'fixes-v5.1-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security:
  keys: Timestamp new keys
  keys: Fix dependency loop between construction record and auth key
  assoc_array: Fix shortcut creation
  KEYS: allow reaching the keys quotas exactly
parents 40e196a9 7c1857bd
Loading
Loading
Loading
Loading
+17 −14
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@
#include <linux/keyctl.h>
#include <linux/key-type.h>
#include <keys/user-type.h>
#include <keys/request_key_auth-type.h>
#include <linux/module.h>

#include "internal.h"
@@ -59,7 +60,7 @@ static struct key_type key_type_id_resolver_legacy;
struct idmap_legacy_upcalldata {
	struct rpc_pipe_msg pipe_msg;
	struct idmap_msg idmap_msg;
	struct key_construction	*key_cons;
	struct key	*authkey;
	struct idmap *idmap;
};

@@ -384,7 +385,7 @@ static const match_table_t nfs_idmap_tokens = {
	{ Opt_find_err, NULL }
};

static int nfs_idmap_legacy_upcall(struct key_construction *, const char *, void *);
static int nfs_idmap_legacy_upcall(struct key *, void *);
static ssize_t idmap_pipe_downcall(struct file *, const char __user *,
				   size_t);
static void idmap_release_pipe(struct inode *);
@@ -549,11 +550,12 @@ nfs_idmap_prepare_pipe_upcall(struct idmap *idmap,
static void
nfs_idmap_complete_pipe_upcall_locked(struct idmap *idmap, int ret)
{
	struct key_construction *cons = idmap->idmap_upcall_data->key_cons;
	struct key *authkey = idmap->idmap_upcall_data->authkey;

	kfree(idmap->idmap_upcall_data);
	idmap->idmap_upcall_data = NULL;
	complete_request_key(cons, ret);
	complete_request_key(authkey, ret);
	key_put(authkey);
}

static void
@@ -563,15 +565,14 @@ nfs_idmap_abort_pipe_upcall(struct idmap *idmap, int ret)
		nfs_idmap_complete_pipe_upcall_locked(idmap, ret);
}

static int nfs_idmap_legacy_upcall(struct key_construction *cons,
				   const char *op,
				   void *aux)
static int nfs_idmap_legacy_upcall(struct key *authkey, void *aux)
{
	struct idmap_legacy_upcalldata *data;
	struct request_key_auth *rka = get_request_key_auth(authkey);
	struct rpc_pipe_msg *msg;
	struct idmap_msg *im;
	struct idmap *idmap = (struct idmap *)aux;
	struct key *key = cons->key;
	struct key *key = rka->target_key;
	int ret = -ENOKEY;

	if (!aux)
@@ -586,7 +587,7 @@ static int nfs_idmap_legacy_upcall(struct key_construction *cons,
	msg = &data->pipe_msg;
	im = &data->idmap_msg;
	data->idmap = idmap;
	data->key_cons = cons;
	data->authkey = key_get(authkey);

	ret = nfs_idmap_prepare_message(key->description, idmap, im, msg);
	if (ret < 0)
@@ -604,7 +605,7 @@ static int nfs_idmap_legacy_upcall(struct key_construction *cons,
out2:
	kfree(data);
out1:
	complete_request_key(cons, ret);
	complete_request_key(authkey, ret);
	return ret;
}

@@ -651,9 +652,10 @@ out:
static ssize_t
idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
{
	struct request_key_auth *rka;
	struct rpc_inode *rpci = RPC_I(file_inode(filp));
	struct idmap *idmap = (struct idmap *)rpci->private;
	struct key_construction *cons;
	struct key *authkey;
	struct idmap_msg im;
	size_t namelen_in;
	int ret = -ENOKEY;
@@ -665,7 +667,8 @@ idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
	if (idmap->idmap_upcall_data == NULL)
		goto out_noupcall;

	cons = idmap->idmap_upcall_data->key_cons;
	authkey = idmap->idmap_upcall_data->authkey;
	rka = get_request_key_auth(authkey);

	if (mlen != sizeof(im)) {
		ret = -ENOSPC;
@@ -690,9 +693,9 @@ idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)

	ret = nfs_idmap_read_and_verify_message(&im,
			&idmap->idmap_upcall_data->idmap_msg,
			cons->key, cons->authkey);
			rka->target_key, authkey);
	if (ret >= 0) {
		key_set_timeout(cons->key, nfs_idmap_cache_timeout);
		key_set_timeout(rka->target_key, nfs_idmap_cache_timeout);
		ret = mlen;
	}

+36 −0
Original line number Diff line number Diff line
/* request_key authorisation token key type
 *
 * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
 * Written by David Howells (dhowells@redhat.com)
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public Licence
 * as published by the Free Software Foundation; either version
 * 2 of the Licence, or (at your option) any later version.
 */

#ifndef _KEYS_REQUEST_KEY_AUTH_TYPE_H
#define _KEYS_REQUEST_KEY_AUTH_TYPE_H

#include <linux/key.h>

/*
 * Authorisation record for request_key().
 */
struct request_key_auth {
	struct key		*target_key;
	struct key		*dest_keyring;
	const struct cred	*cred;
	void			*callout_info;
	size_t			callout_len;
	pid_t			pid;
	char			op[8];
} __randomize_layout;

static inline struct request_key_auth *get_request_key_auth(const struct key *key)
{
	return key->payload.data[0];
}


#endif /* _KEYS_REQUEST_KEY_AUTH_TYPE_H */
+6 −16
Original line number Diff line number Diff line
@@ -20,15 +20,6 @@
struct kernel_pkey_query;
struct kernel_pkey_params;

/*
 * key under-construction record
 * - passed to the request_key actor if supplied
 */
struct key_construction {
	struct key	*key;	/* key being constructed */
	struct key	*authkey;/* authorisation for key being constructed */
};

/*
 * Pre-parsed payload, used by key add, update and instantiate.
 *
@@ -50,8 +41,7 @@ struct key_preparsed_payload {
	time64_t	expiry;		/* Expiry time of key */
} __randomize_layout;

typedef int (*request_key_actor_t)(struct key_construction *key,
				   const char *op, void *aux);
typedef int (*request_key_actor_t)(struct key *auth_key, void *aux);

/*
 * Preparsed matching criterion.
@@ -181,20 +171,20 @@ extern int key_instantiate_and_link(struct key *key,
				    const void *data,
				    size_t datalen,
				    struct key *keyring,
				    struct key *instkey);
				    struct key *authkey);
extern int key_reject_and_link(struct key *key,
			       unsigned timeout,
			       unsigned error,
			       struct key *keyring,
			       struct key *instkey);
extern void complete_request_key(struct key_construction *cons, int error);
			       struct key *authkey);
extern void complete_request_key(struct key *authkey, int error);

static inline int key_negate_and_link(struct key *key,
				      unsigned timeout,
				      struct key *keyring,
				      struct key *instkey)
				      struct key *authkey)
{
	return key_reject_and_link(key, timeout, ENOKEY, keyring, instkey);
	return key_reject_and_link(key, timeout, ENOKEY, keyring, authkey);
}

extern int generic_key_instantiate(struct key *key, struct key_preparsed_payload *prep);
+5 −3
Original line number Diff line number Diff line
@@ -768,9 +768,11 @@ all_leaves_cluster_together:
		new_s0->index_key[i] =
			ops->get_key_chunk(index_key, i * ASSOC_ARRAY_KEY_CHUNK_SIZE);

	if (level & ASSOC_ARRAY_KEY_CHUNK_MASK) {
		blank = ULONG_MAX << (level & ASSOC_ARRAY_KEY_CHUNK_MASK);
		pr_devel("blank off [%zu] %d: %lx\n", keylen - 1, level, blank);
		new_s0->index_key[keylen - 1] &= ~blank;
	}

	/* This now reduces to a node splitting exercise for which we'll need
	 * to regenerate the disparity table.
+1 −12
Original line number Diff line number Diff line
@@ -186,20 +186,9 @@ static inline int key_permission(const key_ref_t key_ref, unsigned perm)
	return key_task_permission(key_ref, current_cred(), perm);
}

/*
 * Authorisation record for request_key().
 */
struct request_key_auth {
	struct key		*target_key;
	struct key		*dest_keyring;
	const struct cred	*cred;
	void			*callout_info;
	size_t			callout_len;
	pid_t			pid;
} __randomize_layout;

extern struct key_type key_type_request_key_auth;
extern struct key *request_key_auth_new(struct key *target,
					const char *op,
					const void *callout_info,
					size_t callout_len,
					struct key *dest_keyring);
Loading