xref: /OK3568_Linux_fs/kernel/security/keys/user_defined.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /* user_defined.c: user defined key type
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
5*4882a593Smuzhiyun  * Written by David Howells (dhowells@redhat.com)
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <linux/export.h>
9*4882a593Smuzhiyun #include <linux/init.h>
10*4882a593Smuzhiyun #include <linux/slab.h>
11*4882a593Smuzhiyun #include <linux/seq_file.h>
12*4882a593Smuzhiyun #include <linux/err.h>
13*4882a593Smuzhiyun #include <keys/user-type.h>
14*4882a593Smuzhiyun #include <linux/uaccess.h>
15*4882a593Smuzhiyun #include "internal.h"
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun static int logon_vet_description(const char *desc);
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun /*
20*4882a593Smuzhiyun  * user defined keys take an arbitrary string as the description and an
21*4882a593Smuzhiyun  * arbitrary blob of data as the payload
22*4882a593Smuzhiyun  */
23*4882a593Smuzhiyun struct key_type key_type_user = {
24*4882a593Smuzhiyun 	.name			= "user",
25*4882a593Smuzhiyun 	.preparse		= user_preparse,
26*4882a593Smuzhiyun 	.free_preparse		= user_free_preparse,
27*4882a593Smuzhiyun 	.instantiate		= generic_key_instantiate,
28*4882a593Smuzhiyun 	.update			= user_update,
29*4882a593Smuzhiyun 	.revoke			= user_revoke,
30*4882a593Smuzhiyun 	.destroy		= user_destroy,
31*4882a593Smuzhiyun 	.describe		= user_describe,
32*4882a593Smuzhiyun 	.read			= user_read,
33*4882a593Smuzhiyun };
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(key_type_user);
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun /*
38*4882a593Smuzhiyun  * This key type is essentially the same as key_type_user, but it does
39*4882a593Smuzhiyun  * not define a .read op. This is suitable for storing username and
40*4882a593Smuzhiyun  * password pairs in the keyring that you do not want to be readable
41*4882a593Smuzhiyun  * from userspace.
42*4882a593Smuzhiyun  */
43*4882a593Smuzhiyun struct key_type key_type_logon = {
44*4882a593Smuzhiyun 	.name			= "logon",
45*4882a593Smuzhiyun 	.preparse		= user_preparse,
46*4882a593Smuzhiyun 	.free_preparse		= user_free_preparse,
47*4882a593Smuzhiyun 	.instantiate		= generic_key_instantiate,
48*4882a593Smuzhiyun 	.update			= user_update,
49*4882a593Smuzhiyun 	.revoke			= user_revoke,
50*4882a593Smuzhiyun 	.destroy		= user_destroy,
51*4882a593Smuzhiyun 	.describe		= user_describe,
52*4882a593Smuzhiyun 	.vet_description	= logon_vet_description,
53*4882a593Smuzhiyun };
54*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(key_type_logon);
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun /*
57*4882a593Smuzhiyun  * Preparse a user defined key payload
58*4882a593Smuzhiyun  */
user_preparse(struct key_preparsed_payload * prep)59*4882a593Smuzhiyun int user_preparse(struct key_preparsed_payload *prep)
60*4882a593Smuzhiyun {
61*4882a593Smuzhiyun 	struct user_key_payload *upayload;
62*4882a593Smuzhiyun 	size_t datalen = prep->datalen;
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun 	if (datalen <= 0 || datalen > 32767 || !prep->data)
65*4882a593Smuzhiyun 		return -EINVAL;
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun 	upayload = kmalloc(sizeof(*upayload) + datalen, GFP_KERNEL);
68*4882a593Smuzhiyun 	if (!upayload)
69*4882a593Smuzhiyun 		return -ENOMEM;
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun 	/* attach the data */
72*4882a593Smuzhiyun 	prep->quotalen = datalen;
73*4882a593Smuzhiyun 	prep->payload.data[0] = upayload;
74*4882a593Smuzhiyun 	upayload->datalen = datalen;
75*4882a593Smuzhiyun 	memcpy(upayload->data, prep->data, datalen);
76*4882a593Smuzhiyun 	return 0;
77*4882a593Smuzhiyun }
78*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(user_preparse);
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun /*
81*4882a593Smuzhiyun  * Free a preparse of a user defined key payload
82*4882a593Smuzhiyun  */
user_free_preparse(struct key_preparsed_payload * prep)83*4882a593Smuzhiyun void user_free_preparse(struct key_preparsed_payload *prep)
84*4882a593Smuzhiyun {
85*4882a593Smuzhiyun 	kfree_sensitive(prep->payload.data[0]);
86*4882a593Smuzhiyun }
87*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(user_free_preparse);
88*4882a593Smuzhiyun 
user_free_payload_rcu(struct rcu_head * head)89*4882a593Smuzhiyun static void user_free_payload_rcu(struct rcu_head *head)
90*4882a593Smuzhiyun {
91*4882a593Smuzhiyun 	struct user_key_payload *payload;
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun 	payload = container_of(head, struct user_key_payload, rcu);
94*4882a593Smuzhiyun 	kfree_sensitive(payload);
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun /*
98*4882a593Smuzhiyun  * update a user defined key
99*4882a593Smuzhiyun  * - the key's semaphore is write-locked
100*4882a593Smuzhiyun  */
user_update(struct key * key,struct key_preparsed_payload * prep)101*4882a593Smuzhiyun int user_update(struct key *key, struct key_preparsed_payload *prep)
102*4882a593Smuzhiyun {
103*4882a593Smuzhiyun 	struct user_key_payload *zap = NULL;
104*4882a593Smuzhiyun 	int ret;
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun 	/* check the quota and attach the new data */
107*4882a593Smuzhiyun 	ret = key_payload_reserve(key, prep->datalen);
108*4882a593Smuzhiyun 	if (ret < 0)
109*4882a593Smuzhiyun 		return ret;
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun 	/* attach the new data, displacing the old */
112*4882a593Smuzhiyun 	key->expiry = prep->expiry;
113*4882a593Smuzhiyun 	if (key_is_positive(key))
114*4882a593Smuzhiyun 		zap = dereference_key_locked(key);
115*4882a593Smuzhiyun 	rcu_assign_keypointer(key, prep->payload.data[0]);
116*4882a593Smuzhiyun 	prep->payload.data[0] = NULL;
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun 	if (zap)
119*4882a593Smuzhiyun 		call_rcu(&zap->rcu, user_free_payload_rcu);
120*4882a593Smuzhiyun 	return ret;
121*4882a593Smuzhiyun }
122*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(user_update);
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun /*
125*4882a593Smuzhiyun  * dispose of the links from a revoked keyring
126*4882a593Smuzhiyun  * - called with the key sem write-locked
127*4882a593Smuzhiyun  */
user_revoke(struct key * key)128*4882a593Smuzhiyun void user_revoke(struct key *key)
129*4882a593Smuzhiyun {
130*4882a593Smuzhiyun 	struct user_key_payload *upayload = user_key_payload_locked(key);
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun 	/* clear the quota */
133*4882a593Smuzhiyun 	key_payload_reserve(key, 0);
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun 	if (upayload) {
136*4882a593Smuzhiyun 		rcu_assign_keypointer(key, NULL);
137*4882a593Smuzhiyun 		call_rcu(&upayload->rcu, user_free_payload_rcu);
138*4882a593Smuzhiyun 	}
139*4882a593Smuzhiyun }
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun EXPORT_SYMBOL(user_revoke);
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun /*
144*4882a593Smuzhiyun  * dispose of the data dangling from the corpse of a user key
145*4882a593Smuzhiyun  */
user_destroy(struct key * key)146*4882a593Smuzhiyun void user_destroy(struct key *key)
147*4882a593Smuzhiyun {
148*4882a593Smuzhiyun 	struct user_key_payload *upayload = key->payload.data[0];
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun 	kfree_sensitive(upayload);
151*4882a593Smuzhiyun }
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(user_destroy);
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun /*
156*4882a593Smuzhiyun  * describe the user key
157*4882a593Smuzhiyun  */
user_describe(const struct key * key,struct seq_file * m)158*4882a593Smuzhiyun void user_describe(const struct key *key, struct seq_file *m)
159*4882a593Smuzhiyun {
160*4882a593Smuzhiyun 	seq_puts(m, key->description);
161*4882a593Smuzhiyun 	if (key_is_positive(key))
162*4882a593Smuzhiyun 		seq_printf(m, ": %u", key->datalen);
163*4882a593Smuzhiyun }
164*4882a593Smuzhiyun 
165*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(user_describe);
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun /*
168*4882a593Smuzhiyun  * read the key data
169*4882a593Smuzhiyun  * - the key's semaphore is read-locked
170*4882a593Smuzhiyun  */
user_read(const struct key * key,char * buffer,size_t buflen)171*4882a593Smuzhiyun long user_read(const struct key *key, char *buffer, size_t buflen)
172*4882a593Smuzhiyun {
173*4882a593Smuzhiyun 	const struct user_key_payload *upayload;
174*4882a593Smuzhiyun 	long ret;
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun 	upayload = user_key_payload_locked(key);
177*4882a593Smuzhiyun 	ret = upayload->datalen;
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun 	/* we can return the data as is */
180*4882a593Smuzhiyun 	if (buffer && buflen > 0) {
181*4882a593Smuzhiyun 		if (buflen > upayload->datalen)
182*4882a593Smuzhiyun 			buflen = upayload->datalen;
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun 		memcpy(buffer, upayload->data, buflen);
185*4882a593Smuzhiyun 	}
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun 	return ret;
188*4882a593Smuzhiyun }
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(user_read);
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun /* Vet the description for a "logon" key */
logon_vet_description(const char * desc)193*4882a593Smuzhiyun static int logon_vet_description(const char *desc)
194*4882a593Smuzhiyun {
195*4882a593Smuzhiyun 	char *p;
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun 	/* require a "qualified" description string */
198*4882a593Smuzhiyun 	p = strchr(desc, ':');
199*4882a593Smuzhiyun 	if (!p)
200*4882a593Smuzhiyun 		return -EINVAL;
201*4882a593Smuzhiyun 
202*4882a593Smuzhiyun 	/* also reject description with ':' as first char */
203*4882a593Smuzhiyun 	if (p == desc)
204*4882a593Smuzhiyun 		return -EINVAL;
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun 	return 0;
207*4882a593Smuzhiyun }
208