File Index
Files and directories
Sign in
FILE

rpc.c

File preview with syntax highlighting.

linux-6.19.14/drivers/tee/optee/rpc.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright (c) 2015-2021, Linaro Limited
  4 */
  5
  6#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  7
  8#include <linux/delay.h>
  9#include <linux/i2c.h>
 10#include <linux/rpmb.h>
 11#include <linux/slab.h>
 12#include <linux/tee_core.h>
 13#include "optee_private.h"
 14#include "optee_rpc_cmd.h"
 15
 16static void handle_rpc_func_cmd_get_time(struct optee_msg_arg *arg)
 17{
 18	struct timespec64 ts;
 19
 20	if (arg->num_params != 1)
 21		goto bad;
 22	if ((arg->params[0].attr & OPTEE_MSG_ATTR_TYPE_MASK) !=
 23			OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT)
 24		goto bad;
 25
 26	ktime_get_real_ts64(&ts);
 27	arg->params[0].u.value.a = ts.tv_sec;
 28	arg->params[0].u.value.b = ts.tv_nsec;
 29
 30	arg->ret = TEEC_SUCCESS;
 31	return;
 32bad:
 33	arg->ret = TEEC_ERROR_BAD_PARAMETERS;
 34}
 35
 36#if IS_REACHABLE(CONFIG_I2C)
 37static void handle_rpc_func_cmd_i2c_transfer(struct tee_context *ctx,
 38					     struct optee_msg_arg *arg)
 39{
 40	struct optee *optee = tee_get_drvdata(ctx->teedev);
 41	struct tee_param *params;
 42	struct i2c_adapter *adapter;
 43	struct i2c_msg msg = { };
 44	size_t i;
 45	int ret = -EOPNOTSUPP;
 46	u8 attr[] = {
 47		TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT,
 48		TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT,
 49		TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT,
 50		TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT,
 51	};
 52
 53	if (arg->num_params != ARRAY_SIZE(attr)) {
 54		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
 55		return;
 56	}
 57
 58	params = kmalloc_array(arg->num_params, sizeof(struct tee_param),
 59			       GFP_KERNEL);
 60	if (!params) {
 61		arg->ret = TEEC_ERROR_OUT_OF_MEMORY;
 62		return;
 63	}
 64
 65	if (optee->ops->from_msg_param(optee, params, arg->num_params,
 66				       arg->params))
 67		goto bad;
 68
 69	for (i = 0; i < arg->num_params; i++) {
 70		if (params[i].attr != attr[i])
 71			goto bad;
 72	}
 73
 74	adapter = i2c_get_adapter(params[0].u.value.b);
 75	if (!adapter)
 76		goto bad;
 77
 78	if (params[1].u.value.a & OPTEE_RPC_I2C_FLAGS_TEN_BIT) {
 79		if (!i2c_check_functionality(adapter,
 80					     I2C_FUNC_10BIT_ADDR)) {
 81			i2c_put_adapter(adapter);
 82			goto bad;
 83		}
 84
 85		msg.flags = I2C_M_TEN;
 86	}
 87
 88	msg.addr = params[0].u.value.c;
 89	msg.buf  = params[2].u.memref.shm->kaddr;
 90	msg.len  = params[2].u.memref.size;
 91
 92	switch (params[0].u.value.a) {
 93	case OPTEE_RPC_I2C_TRANSFER_RD:
 94		msg.flags |= I2C_M_RD;
 95		break;
 96	case OPTEE_RPC_I2C_TRANSFER_WR:
 97		break;
 98	default:
 99		i2c_put_adapter(adapter);
100		goto bad;
101	}
102
103	ret = i2c_transfer(adapter, &msg, 1);
104
105	if (ret < 0) {
106		arg->ret = TEEC_ERROR_COMMUNICATION;
107	} else {
108		params[3].u.value.a = msg.len;
109		if (optee->ops->to_msg_param(optee, arg->params,
110					     arg->num_params, params))
111			arg->ret = TEEC_ERROR_BAD_PARAMETERS;
112		else
113			arg->ret = TEEC_SUCCESS;
114	}
115
116	i2c_put_adapter(adapter);
117	kfree(params);
118	return;
119bad:
120	kfree(params);
121	arg->ret = TEEC_ERROR_BAD_PARAMETERS;
122}
123#else
124static void handle_rpc_func_cmd_i2c_transfer(struct tee_context *ctx,
125					     struct optee_msg_arg *arg)
126{
127	arg->ret = TEEC_ERROR_NOT_SUPPORTED;
128}
129#endif
130
131static void handle_rpc_func_cmd_wq(struct optee *optee,
132				   struct optee_msg_arg *arg)
133{
134	int rc = 0;
135
136	if (arg->num_params != 1)
137		goto bad;
138
139	if ((arg->params[0].attr & OPTEE_MSG_ATTR_TYPE_MASK) !=
140			OPTEE_MSG_ATTR_TYPE_VALUE_INPUT)
141		goto bad;
142
143	switch (arg->params[0].u.value.a) {
144	case OPTEE_RPC_NOTIFICATION_WAIT:
145		rc = optee_notif_wait(optee, arg->params[0].u.value.b, arg->params[0].u.value.c);
146		if (rc)
147			goto bad;
148		break;
149	case OPTEE_RPC_NOTIFICATION_SEND:
150		if (optee_notif_send(optee, arg->params[0].u.value.b))
151			goto bad;
152		break;
153	default:
154		goto bad;
155	}
156
157	arg->ret = TEEC_SUCCESS;
158	return;
159bad:
160	if (rc == -ETIMEDOUT)
161		arg->ret = TEE_ERROR_TIMEOUT;
162	else
163		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
164}
165
166static void handle_rpc_func_cmd_wait(struct optee_msg_arg *arg)
167{
168	u32 msec_to_wait;
169
170	if (arg->num_params != 1)
171		goto bad;
172
173	if ((arg->params[0].attr & OPTEE_MSG_ATTR_TYPE_MASK) !=
174			OPTEE_MSG_ATTR_TYPE_VALUE_INPUT)
175		goto bad;
176
177	msec_to_wait = arg->params[0].u.value.a;
178
179	/* Go to interruptible sleep */
180	msleep_interruptible(msec_to_wait);
181
182	arg->ret = TEEC_SUCCESS;
183	return;
184bad:
185	arg->ret = TEEC_ERROR_BAD_PARAMETERS;
186}
187
188static void handle_rpc_supp_cmd(struct tee_context *ctx, struct optee *optee,
189				struct optee_msg_arg *arg)
190{
191	struct tee_param *params;
192
193	arg->ret_origin = TEEC_ORIGIN_COMMS;
194
195	params = kmalloc_array(arg->num_params, sizeof(struct tee_param),
196			       GFP_KERNEL);
197	if (!params) {
198		arg->ret = TEEC_ERROR_OUT_OF_MEMORY;
199		return;
200	}
201
202	if (optee->ops->from_msg_param(optee, params, arg->num_params,
203				       arg->params)) {
204		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
205		goto out;
206	}
207
208	arg->ret = optee_supp_thrd_req(ctx, arg->cmd, arg->num_params, params);
209
210	if (optee->ops->to_msg_param(optee, arg->params, arg->num_params,
211				     params))
212		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
213out:
214	kfree(params);
215}
216
217struct tee_shm *optee_rpc_cmd_alloc_suppl(struct tee_context *ctx, size_t sz)
218{
219	u32 ret;
220	struct tee_param param;
221	struct optee *optee = tee_get_drvdata(ctx->teedev);
222	struct tee_shm *shm;
223
224	param.attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT;
225	param.u.value.a = OPTEE_RPC_SHM_TYPE_APPL;
226	param.u.value.b = sz;
227	param.u.value.c = 0;
228
229	ret = optee_supp_thrd_req(ctx, OPTEE_RPC_CMD_SHM_ALLOC, 1, &param);
230	if (ret)
231		return ERR_PTR(-ENOMEM);
232
233	mutex_lock(&optee->supp.mutex);
234	/* Increases count as secure world doesn't have a reference */
235	shm = tee_shm_get_from_id(optee->supp.ctx, param.u.value.c);
236	mutex_unlock(&optee->supp.mutex);
237	return shm;
238}
239
240void optee_rpc_cmd_free_suppl(struct tee_context *ctx, struct tee_shm *shm)
241{
242	struct tee_param param;
243
244	param.attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT;
245	param.u.value.a = OPTEE_RPC_SHM_TYPE_APPL;
246	param.u.value.b = tee_shm_get_id(shm);
247	param.u.value.c = 0;
248
249	/*
250	 * Match the tee_shm_get_from_id() in cmd_alloc_suppl() as secure
251	 * world has released its reference.
252	 *
253	 * It's better to do this before sending the request to supplicant
254	 * as we'd like to let the process doing the initial allocation to
255	 * do release the last reference too in order to avoid stacking
256	 * many pending fput() on the client process. This could otherwise
257	 * happen if secure world does many allocate and free in a single
258	 * invoke.
259	 */
260	tee_shm_put(shm);
261
262	optee_supp_thrd_req(ctx, OPTEE_RPC_CMD_SHM_FREE, 1, &param);
263}
264
265static void handle_rpc_func_rpmb_probe_reset(struct tee_context *ctx,
266					     struct optee *optee,
267					     struct optee_msg_arg *arg)
268{
269	struct tee_param params[1];
270
271	if (arg->num_params != ARRAY_SIZE(params) ||
272	    optee->ops->from_msg_param(optee, params, arg->num_params,
273				       arg->params) ||
274	    params[0].attr != TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT) {
275		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
276		return;
277	}
278
279	params[0].u.value.a = OPTEE_RPC_SHM_TYPE_KERNEL;
280	params[0].u.value.b = 0;
281	params[0].u.value.c = 0;
282	if (optee->ops->to_msg_param(optee, arg->params,
283				     arg->num_params, params)) {
284		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
285		return;
286	}
287
288	mutex_lock(&optee->rpmb_dev_mutex);
289	rpmb_dev_put(optee->rpmb_dev);
290	optee->rpmb_dev = NULL;
291	mutex_unlock(&optee->rpmb_dev_mutex);
292
293	arg->ret = TEEC_SUCCESS;
294}
295
296static int rpmb_type_to_rpc_type(enum rpmb_type rtype)
297{
298	switch (rtype) {
299	case RPMB_TYPE_EMMC:
300		return OPTEE_RPC_RPMB_EMMC;
301	case RPMB_TYPE_UFS:
302		return OPTEE_RPC_RPMB_UFS;
303	case RPMB_TYPE_NVME:
304		return OPTEE_RPC_RPMB_NVME;
305	default:
306		return -1;
307	}
308}
309
310static int rpc_rpmb_match(struct device *dev, const void *data)
311{
312	struct rpmb_dev *rdev = to_rpmb_dev(dev);
313
314	return rpmb_type_to_rpc_type(rdev->descr.type) >= 0;
315}
316
317static void handle_rpc_func_rpmb_probe_next(struct tee_context *ctx,
318					    struct optee *optee,
319					    struct optee_msg_arg *arg)
320{
321	struct rpmb_dev *rdev;
322	struct tee_param params[2];
323	void *buf;
324
325	if (arg->num_params != ARRAY_SIZE(params) ||
326	    optee->ops->from_msg_param(optee, params, arg->num_params,
327				       arg->params) ||
328	    params[0].attr != TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT ||
329	    params[1].attr != TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT) {
330		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
331		return;
332	}
333	buf = tee_shm_get_va(params[1].u.memref.shm,
334			     params[1].u.memref.shm_offs);
335	if (IS_ERR(buf)) {
336		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
337		return;
338	}
339
340	mutex_lock(&optee->rpmb_dev_mutex);
341	rdev = rpmb_dev_find_device(NULL, optee->rpmb_dev, rpc_rpmb_match);
342	rpmb_dev_put(optee->rpmb_dev);
343	optee->rpmb_dev = rdev;
344	mutex_unlock(&optee->rpmb_dev_mutex);
345
346	if (!rdev) {
347		arg->ret = TEEC_ERROR_ITEM_NOT_FOUND;
348		return;
349	}
350
351	if (params[1].u.memref.size < rdev->descr.dev_id_len) {
352		arg->ret = TEEC_ERROR_SHORT_BUFFER;
353		return;
354	}
355	memcpy(buf, rdev->descr.dev_id, rdev->descr.dev_id_len);
356	params[1].u.memref.size = rdev->descr.dev_id_len;
357	params[0].u.value.a = rpmb_type_to_rpc_type(rdev->descr.type);
358	params[0].u.value.b = rdev->descr.capacity;
359	params[0].u.value.c = rdev->descr.reliable_wr_count;
360	if (optee->ops->to_msg_param(optee, arg->params,
361				     arg->num_params, params)) {
362		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
363		return;
364	}
365
366	arg->ret = TEEC_SUCCESS;
367}
368
369static void handle_rpc_func_rpmb_frames(struct tee_context *ctx,
370					struct optee *optee,
371					struct optee_msg_arg *arg)
372{
373	struct tee_param params[2];
374	struct rpmb_dev *rdev;
375	void *p0, *p1;
376
377	mutex_lock(&optee->rpmb_dev_mutex);
378	rdev = rpmb_dev_get(optee->rpmb_dev);
379	mutex_unlock(&optee->rpmb_dev_mutex);
380	if (!rdev) {
381		arg->ret = TEEC_ERROR_ITEM_NOT_FOUND;
382		return;
383	}
384
385	if (arg->num_params != ARRAY_SIZE(params) ||
386	    optee->ops->from_msg_param(optee, params, arg->num_params,
387				       arg->params) ||
388	    params[0].attr != TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT ||
389	    params[1].attr != TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT) {
390		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
391		goto out;
392	}
393
394	p0 = tee_shm_get_va(params[0].u.memref.shm,
395			    params[0].u.memref.shm_offs);
396	p1 = tee_shm_get_va(params[1].u.memref.shm,
397			    params[1].u.memref.shm_offs);
398	if (rpmb_route_frames(rdev, p0, params[0].u.memref.size, p1,
399			      params[1].u.memref.size)) {
400		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
401		goto out;
402	}
403	if (optee->ops->to_msg_param(optee, arg->params,
404				     arg->num_params, params)) {
405		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
406		goto out;
407	}
408	arg->ret = TEEC_SUCCESS;
409out:
410	rpmb_dev_put(rdev);
411}
412
413void optee_rpc_cmd(struct tee_context *ctx, struct optee *optee,
414		   struct optee_msg_arg *arg)
415{
416	switch (arg->cmd) {
417	case OPTEE_RPC_CMD_GET_TIME:
418		handle_rpc_func_cmd_get_time(arg);
419		break;
420	case OPTEE_RPC_CMD_NOTIFICATION:
421		handle_rpc_func_cmd_wq(optee, arg);
422		break;
423	case OPTEE_RPC_CMD_SUSPEND:
424		handle_rpc_func_cmd_wait(arg);
425		break;
426	case OPTEE_RPC_CMD_I2C_TRANSFER:
427		handle_rpc_func_cmd_i2c_transfer(ctx, arg);
428		break;
429	/*
430	 * optee->in_kernel_rpmb_routing true means that OP-TEE supports
431	 * in-kernel RPMB routing _and_ that the RPMB subsystem is
432	 * reachable. This is reported to user space with
433	 * rpmb_routing_model=kernel in sysfs.
434	 *
435	 * rpmb_routing_model=kernel is also a promise to user space that
436	 * RPMB access will not require supplicant support, hence the
437	 * checks below.
438	 */
439	case OPTEE_RPC_CMD_RPMB_PROBE_RESET:
440		if (optee->in_kernel_rpmb_routing)
441			handle_rpc_func_rpmb_probe_reset(ctx, optee, arg);
442		else
443			handle_rpc_supp_cmd(ctx, optee, arg);
444		break;
445	case OPTEE_RPC_CMD_RPMB_PROBE_NEXT:
446		if (optee->in_kernel_rpmb_routing)
447			handle_rpc_func_rpmb_probe_next(ctx, optee, arg);
448		else
449			handle_rpc_supp_cmd(ctx, optee, arg);
450		break;
451	case OPTEE_RPC_CMD_RPMB_FRAMES:
452		if (optee->in_kernel_rpmb_routing)
453			handle_rpc_func_rpmb_frames(ctx, optee, arg);
454		else
455			handle_rpc_supp_cmd(ctx, optee, arg);
456		break;
457	default:
458		handle_rpc_supp_cmd(ctx, optee, arg);
459	}
460}
461
462
~/ Read-only file preview.