Skip to content

Commit

Permalink
Merge branch 'fixes-v5.1-rc6' of git://git.kernel.org/pub/scm/linux/k…
Browse files Browse the repository at this point in the history
…ernel/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
  • Loading branch information
torvalds committed Feb 20, 2019
2 parents 40e196a + 7c1857b commit 1f5a018
Show file tree
Hide file tree
Showing 10 changed files with 108 additions and 97 deletions.
31 changes: 17 additions & 14 deletions fs/nfs/nfs4idmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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;
};

Expand Down Expand Up @@ -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 *);
Expand Down Expand Up @@ -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
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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;
}

Expand Down Expand Up @@ -651,9 +652,10 @@ static int nfs_idmap_read_and_verify_message(struct idmap_msg *im,
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;
Expand All @@ -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;
Expand All @@ -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;
}

Expand Down
36 changes: 36 additions & 0 deletions include/keys/request_key_auth-type.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/* request_key authorisation token key type
*
* Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
* Written by David Howells ([email protected])
*
* 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 */
22 changes: 6 additions & 16 deletions include/linux/key-type.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand All @@ -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.
Expand Down Expand Up @@ -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);
Expand Down
8 changes: 5 additions & 3 deletions lib/assoc_array.c
Original file line number Diff line number Diff line change
Expand Up @@ -768,9 +768,11 @@ static bool assoc_array_insert_into_terminal_node(struct assoc_array_edit *edit,
new_s0->index_key[i] =
ops->get_key_chunk(index_key, i * ASSOC_ARRAY_KEY_CHUNK_SIZE);

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;
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.
Expand Down
13 changes: 1 addition & 12 deletions security/keys/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
5 changes: 3 additions & 2 deletions security/keys/key.c
Original file line number Diff line number Diff line change
Expand Up @@ -265,8 +265,8 @@ struct key *key_alloc(struct key_type *type, const char *desc,

spin_lock(&user->lock);
if (!(flags & KEY_ALLOC_QUOTA_OVERRUN)) {
if (user->qnkeys + 1 >= maxkeys ||
user->qnbytes + quotalen >= maxbytes ||
if (user->qnkeys + 1 > maxkeys ||
user->qnbytes + quotalen > maxbytes ||
user->qnbytes + quotalen < user->qnbytes)
goto no_quota;
}
Expand Down Expand Up @@ -297,6 +297,7 @@ struct key *key_alloc(struct key_type *type, const char *desc,
key->gid = gid;
key->perm = perm;
key->restrict_link = restrict_link;
key->last_used_at = ktime_get_real_seconds();

if (!(flags & KEY_ALLOC_NOT_IN_QUOTA))
key->flags |= 1 << KEY_FLAG_IN_QUOTA;
Expand Down
1 change: 1 addition & 0 deletions security/keys/keyctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <linux/security.h>
#include <linux/uio.h>
#include <linux/uaccess.h>
#include <keys/request_key_auth-type.h>
#include "internal.h"

#define KEY_MAX_DESC_SIZE 4096
Expand Down
1 change: 1 addition & 0 deletions security/keys/process_keys.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <linux/security.h>
#include <linux/user_namespace.h>
#include <linux/uaccess.h>
#include <keys/request_key_auth-type.h>
#include "internal.h"

/* Session keyring create vs join semaphore */
Expand Down
Loading

0 comments on commit 1f5a018

Please sign in to comment.