tee: fix possible error pointer ctx dereferencing
[sfrench/cifs-2.6.git] / drivers / tee / tee_core.c
index 7b2bb4c500580099a2f6e443da6fab9e4db7ae00..06fbfc044ea33ea0926bb7af3200e2ddb3e48796 100644 (file)
@@ -15,7 +15,6 @@
 #define pr_fmt(fmt) "%s: " fmt, __func__
 
 #include <linux/cdev.h>
-#include <linux/device.h>
 #include <linux/fs.h>
 #include <linux/idr.h>
 #include <linux/module.h>
@@ -106,6 +105,11 @@ static int tee_open(struct inode *inode, struct file *filp)
        if (IS_ERR(ctx))
                return PTR_ERR(ctx);
 
+       /*
+        * Default user-space behaviour is to wait for tee-supplicant
+        * if not present for any requests in this context.
+        */
+       ctx->supp_nowait = false;
        filp->private_data = ctx;
        return 0;
 }
@@ -982,6 +986,16 @@ tee_client_open_context(struct tee_context *start,
        } while (IS_ERR(ctx) && PTR_ERR(ctx) != -ENOMEM);
 
        put_device(put_dev);
+       /*
+        * Default behaviour for in kernel client is to not wait for
+        * tee-supplicant if not present for any requests in this context.
+        * Also this flag could be configured again before call to
+        * tee_client_open_session() if any in kernel client requires
+        * different behaviour.
+        */
+       if (!IS_ERR(ctx))
+               ctx->supp_nowait = true;
+
        return ctx;
 }
 EXPORT_SYMBOL_GPL(tee_client_open_context);
@@ -1027,6 +1041,39 @@ int tee_client_invoke_func(struct tee_context *ctx,
 }
 EXPORT_SYMBOL_GPL(tee_client_invoke_func);
 
+static int tee_client_device_match(struct device *dev,
+                                  struct device_driver *drv)
+{
+       const struct tee_client_device_id *id_table;
+       struct tee_client_device *tee_device;
+
+       id_table = to_tee_client_driver(drv)->id_table;
+       tee_device = to_tee_client_device(dev);
+
+       while (!uuid_is_null(&id_table->uuid)) {
+               if (uuid_equal(&tee_device->id.uuid, &id_table->uuid))
+                       return 1;
+               id_table++;
+       }
+
+       return 0;
+}
+
+static int tee_client_device_uevent(struct device *dev,
+                                   struct kobj_uevent_env *env)
+{
+       uuid_t *dev_id = &to_tee_client_device(dev)->id.uuid;
+
+       return add_uevent_var(env, "MODALIAS=tee:%pUb", dev_id);
+}
+
+struct bus_type tee_bus_type = {
+       .name           = "tee",
+       .match          = tee_client_device_match,
+       .uevent         = tee_client_device_uevent,
+};
+EXPORT_SYMBOL_GPL(tee_bus_type);
+
 static int __init tee_init(void)
 {
        int rc;
@@ -1040,18 +1087,32 @@ static int __init tee_init(void)
        rc = alloc_chrdev_region(&tee_devt, 0, TEE_NUM_DEVICES, "tee");
        if (rc) {
                pr_err("failed to allocate char dev region\n");
-               class_destroy(tee_class);
-               tee_class = NULL;
+               goto out_unreg_class;
        }
 
+       rc = bus_register(&tee_bus_type);
+       if (rc) {
+               pr_err("failed to register tee bus\n");
+               goto out_unreg_chrdev;
+       }
+
+       return 0;
+
+out_unreg_chrdev:
+       unregister_chrdev_region(tee_devt, TEE_NUM_DEVICES);
+out_unreg_class:
+       class_destroy(tee_class);
+       tee_class = NULL;
+
        return rc;
 }
 
 static void __exit tee_exit(void)
 {
+       bus_unregister(&tee_bus_type);
+       unregister_chrdev_region(tee_devt, TEE_NUM_DEVICES);
        class_destroy(tee_class);
        tee_class = NULL;
-       unregister_chrdev_region(tee_devt, TEE_NUM_DEVICES);
 }
 
 subsys_initcall(tee_init);