cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

device.c (4201B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (C) 2019 Linaro Ltd.
      4 */
      5
      6#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
      7
      8#include <linux/kernel.h>
      9#include <linux/slab.h>
     10#include <linux/tee_drv.h>
     11#include <linux/uuid.h>
     12#include "optee_private.h"
     13
     14static int optee_ctx_match(struct tee_ioctl_version_data *ver, const void *data)
     15{
     16	if (ver->impl_id == TEE_IMPL_ID_OPTEE)
     17		return 1;
     18	else
     19		return 0;
     20}
     21
     22static int get_devices(struct tee_context *ctx, u32 session,
     23		       struct tee_shm *device_shm, u32 *shm_size,
     24		       u32 func)
     25{
     26	int ret = 0;
     27	struct tee_ioctl_invoke_arg inv_arg;
     28	struct tee_param param[4];
     29
     30	memset(&inv_arg, 0, sizeof(inv_arg));
     31	memset(&param, 0, sizeof(param));
     32
     33	inv_arg.func = func;
     34	inv_arg.session = session;
     35	inv_arg.num_params = 4;
     36
     37	/* Fill invoke cmd params */
     38	param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT;
     39	param[0].u.memref.shm = device_shm;
     40	param[0].u.memref.size = *shm_size;
     41	param[0].u.memref.shm_offs = 0;
     42
     43	ret = tee_client_invoke_func(ctx, &inv_arg, param);
     44	if ((ret < 0) || ((inv_arg.ret != TEEC_SUCCESS) &&
     45			  (inv_arg.ret != TEEC_ERROR_SHORT_BUFFER))) {
     46		pr_err("PTA_CMD_GET_DEVICES invoke function err: %x\n",
     47		       inv_arg.ret);
     48		return -EINVAL;
     49	}
     50
     51	*shm_size = param[0].u.memref.size;
     52
     53	return 0;
     54}
     55
     56static void optee_release_device(struct device *dev)
     57{
     58	struct tee_client_device *optee_device = to_tee_client_device(dev);
     59
     60	kfree(optee_device);
     61}
     62
     63static int optee_register_device(const uuid_t *device_uuid)
     64{
     65	struct tee_client_device *optee_device = NULL;
     66	int rc;
     67
     68	optee_device = kzalloc(sizeof(*optee_device), GFP_KERNEL);
     69	if (!optee_device)
     70		return -ENOMEM;
     71
     72	optee_device->dev.bus = &tee_bus_type;
     73	optee_device->dev.release = optee_release_device;
     74	if (dev_set_name(&optee_device->dev, "optee-ta-%pUb", device_uuid)) {
     75		kfree(optee_device);
     76		return -ENOMEM;
     77	}
     78	uuid_copy(&optee_device->id.uuid, device_uuid);
     79
     80	rc = device_register(&optee_device->dev);
     81	if (rc) {
     82		pr_err("device registration failed, err: %d\n", rc);
     83		kfree(optee_device);
     84	}
     85
     86	return rc;
     87}
     88
     89static int __optee_enumerate_devices(u32 func)
     90{
     91	const uuid_t pta_uuid =
     92		UUID_INIT(0x7011a688, 0xddde, 0x4053,
     93			  0xa5, 0xa9, 0x7b, 0x3c, 0x4d, 0xdf, 0x13, 0xb8);
     94	struct tee_ioctl_open_session_arg sess_arg;
     95	struct tee_shm *device_shm = NULL;
     96	const uuid_t *device_uuid = NULL;
     97	struct tee_context *ctx = NULL;
     98	u32 shm_size = 0, idx, num_devices = 0;
     99	int rc;
    100
    101	memset(&sess_arg, 0, sizeof(sess_arg));
    102
    103	/* Open context with OP-TEE driver */
    104	ctx = tee_client_open_context(NULL, optee_ctx_match, NULL, NULL);
    105	if (IS_ERR(ctx))
    106		return -ENODEV;
    107
    108	/* Open session with device enumeration pseudo TA */
    109	export_uuid(sess_arg.uuid, &pta_uuid);
    110	sess_arg.clnt_login = TEE_IOCTL_LOGIN_PUBLIC;
    111	sess_arg.num_params = 0;
    112
    113	rc = tee_client_open_session(ctx, &sess_arg, NULL);
    114	if ((rc < 0) || (sess_arg.ret != TEEC_SUCCESS)) {
    115		/* Device enumeration pseudo TA not found */
    116		rc = 0;
    117		goto out_ctx;
    118	}
    119
    120	rc = get_devices(ctx, sess_arg.session, NULL, &shm_size, func);
    121	if (rc < 0 || !shm_size)
    122		goto out_sess;
    123
    124	device_shm = tee_shm_alloc_kernel_buf(ctx, shm_size);
    125	if (IS_ERR(device_shm)) {
    126		pr_err("tee_shm_alloc_kernel_buf failed\n");
    127		rc = PTR_ERR(device_shm);
    128		goto out_sess;
    129	}
    130
    131	rc = get_devices(ctx, sess_arg.session, device_shm, &shm_size, func);
    132	if (rc < 0)
    133		goto out_shm;
    134
    135	device_uuid = tee_shm_get_va(device_shm, 0);
    136	if (IS_ERR(device_uuid)) {
    137		pr_err("tee_shm_get_va failed\n");
    138		rc = PTR_ERR(device_uuid);
    139		goto out_shm;
    140	}
    141
    142	num_devices = shm_size / sizeof(uuid_t);
    143
    144	for (idx = 0; idx < num_devices; idx++) {
    145		rc = optee_register_device(&device_uuid[idx]);
    146		if (rc)
    147			goto out_shm;
    148	}
    149
    150out_shm:
    151	tee_shm_free(device_shm);
    152out_sess:
    153	tee_client_close_session(ctx, sess_arg.session);
    154out_ctx:
    155	tee_client_close_context(ctx);
    156
    157	return rc;
    158}
    159
    160int optee_enumerate_devices(u32 func)
    161{
    162	return  __optee_enumerate_devices(func);
    163}
    164
    165static int __optee_unregister_device(struct device *dev, void *data)
    166{
    167	if (!strncmp(dev_name(dev), "optee-ta", strlen("optee-ta")))
    168		device_unregister(dev);
    169
    170	return 0;
    171}
    172
    173void optee_unregister_devices(void)
    174{
    175	bus_for_each_dev(&tee_bus_type, NULL, NULL,
    176			 __optee_unregister_device);
    177}