Unverified Commit 19014bbb authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!10917 Fix CVE-2024-36031

Merge Pull Request from: @ci-robot 
 
PR sync from: Yi Yang <yiyang13@huawei.com>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/4HF72RGWWLQX22ZPFW7FHJF4ZKNPKPLO/ 
Fix CVE-2024-36031 for openEuler-22.03-LTS-SP1

David Howells (2):
  keys, dns: Allow key types (eg. DNS) to be reclaimed immediately on
    expiry
  keys, dns: Fix size check of V1 server-list header

Edward Adam Davis (1):
  keys, dns: Fix missing size check of V1 server-list header

Silvio Gissi (1):
  keys: Fix overwrite of key expiration on instantiation


-- 
2.25.1
 
https://gitee.com/src-openeuler/kernel/issues/I9TM8D 
 
Link:https://gitee.com/openeuler/kernel/pulls/10917

 

Reviewed-by: default avatarYang Yingliang <yangyingliang@huawei.com>
Signed-off-by: default avatarYang Yingliang <yangyingliang@huawei.com>
parents cc1a8dde e9b1d3ed
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -74,6 +74,7 @@ struct key_type {

	unsigned int flags;
#define KEY_TYPE_NET_DOMAIN	0x00000001 /* Keys of this type have a net namespace domain */
#define KEY_TYPE_INSTANT_REAP	0x00000002 /* Keys of this type don't have a delay after expiring */

	/* vet a description */
	int (*vet_description)(const char *description);
+16 −9
Original line number Diff line number Diff line
@@ -91,7 +91,6 @@ const struct cred *dns_resolver_cache;
static int
dns_resolver_preparse(struct key_preparsed_payload *prep)
{
	const struct dns_payload_header *bin;
	struct user_key_payload *upayload;
	unsigned long derrno;
	int ret;
@@ -102,26 +101,34 @@ dns_resolver_preparse(struct key_preparsed_payload *prep)
		return -EINVAL;

	if (data[0] == 0) {
		const struct dns_server_list_v1_header *v1;

		/* It may be a server list. */
		if (datalen <= sizeof(*bin))
		if (datalen < sizeof(*v1))
			return -EINVAL;

		bin = (const struct dns_payload_header *)data;
		kenter("[%u,%u],%u", bin->content, bin->version, datalen);
		if (bin->content != DNS_PAYLOAD_IS_SERVER_LIST) {
		v1 = (const struct dns_server_list_v1_header *)data;
		kenter("[%u,%u],%u", v1->hdr.content, v1->hdr.version, datalen);
		if (v1->hdr.content != DNS_PAYLOAD_IS_SERVER_LIST) {
			pr_warn_ratelimited(
				"dns_resolver: Unsupported content type (%u)\n",
				bin->content);
				v1->hdr.content);
			return -EINVAL;
		}

		if (bin->version != 1) {
		if (v1->hdr.version != 1) {
			pr_warn_ratelimited(
				"dns_resolver: Unsupported server list version (%u)\n",
				bin->version);
				v1->hdr.version);
			return -EINVAL;
		}

		if ((v1->status != DNS_LOOKUP_GOOD &&
		     v1->status != DNS_LOOKUP_GOOD_WITH_BAD)) {
			if (prep->expiry == TIME64_MAX)
				prep->expiry = ktime_get_real_seconds() + 1;
		}

		result_len = datalen;
		goto store_result;
	}
@@ -314,7 +321,7 @@ static long dns_resolver_read(const struct key *key,

struct key_type key_type_dns_resolver = {
	.name		= "dns_resolver",
	.flags		= KEY_TYPE_NET_DOMAIN,
	.flags		= KEY_TYPE_NET_DOMAIN | KEY_TYPE_INSTANT_REAP,
	.preparse	= dns_resolver_preparse,
	.free_preparse	= dns_resolver_free_preparse,
	.instantiate	= generic_key_instantiate,
+21 −10
Original line number Diff line number Diff line
@@ -66,6 +66,19 @@ void key_schedule_gc(time64_t gc_at)
	}
}

/*
 * Set the expiration time on a key.
 */
void key_set_expiry(struct key *key, time64_t expiry)
{
	key->expiry = expiry;
	if (expiry != TIME64_MAX) {
		if (!(key->type->flags & KEY_TYPE_INSTANT_REAP))
			expiry += key_gc_delay;
		key_schedule_gc(expiry);
	}
}

/*
 * Schedule a dead links collection run.
 */
@@ -176,7 +189,6 @@ static void key_garbage_collector(struct work_struct *work)
	static u8 gc_state;		/* Internal persistent state */
#define KEY_GC_REAP_AGAIN	0x01	/* - Need another cycle */
#define KEY_GC_REAPING_LINKS	0x02	/* - We need to reap links */
#define KEY_GC_SET_TIMER	0x04	/* - We need to restart the timer */
#define KEY_GC_REAPING_DEAD_1	0x10	/* - We need to mark dead keys */
#define KEY_GC_REAPING_DEAD_2	0x20	/* - We need to reap dead key links */
#define KEY_GC_REAPING_DEAD_3	0x40	/* - We need to reap dead keys */
@@ -184,21 +196,17 @@ static void key_garbage_collector(struct work_struct *work)

	struct rb_node *cursor;
	struct key *key;
	time64_t new_timer, limit;
	time64_t new_timer, limit, expiry;

	kenter("[%lx,%x]", key_gc_flags, gc_state);

	limit = ktime_get_real_seconds();
	if (limit > key_gc_delay)
		limit -= key_gc_delay;
	else
		limit = key_gc_delay;

	/* Work out what we're going to be doing in this pass */
	gc_state &= KEY_GC_REAPING_DEAD_1 | KEY_GC_REAPING_DEAD_2;
	gc_state <<= 1;
	if (test_and_clear_bit(KEY_GC_KEY_EXPIRED, &key_gc_flags))
		gc_state |= KEY_GC_REAPING_LINKS | KEY_GC_SET_TIMER;
		gc_state |= KEY_GC_REAPING_LINKS;

	if (test_and_clear_bit(KEY_GC_REAP_KEYTYPE, &key_gc_flags))
		gc_state |= KEY_GC_REAPING_DEAD_1;
@@ -233,8 +241,11 @@ static void key_garbage_collector(struct work_struct *work)
			}
		}

		if (gc_state & KEY_GC_SET_TIMER) {
			if (key->expiry > limit && key->expiry < new_timer) {
		expiry = key->expiry;
		if (expiry != TIME64_MAX) {
			if (!(key->type->flags & KEY_TYPE_INSTANT_REAP))
				expiry += key_gc_delay;
			if (expiry > limit && expiry < new_timer) {
				kdebug("will expire %x in %lld",
				       key_serial(key), key->expiry - limit);
				new_timer = key->expiry;
@@ -276,7 +287,7 @@ static void key_garbage_collector(struct work_struct *work)
	 */
	kdebug("pass complete");

	if (gc_state & KEY_GC_SET_TIMER && new_timer != (time64_t)TIME64_MAX) {
	if (new_timer != TIME64_MAX) {
		new_timer += key_gc_delay;
		key_schedule_gc(new_timer);
	}
+10 −1
Original line number Diff line number Diff line
@@ -176,6 +176,7 @@ extern unsigned key_gc_delay;
extern void keyring_gc(struct key *keyring, time64_t limit);
extern void keyring_restriction_gc(struct key *keyring,
				   struct key_type *dead_type);
void key_set_expiry(struct key *key, time64_t expiry);
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);
@@ -224,10 +225,18 @@ extern struct key *key_get_instantiation_authkey(key_serial_t target_id);
 */
static inline bool key_is_dead(const struct key *key, time64_t limit)
{
	time64_t expiry = key->expiry;

	if (expiry != TIME64_MAX) {
		if (!(key->type->flags & KEY_TYPE_INSTANT_REAP))
			expiry += key_gc_delay;
		if (expiry <= limit)
			return true;
	}

	return
		key->flags & ((1 << KEY_FLAG_DEAD) |
			      (1 << KEY_FLAG_INVALIDATED)) ||
		(key->expiry > 0 && key->expiry <= limit) ||
		key->domain_tag->removed;
}

+6 −10
Original line number Diff line number Diff line
@@ -294,6 +294,7 @@ struct key *key_alloc(struct key_type *type, const char *desc,
	key->uid = uid;
	key->gid = gid;
	key->perm = perm;
	key->expiry = TIME64_MAX;
	key->restrict_link = restrict_link;
	key->last_used_at = ktime_get_real_seconds();

@@ -463,10 +464,8 @@ static int __key_instantiate_and_link(struct key *key,
			if (authkey)
				key_invalidate(authkey);

			if (prep->expiry != TIME64_MAX) {
				key->expiry = prep->expiry;
				key_schedule_gc(prep->expiry + key_gc_delay);
			}
			if (prep->expiry != TIME64_MAX)
				key_set_expiry(key, prep->expiry);
		}
	}

@@ -605,8 +604,7 @@ int key_reject_and_link(struct key *key,
		atomic_inc(&key->user->nikeys);
		mark_key_instantiated(key, -error);
		notify_key(key, NOTIFY_KEY_INSTANTIATED, -error);
		key->expiry = ktime_get_real_seconds() + timeout;
		key_schedule_gc(key->expiry + key_gc_delay);
		key_set_expiry(key, ktime_get_real_seconds() + timeout);

		if (test_and_clear_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags))
			awaken = 1;
@@ -721,16 +719,14 @@ struct key_type *key_type_lookup(const char *type)

void key_set_timeout(struct key *key, unsigned timeout)
{
	time64_t expiry = 0;
	time64_t expiry = TIME64_MAX;

	/* make the changes with the locks held to prevent races */
	down_write(&key->sem);

	if (timeout > 0)
		expiry = ktime_get_real_seconds() + timeout;

	key->expiry = expiry;
	key_schedule_gc(key->expiry + key_gc_delay);
	key_set_expiry(key, expiry);

	up_write(&key->sem);
}
Loading