Keys devel

-----BEGIN PGP SIGNATURE-----
 
 iQIVAwUAWhc/3fSw1s6N8H32AQLJxQ/9Gw5ns9bipLQ5VeXjgQjY6U39lHWD7z0e
 cz1jYsqOGvWXqoHZumK6fB0NorYZ3EEiWTVqNkpTv1p5ZIJe612G3oe5SOTn2gA5
 1X4qb/QMCr12TIv/R40mXuEsBUZZaUvxK5G7L7/Ty8a9iC+Pp3Tr009ThPvhfDMc
 RRP5MHxPghat+jwRcBjMz3ndQCkoTIlR9qichzQcndv5yywASQFxQsHEeG0tK48j
 NvicJawsr+0kZ2xqpRjRRJ/aQ+lMpI3SLsaUJBbIf6IYFs+i++OUkwAv0WYG0RZa
 xGjQBaaSmXPp48akIeModsp3SgNwBFpbTiXJR8hdGYjJNaaMNGD5HGQ539Ij+Wpf
 YHTIsdqw3xfFH/FoHMOesF/h/uMoA1NAMFAy/gGHxRRGNIk0wERHdTpdFUODIx9E
 NJk2fwBYpO+uRntgcmt9F3S9+YBzxACHYNmjvtbvUwjkr/hnl6jincTmlkmR9Fgl
 HYy+RcBb9A19wRYnZ5wDFOyk3sua7iq4ZBq0dbpYtSOtR9q4RtFw9wfsT8OoQMKz
 aBBn8AiV2ak+Qu00MFCyqj3jUoWa/8qzy6/57nWNsqoJTBMD0uI5UY4liTBGeq3g
 m02uVqtZgwjeBxUmMh8IxZDntVRZChGgvmifwOzb/BUV8oaOiy4aiQjONSdQBeP6
 j9SDBLRH/PY=
 =wuVV
 -----END PGP SIGNATURE-----

Merge tag 'keys-next-20171123' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs into next-keys

Merge keys subsystem changes from David Howells, for v4.15.
This commit is contained in:
James Morris 2017-11-24 11:54:11 +11:00
commit ce44cd8dfc
14 changed files with 66 additions and 65 deletions

View file

@ -628,12 +628,12 @@ The keyctl syscall functions are:
defined key type will return its data as is. If a key type does not
implement this function, error EOPNOTSUPP will result.
As much of the data as can be fitted into the buffer will be copied to
userspace if the buffer pointer is not NULL.
On a successful return, the function will always return the amount of data
available rather than the amount copied.
If the specified buffer is too small, then the size of the buffer required
will be returned. Note that in this case, the contents of the buffer may
have been overwritten in some undefined way.
Otherwise, on success, the function will return the amount of data copied
into the buffer.
* Instantiate a partially constructed key::

View file

@ -19,6 +19,7 @@
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("PKCS#7 testing key type");
MODULE_AUTHOR("Red Hat, Inc.");
static unsigned pkcs7_usage;
module_param_named(usage, pkcs7_usage, uint, S_IWUSR | S_IRUGO);

View file

