Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tee: add TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF

The TEE subsystem allows session-based access to trusted services,
requiring a session to be established to receive a service. This
is not suitable for an environment that represents services as objects.
An object supports various operations that a client can invoke,
potentially generating a result or a new object that can be invoked
independently of the original object.

Add TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_INPUT/OUTPUT/INOUT to represent an
object. Objects may reside in either TEE or userspace. To invoke an
object in TEE, introduce a new ioctl. Use the existing SUPPL_RECV and
SUPPL_SEND to invoke an object in userspace.

Reviewed-by: Sumit Garg <sumit.garg@oss.qualcomm.com>
Tested-by: Neil Armstrong <neil.armstrong@linaro.org>
Tested-by: Harshal Dev <quic_hdev@quicinc.com>
Signed-off-by: Amirreza Zarrabi <amirreza.zarrabi@oss.qualcomm.com>
Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>

authored by

Amirreza Zarrabi and committed by
Jens Wiklander
d5b8b0fa 54a53e95

+130 -6
+85
drivers/tee/tee_core.c
··· 487 487 switch (ip.attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) { 488 488 case TEE_IOCTL_PARAM_ATTR_TYPE_NONE: 489 489 case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT: 490 + case TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_OUTPUT: 490 491 break; 491 492 case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT: 492 493 case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT: ··· 505 504 params[n].u.ubuf.size)) 506 505 return -EFAULT; 507 506 507 + break; 508 + case TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_INPUT: 509 + case TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_INOUT: 510 + params[n].u.objref.id = ip.a; 511 + params[n].u.objref.flags = ip.b; 508 512 break; 509 513 case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT: 510 514 case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT: ··· 547 541 case TEE_IOCTL_PARAM_ATTR_TYPE_UBUF_OUTPUT: 548 542 case TEE_IOCTL_PARAM_ATTR_TYPE_UBUF_INOUT: 549 543 if (put_user((u64)p->u.ubuf.size, &up->b)) 544 + return -EFAULT; 545 + break; 546 + case TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_OUTPUT: 547 + case TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_INOUT: 548 + if (put_user(p->u.objref.id, &up->a) || 549 + put_user(p->u.objref.flags, &up->b)) 550 550 return -EFAULT; 551 551 break; 552 552 case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT: ··· 707 695 return rc; 708 696 } 709 697 698 + static int tee_ioctl_object_invoke(struct tee_context *ctx, 699 + struct tee_ioctl_buf_data __user *ubuf) 700 + { 701 + int rc; 702 + size_t n; 703 + struct tee_ioctl_buf_data buf; 704 + struct tee_ioctl_object_invoke_arg __user *uarg; 705 + struct tee_ioctl_object_invoke_arg arg; 706 + struct tee_ioctl_param __user *uparams = NULL; 707 + struct tee_param *params = NULL; 708 + 709 + if (!ctx->teedev->desc->ops->object_invoke_func) 710 + return -EINVAL; 711 + 712 + if (copy_from_user(&buf, ubuf, sizeof(buf))) 713 + return -EFAULT; 714 + 715 + if (buf.buf_len > TEE_MAX_ARG_SIZE || 716 + buf.buf_len < sizeof(struct tee_ioctl_object_invoke_arg)) 717 + return -EINVAL; 718 + 719 + uarg = u64_to_user_ptr(buf.buf_ptr); 720 + if (copy_from_user(&arg, uarg, sizeof(arg))) 721 + return -EFAULT; 722 + 723 + if (sizeof(arg) + TEE_IOCTL_PARAM_SIZE(arg.num_params) != buf.buf_len) 724 + return -EINVAL; 725 + 726 + if (arg.num_params) { 727 + params = kcalloc(arg.num_params, sizeof(struct tee_param), 728 + GFP_KERNEL); 729 + if (!params) 730 + return -ENOMEM; 731 + uparams = uarg->params; 732 + rc = params_from_user(ctx, params, arg.num_params, uparams); 733 + if (rc) 734 + goto out; 735 + } 736 + 737 + rc = ctx->teedev->desc->ops->object_invoke_func(ctx, &arg, params); 738 + if (rc) 739 + goto out; 740 + 741 + if (put_user(arg.ret, &uarg->ret)) { 742 + rc = -EFAULT; 743 + goto out; 744 + } 745 + rc = params_to_user(uparams, arg.num_params, params); 746 + out: 747 + if (params) { 748 + /* Decrease ref count for all valid shared memory pointers */ 749 + for (n = 0; n < arg.num_params; n++) 750 + if (tee_param_is_memref(params + n) && 751 + params[n].u.memref.shm) 752 + tee_shm_put(params[n].u.memref.shm); 753 + kfree(params); 754 + } 755 + return rc; 756 + } 757 + 710 758 static int tee_ioctl_cancel(struct tee_context *ctx, 711 759 struct tee_ioctl_cancel_arg __user *uarg) 712 760 { ··· 820 748 case TEE_IOCTL_PARAM_ATTR_TYPE_UBUF_INOUT: 821 749 ip.a = (__force unsigned long)p->u.ubuf.uaddr; 822 750 ip.b = p->u.ubuf.size; 751 + ip.c = 0; 752 + break; 753 + case TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_INPUT: 754 + case TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_INOUT: 755 + ip.a = p->u.objref.id; 756 + ip.b = p->u.objref.flags; 823 757 ip.c = 0; 824 758 break; 825 759 case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT: ··· 940 862 return -EFAULT; 941 863 942 864 break; 865 + case TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_OUTPUT: 866 + case TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_INOUT: 867 + p->u.objref.id = ip.a; 868 + p->u.objref.flags = ip.b; 869 + break; 943 870 case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT: 944 871 case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT: 945 872 /* ··· 1027 944 return tee_ioctl_open_session(ctx, uarg); 1028 945 case TEE_IOC_INVOKE: 1029 946 return tee_ioctl_invoke(ctx, uarg); 947 + case TEE_IOC_OBJECT_INVOKE: 948 + return tee_ioctl_object_invoke(ctx, uarg); 1030 949 case TEE_IOC_CANCEL: 1031 950 return tee_ioctl_cancel(ctx, uarg); 1032 951 case TEE_IOC_CLOSE_SESSION:
+4
include/linux/tee_core.h
··· 83 83 * @close_session: close a session 84 84 * @system_session: declare session as a system session 85 85 * @invoke_func: invoke a trusted function 86 + * @object_invoke_func: invoke a TEE object 86 87 * @cancel_req: request cancel of an ongoing invoke or open 87 88 * @supp_recv: called for supplicant to get a command 88 89 * @supp_send: called for supplicant to send a response ··· 109 108 int (*invoke_func)(struct tee_context *ctx, 110 109 struct tee_ioctl_invoke_arg *arg, 111 110 struct tee_param *param); 111 + int (*object_invoke_func)(struct tee_context *ctx, 112 + struct tee_ioctl_object_invoke_arg *arg, 113 + struct tee_param *param); 112 114 int (*cancel_req)(struct tee_context *ctx, u32 cancel_id, u32 session); 113 115 int (*supp_recv)(struct tee_context *ctx, u32 *func, u32 *num_params, 114 116 struct tee_param *param);
+6
include/linux/tee_drv.h
··· 87 87 size_t size; 88 88 }; 89 89 90 + struct tee_param_objref { 91 + u64 id; 92 + u64 flags; 93 + }; 94 + 90 95 struct tee_param_value { 91 96 u64 a; 92 97 u64 b; ··· 102 97 u64 attr; 103 98 union { 104 99 struct tee_param_memref memref; 100 + struct tee_param_objref objref; 105 101 struct tee_param_ubuf ubuf; 106 102 struct tee_param_value value; 107 103 } u;
+35 -6
include/uapi/linux/tee.h
··· 48 48 #define TEE_GEN_CAP_PRIVILEGED (1 << 1)/* Privileged device (for supplicant) */ 49 49 #define TEE_GEN_CAP_REG_MEM (1 << 2)/* Supports registering shared memory */ 50 50 #define TEE_GEN_CAP_MEMREF_NULL (1 << 3)/* NULL MemRef support */ 51 + #define TEE_GEN_CAP_OBJREF (1 << 4)/* Supports generic object reference */ 51 52 52 - #define TEE_MEMREF_NULL (__u64)(-1) /* NULL MemRef Buffer */ 53 + #define TEE_MEMREF_NULL ((__u64)(-1)) /* NULL MemRef Buffer */ 54 + #define TEE_OBJREF_NULL ((__u64)(-1)) /* NULL ObjRef Object */ 53 55 54 56 /* 55 57 * TEE Implementation ID ··· 161 159 #define TEE_IOCTL_PARAM_ATTR_TYPE_UBUF_INOUT 10 /* input and output */ 162 160 163 161 /* 162 + * These defines object reference parameters. 163 + */ 164 + #define TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_INPUT 11 165 + #define TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_OUTPUT 12 166 + #define TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_INOUT 13 167 + 168 + /* 164 169 * Mask for the type part of the attribute, leaves room for more types 165 170 */ 166 171 #define TEE_IOCTL_PARAM_ATTR_TYPE_MASK 0xff ··· 204 195 * @attr: attributes 205 196 * @a: if a memref, offset into the shared memory object, 206 197 * else if a ubuf, address of the user buffer, 207 - * else a value parameter 208 - * @b: if a memref or ubuf, size of the buffer, else a value parameter 198 + * else if an objref, object identifier, else a value parameter 199 + * @b: if a memref or ubuf, size of the buffer, 200 + * else if objref, flags for the object, else a value parameter 209 201 * @c: if a memref, shared memory identifier, else a value parameter 210 202 * 211 203 * @attr & TEE_PARAM_ATTR_TYPE_MASK indicates if memref, ubuf, or value is 212 204 * used in the union. TEE_PARAM_ATTR_TYPE_VALUE_* indicates value, 213 - * TEE_PARAM_ATTR_TYPE_MEMREF_* indicates memref, and TEE_PARAM_ATTR_TYPE_UBUF_* 214 - * indicates ubuf. TEE_PARAM_ATTR_TYPE_NONE indicates that none of the members 215 - * are used. 205 + * TEE_PARAM_ATTR_TYPE_MEMREF_* indicates memref, TEE_PARAM_ATTR_TYPE_UBUF_* 206 + * indicates ubuf, and TEE_PARAM_ATTR_TYPE_OBJREF_* indicates objref. 207 + * TEE_PARAM_ATTR_TYPE_NONE indicates that none of the members are used. 216 208 * 217 209 * Shared memory is allocated with TEE_IOC_SHM_ALLOC which returns an 218 210 * identifier representing the shared memory object. A memref can reference ··· 451 441 * tee_ioctl_shm_alloc_data 452 442 * munmap(): unmaps previously shared memory 453 443 */ 444 + 445 + /** 446 + * struct tee_ioctl_invoke_func_arg - Invokes an object in a Trusted Application 447 + * @id: [in] Object id 448 + * @op: [in] Object operation, specific to the object 449 + * @ret: [out] return value 450 + * @num_params: [in] number of parameters following this struct 451 + */ 452 + struct tee_ioctl_object_invoke_arg { 453 + __u64 id; 454 + __u32 op; 455 + __u32 ret; 456 + __u32 num_params; 457 + /* num_params tells the actual number of element in params */ 458 + struct tee_ioctl_param params[]; 459 + }; 460 + 461 + #define TEE_IOC_OBJECT_INVOKE _IOR(TEE_IOC_MAGIC, TEE_IOC_BASE + 10, \ 462 + struct tee_ioctl_buf_data) 454 463 455 464 #endif /*__TEE_H*/