remoteproc: Fix potential race condition in rproc_add
authorDave Gerlach <d-gerlach@ti.com>
Wed, 25 May 2016 20:41:28 +0000 (15:41 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 20 Aug 2016 16:09:20 +0000 (18:09 +0200)
commit d2e12e66a939c54ed84e5f1b6947f0c45f6c56eb upstream.

rproc_add adds the newly created remoteproc to a list for use by
rproc_get_by_phandle and then does some additional processing to finish
adding the remoteproc. This leaves a small window of time in which the
rproc is available in the list but not yet fully initialized, so if
another driver comes along and gets a handle to the rproc, it will be
invalid. Rearrange the code in rproc_add to make sure the rproc is added
to the list only after it has been successfuly initialized.

Fixes: fec47d863587 ("remoteproc: introduce rproc_get_by_phandle API")
Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/remoteproc/remoteproc_core.c

index 9e03d158f4119133f09b0979d8b5b70e1ae63c06..4f7ce0097191d5ae0c4b351ddb25c179b19231ee 100644 (file)
@@ -1239,11 +1239,6 @@ int rproc_add(struct rproc *rproc)
        if (ret < 0)
                return ret;
 
-       /* expose to rproc_get_by_phandle users */
-       mutex_lock(&rproc_list_mutex);
-       list_add(&rproc->node, &rproc_list);
-       mutex_unlock(&rproc_list_mutex);
-
        dev_info(dev, "%s is available\n", rproc->name);
 
        dev_info(dev, "Note: remoteproc is still under development and considered experimental.\n");
@@ -1251,8 +1246,16 @@ int rproc_add(struct rproc *rproc)
 
        /* create debugfs entries */
        rproc_create_debug_dir(rproc);
+       ret = rproc_add_virtio_devices(rproc);
+       if (ret < 0)
+               return ret;
 
-       return rproc_add_virtio_devices(rproc);
+       /* expose to rproc_get_by_phandle users */
+       mutex_lock(&rproc_list_mutex);
+       list_add(&rproc->node, &rproc_list);
+       mutex_unlock(&rproc_list_mutex);
+
+       return 0;
 }
 EXPORT_SYMBOL(rproc_add);