diff options
Diffstat (limited to 'drivers/tee/tee_core.c')
-rw-r--r-- | drivers/tee/tee_core.c | 89 |
1 files changed, 38 insertions, 51 deletions
diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c index 64637e09a095..f53bf336c0a2 100644 --- a/drivers/tee/tee_core.c +++ b/drivers/tee/tee_core.c @@ -383,25 +383,38 @@ static int params_from_user(struct tee_context *ctx, struct tee_param *params, case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT: case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT: /* - * If we fail to get a pointer to a shared memory - * object (and increase the ref count) from an - * identifier we return an error. All pointers that - * has been added in params have an increased ref - * count. It's the callers responibility to do - * tee_shm_put() on all resolved pointers. + * If a NULL pointer is passed to a TA in the TEE, + * the ip.c IOCTL parameters is set to TEE_MEMREF_NULL + * indicating a NULL memory reference. */ - shm = tee_shm_get_from_id(ctx, ip.c); - if (IS_ERR(shm)) - return PTR_ERR(shm); - - /* - * Ensure offset + size does not overflow offset - * and does not overflow the size of the referred - * shared memory object. - */ - if ((ip.a + ip.b) < ip.a || - (ip.a + ip.b) > shm->size) { - tee_shm_put(shm); + if (ip.c != TEE_MEMREF_NULL) { + /* + * If we fail to get a pointer to a shared + * memory object (and increase the ref count) + * from an identifier we return an error. All + * pointers that has been added in params have + * an increased ref count. It's the callers + * responibility to do tee_shm_put() on all + * resolved pointers. + */ + shm = tee_shm_get_from_id(ctx, ip.c); + if (IS_ERR(shm)) + return PTR_ERR(shm); + + /* + * Ensure offset + size does not overflow + * offset and does not overflow the size of + * the referred shared memory object. + */ + if ((ip.a + ip.b) < ip.a || + (ip.a + ip.b) > shm->size) { + tee_shm_put(shm); + return -EINVAL; + } + } else if (ctx->cap_memref_null) { + /* Pass NULL pointer to OP-TEE */ + shm = NULL; + } else { return -EINVAL; } @@ -917,7 +930,6 @@ struct tee_device *tee_device_alloc(const struct tee_desc *teedesc, cdev_init(&teedev->cdev, &tee_fops); teedev->cdev.owner = teedesc->owner; - teedev->cdev.kobj.parent = &teedev->dev.kobj; dev_set_drvdata(&teedev->dev, driver_data); device_initialize(&teedev->dev); @@ -963,9 +975,7 @@ static struct attribute *tee_dev_attrs[] = { NULL }; -static const struct attribute_group tee_dev_group = { - .attrs = tee_dev_attrs, -}; +ATTRIBUTE_GROUPS(tee_dev); /** * tee_device_register() - Registers a TEE device @@ -985,39 +995,19 @@ int tee_device_register(struct tee_device *teedev) return -EINVAL; } - rc = cdev_add(&teedev->cdev, teedev->dev.devt, 1); - if (rc) { - dev_err(&teedev->dev, - "unable to cdev_add() %s, major %d, minor %d, err=%d\n", - teedev->name, MAJOR(teedev->dev.devt), - MINOR(teedev->dev.devt), rc); - return rc; - } + teedev->dev.groups = tee_dev_groups; - rc = device_add(&teedev->dev); + rc = cdev_device_add(&teedev->cdev, &teedev->dev); if (rc) { dev_err(&teedev->dev, - "unable to device_add() %s, major %d, minor %d, err=%d\n", + "unable to cdev_device_add() %s, major %d, minor %d, err=%d\n", teedev->name, MAJOR(teedev->dev.devt), MINOR(teedev->dev.devt), rc); - goto err_device_add; - } - - rc = sysfs_create_group(&teedev->dev.kobj, &tee_dev_group); - if (rc) { - dev_err(&teedev->dev, - "failed to create sysfs attributes, err=%d\n", rc); - goto err_sysfs_create_group; + return rc; } teedev->flags |= TEE_DEVICE_FLAG_REGISTERED; return 0; - -err_sysfs_create_group: - device_del(&teedev->dev); -err_device_add: - cdev_del(&teedev->cdev); - return rc; } EXPORT_SYMBOL_GPL(tee_device_register); @@ -1060,11 +1050,8 @@ void tee_device_unregister(struct tee_device *teedev) if (!teedev) return; - if (teedev->flags & TEE_DEVICE_FLAG_REGISTERED) { - sysfs_remove_group(&teedev->dev.kobj, &tee_dev_group); - cdev_del(&teedev->cdev); - device_del(&teedev->dev); - } + if (teedev->flags & TEE_DEVICE_FLAG_REGISTERED) + cdev_device_del(&teedev->cdev, &teedev->dev); tee_device_put(teedev); wait_for_completion(&teedev->c_no_users); |