@ -11,6 +11,7 @@
#define pr_fmt(fmt) "PKCS7: "fmt
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/export.h>
#include <linux/slab.h>
#include <linux/err.h>
@ -19,6 +20,10 @@
#include "pkcs7_parser.h"
#include "pkcs7-asn1.h"
MODULE_DESCRIPTION("PKCS#7 parser");
MODULE_AUTHOR("Red Hat, Inc.");
MODULE_LICENSE("GPL");
struct pkcs7_parse_context {
struct pkcs7_message *msg; /* Message being constructed */
struct pkcs7_signed_info *sinfo; /* SignedInfo being constructed */

View file

@ -22,6 +22,8 @@
#include <crypto/public_key.h>
#include <crypto/akcipher.h>
MODULE_DESCRIPTION("In-software asymmetric public-key subtype");
MODULE_AUTHOR("Red Hat, Inc.");
MODULE_LICENSE("GPL");
/*

View file

@ -275,4 +275,5 @@ module_init(x509_key_init);
module_exit(x509_key_exit);
MODULE_DESCRIPTION("X.509 certificate parser");
MODULE_AUTHOR("Red Hat, Inc.");
MODULE_LICENSE("GPL");

View file

@ -44,7 +44,7 @@ struct key_preparsed_payload {
const void *data; /* Raw data */
size_t datalen; /* Raw datalen */
size_t quotalen; /* Quota length for proposed payload */
time_t expiry; /* Expiry time of key */
time64_t expiry; /* Expiry time of key */
} __randomize_layout;
typedef int (*request_key_actor_t)(struct key_construction *key,

View file

@ -24,6 +24,7 @@
#include <linux/atomic.h>
#include <linux/assoc_array.h>
#include <linux/refcount.h>
#include <linux/time64.h>
#ifdef __KERNEL__
#include <linux/uidgid.h>
@ -162,10 +163,10 @@ struct key {
struct key_user *user; /* owner of this key */
void *security; /* security data for this key */
union {
time_t expiry; /* time at which key expires (or 0) */
time_t revoked_at; /* time at which key was revoked */
time64_t expiry; /* time at which key expires (or 0) */
time64_t revoked_at; /* time at which key was revoked */
};
time_t last_used_at; /* last time used for LRU keyring discard */
time64_t last_used_at; /* last time used for LRU keyring discard */
kuid_t uid;
kgid_t gid;
key_perm_t perm; /* access permissions */

View file

@ -32,7 +32,7 @@ DECLARE_WORK(key_gc_work, key_garbage_collector);
static void key_gc_timer_func(unsigned long);
static DEFINE_TIMER(key_gc_timer, key_gc_timer_func);
static time_t key_gc_next_run = LONG_MAX;
static time64_t key_gc_next_run = TIME64_MAX;
static struct key_type *key_gc_dead_keytype;
static unsigned long key_gc_flags;
@ -53,12 +53,12 @@ struct key_type key_type_dead = {
* Schedule a garbage collection run.
* - time precision isn't particularly important
*/
void key_schedule_gc(time_t gc_at)
void key_schedule_gc(time64_t gc_at)
{
unsigned long expires;
time_t now = current_kernel_time().tv_sec;
time64_t now = ktime_get_real_seconds();
kenter("%ld", gc_at - now);
kenter("%lld", gc_at - now);
if (gc_at <= now || test_bit(KEY_GC_REAP_KEYTYPE, &key_gc_flags)) {
kdebug("IMMEDIATE");
@ -87,7 +87,7 @@ void key_schedule_gc_links(void)
static void key_gc_timer_func(unsigned long data)
{
kenter("");
key_gc_next_run = LONG_MAX;
key_gc_next_run = TIME64_MAX;
key_schedule_gc_links();
}
@ -184,11 +184,11 @@ static void key_garbage_collector(struct work_struct *work)
struct rb_node *cursor;
struct key *key;
time_t new_timer, limit;
time64_t new_timer, limit;
kenter("[%lx,%x]", key_gc_flags, gc_state);
limit = current_kernel_time().tv_sec;
limit = ktime_get_real_seconds();
if (limit > key_gc_delay)
limit -= key_gc_delay;
else
@ -204,7 +204,7 @@ static void key_garbage_collector(struct work_struct *work)
gc_state |= KEY_GC_REAPING_DEAD_1;
kdebug("new pass %x", gc_state);
new_timer = LONG_MAX;
new_timer = TIME64_MAX;
/* As only this function is permitted to remove things from the key
* serial tree, if cursor is non-NULL then it will always point to a
@ -235,7 +235,7 @@ continue_scanning:
if (gc_state & KEY_GC_SET_TIMER) {
if (key->expiry > limit && key->expiry < new_timer) {
kdebug("will expire %x in %ld",
kdebug("will expire %x in %lld",
key_serial(key), key->expiry - limit);
new_timer = key->expiry;
}
@ -276,7 +276,7 @@ maybe_resched:
*/
kdebug("pass complete");
if (gc_state & KEY_GC_SET_TIMER && new_timer != (time_t)LONG_MAX) {
if (gc_state & KEY_GC_SET_TIMER && new_timer != (time64_t)TIME64_MAX) {
new_timer += key_gc_delay;
key_schedule_gc(new_timer);
}

View file

@ -130,7 +130,7 @@ struct keyring_search_context {
int skipped_ret;
bool possessed;
key_ref_t result;
struct timespec now;
time64_t now;
};
extern bool key_default_cmp(const struct key *key,
@ -169,10 +169,10 @@ extern void key_change_session_keyring(struct callback_head *twork);
extern struct work_struct key_gc_work;
extern unsigned key_gc_delay;
extern void keyring_gc(struct key *keyring, time_t limit);
extern void keyring_gc(struct key *keyring, time64_t limit);
extern void keyring_restriction_gc(struct key *keyring,
struct key_type *dead_type);
extern void key_schedule_gc(time_t gc_at);
extern void key_schedule_gc(time64_t gc_at);
extern void key_schedule_gc_links(void);
extern void key_gc_keytype(struct key_type *ktype);
@ -211,7 +211,7 @@ extern struct key *key_get_instantiation_authkey(key_serial_t target_id);
/*
* Determine whether a key is dead.
*/
static inline bool key_is_dead(const struct key *key, time_t limit)
static inline bool key_is_dead(const struct key *key, time64_t limit)
{
return
key->flags & ((1 << KEY_FLAG_DEAD) |

View file

@ -460,7 +460,7 @@ static int __key_instantiate_and_link(struct key *key,
if (authkey)
key_revoke(authkey);
if (prep->expiry != TIME_T_MAX) {
if (prep->expiry != TIME64_MAX) {
key->expiry = prep->expiry;
key_schedule_gc(prep->expiry + key_gc_delay);
}
@ -506,7 +506,7 @@ int key_instantiate_and_link(struct key *key,
prep.data = data;
prep.datalen = datalen;
prep.quotalen = key->type->def_datalen;
prep.expiry = TIME_T_MAX;
prep.expiry = TIME64_MAX;
if (key->type->preparse) {
ret = key->type->preparse(&prep);
if (ret < 0)
@ -570,7 +570,6 @@ int key_reject_and_link(struct key *key,
struct key *authkey)
{
struct assoc_array_edit *edit;
struct timespec now;
int ret, awaken, link_ret = 0;
key_check(key);
@ -593,8 +592,7 @@ int key_reject_and_link(struct key *key,
/* mark the key as being negatively instantiated */
atomic_inc(&key->user->nikeys);
mark_key_instantiated(key, -error);
now = current_kernel_time();
key->expiry = now.tv_sec + timeout;
key->expiry = ktime_get_real_seconds() + timeout;
key_schedule_gc(key->expiry + key_gc_delay);
if (test_and_clear_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags))
@ -710,16 +708,13 @@ found_kernel_type:
void key_set_timeout(struct key *key, unsigned timeout)
{
struct timespec now;
time_t expiry = 0;
time64_t expiry = 0;
/* make the changes with the locks held to prevent races */
down_write(&key->sem);
if (timeout > 0) {
now = current_kernel_time();
expiry = now.tv_sec + timeout;
}
if (timeout > 0)
expiry = ktime_get_real_seconds() + timeout;
key->expiry = expiry;
key_schedule_gc(key->expiry + key_gc_delay);
@ -850,7 +845,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
prep.data = payload;
prep.datalen = plen;
prep.quotalen = index_key.type->def_datalen;
prep.expiry = TIME_T_MAX;
prep.expiry = TIME64_MAX;
if (index_key.type->preparse) {
ret = index_key.type->preparse(&prep);
if (ret < 0) {
@ -994,7 +989,7 @@ int key_update(key_ref_t key_ref, const void *payload, size_t plen)
prep.data = payload;
prep.datalen = plen;
prep.quotalen = key->type->def_datalen;
prep.expiry = TIME_T_MAX;
prep.expiry = TIME64_MAX;
if (key->type->preparse) {
ret = key->type->preparse(&prep);
if (ret < 0)
@ -1028,8 +1023,7 @@ EXPORT_SYMBOL(key_update);
*/
void key_revoke(struct key *key)
{
struct timespec now;
time_t time;
time64_t time;
key_check(key);
@ -1044,8 +1038,7 @@ void key_revoke(struct key *key)
key->type->revoke(key);
/* set the death time to no more than the expiry time */
now = current_kernel_time();
time = now.tv_sec;
time = ktime_get_real_seconds();
if (key->revoked_at == 0 || key->revoked_at > time) {
key->revoked_at = time;
key_schedule_gc(key->revoked_at + key_gc_delay);

View file

@ -565,7 +565,7 @@ static int keyring_search_iterator(const void *object, void *iterator_data)
/* skip invalidated, revoked and expired keys */
if (ctx->flags & KEYRING_SEARCH_DO_STATE_CHECK) {
time_t expiry = READ_ONCE(key->expiry);
time64_t expiry = READ_ONCE(key->expiry);
if (kflags & ((1 << KEY_FLAG_INVALIDATED) |
(1 << KEY_FLAG_REVOKED))) {
@ -574,7 +574,7 @@ static int keyring_search_iterator(const void *object, void *iterator_data)
goto skipped;
}
if (expiry && ctx->now.tv_sec >= expiry) {
if (expiry && ctx->now >= expiry) {
if (!(ctx->flags & KEYRING_SEARCH_SKIP_EXPIRED))
ctx->result = ERR_PTR(-EKEYEXPIRED);
kleave(" = %d [expire]", ctx->skipped_ret);
@ -834,10 +834,10 @@ found:
key = key_ref_to_ptr(ctx->result);
key_check(key);
if (!(ctx->flags & KEYRING_SEARCH_NO_UPDATE_TIME)) {
key->last_used_at = ctx->now.tv_sec;
keyring->last_used_at = ctx->now.tv_sec;
key->last_used_at = ctx->now;
keyring->last_used_at = ctx->now;
while (sp > 0)
stack[--sp].keyring->last_used_at = ctx->now.tv_sec;
stack[--sp].keyring->last_used_at = ctx->now;
}
kleave(" = true");
return true;
@ -898,7 +898,7 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
}
rcu_read_lock();
ctx->now = current_kernel_time();
ctx->now = ktime_get_real_seconds();
if (search_nested_keyrings(keyring, ctx))
__key_get(key_ref_to_ptr(ctx->result));
rcu_read_unlock();
@ -1149,7 +1149,7 @@ struct key *find_keyring_by_name(const char *name, bool uid_keyring)
* (ie. it has a zero usage count) */
if (!refcount_inc_not_zero(&keyring->usage))
continue;
keyring->last_used_at = current_kernel_time().tv_sec;
keyring->last_used_at = ktime_get_real_seconds();
goto out;
}
}
@ -1489,7 +1489,7 @@ static void keyring_revoke(struct key *keyring)
static bool keyring_gc_select_iterator(void *object, void *iterator_data)
{
struct key *key = keyring_ptr_to_key(object);
time_t *limit = iterator_data;
time64_t *limit = iterator_data;
if (key_is_dead(key, *limit))
return false;
@ -1500,7 +1500,7 @@ static bool keyring_gc_select_iterator(void *object, void *iterator_data)
static int keyring_gc_check_iterator(const void *object, void *iterator_data)
{
const struct key *key = keyring_ptr_to_key(object);
time_t *limit = iterator_data;
time64_t *limit = iterator_data;
key_check(key);
return key_is_dead(key, *limit);
@ -1512,7 +1512,7 @@ static int keyring_gc_check_iterator(const void *object, void *iterator_data)
* Not called with any locks held. The keyring's key struct will not be
* deallocated under us as only our caller may deallocate it.
*/
void keyring_gc(struct key *keyring, time_t limit)
void keyring_gc(struct key *keyring, time64_t limit)
{
int result;

View file

@ -89,7 +89,7 @@ EXPORT_SYMBOL(key_task_permission);
int key_validate(const struct key *key)
{
unsigned long flags = READ_ONCE(key->flags);
time_t expiry = READ_ONCE(key->expiry);
time64_t expiry = READ_ONCE(key->expiry);
if (flags & (1 << KEY_FLAG_INVALIDATED))
return -ENOKEY;
@ -101,8 +101,7 @@ int key_validate(const struct key *key)
/* check it hasn't expired */
if (expiry) {
struct timespec now = current_kernel_time();
if (now.tv_sec >= expiry)
if (ktime_get_real_seconds() >= expiry)
return -EKEYEXPIRED;
}

View file

@ -178,13 +178,12 @@ static int proc_keys_show(struct seq_file *m, void *v)
{
struct rb_node *_p = v;
struct key *key = rb_entry(_p, struct key, serial_node);
struct timespec now;
time_t expiry;
unsigned long timo;
unsigned long flags;
key_ref_t key_ref, skey_ref;
time64_t now, expiry;
char xbuf[16];
short state;
u64 timo;
int rc;
struct keyring_search_context ctx = {
@ -215,7 +214,7 @@ static int proc_keys_show(struct seq_file *m, void *v)
if (rc < 0)
return 0;
now = current_kernel_time();
now = ktime_get_real_seconds();
rcu_read_lock();
@ -223,21 +222,21 @@ static int proc_keys_show(struct seq_file *m, void *v)
expiry = READ_ONCE(key->expiry);
if (expiry == 0) {
memcpy(xbuf, "perm", 5);
} else if (now.tv_sec >= expiry) {
} else if (now >= expiry) {
memcpy(xbuf, "expd", 5);
} else {
timo = expiry - now.tv_sec;
timo = expiry - now;
if (timo < 60)
sprintf(xbuf, "%lus", timo);
sprintf(xbuf, "%llus", timo);
else if (timo < 60*60)
sprintf(xbuf, "%lum", timo / 60);
sprintf(xbuf, "%llum", div_u64(timo, 60));
else if (timo < 60*60*24)
sprintf(xbuf, "%luh", timo / (60*60));
sprintf(xbuf, "%lluh", div_u64(timo, 60 * 60));
else if (timo < 60*60*24*7)
sprintf(xbuf, "%lud", timo / (60*60*24));
sprintf(xbuf, "%llud", div_u64(timo, 60 * 60 * 24));
else
sprintf(xbuf, "%luw", timo / (60*60*24*7));
sprintf(xbuf, "%lluw", div_u64(timo, 60 * 60 * 24 * 7));
}
state = key_read_state(key);

View file

@ -738,7 +738,7 @@ try_again:
if (ret < 0)
goto invalid_key;
key->last_used_at = current_kernel_time().tv_sec;
key->last_used_at = ktime_get_real_seconds();
error:
put_cred(ctx.cred);