All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH BlueZ] mesh: Fix getting managed objects from ObjectManager
@ 2019-12-17 14:54 Michał Lowas-Rzechonek
  2019-12-18 15:49 ` Gix, Brian
  0 siblings, 1 reply; 2+ messages in thread
From: Michał Lowas-Rzechonek @ 2019-12-17 14:54 UTC (permalink / raw)
  To: linux-bluetooth

D-Bus spec mandates that GetManagedObjects method of
org.freedesktop.DBus.ObjectManager interface returns *children* only:

https://dbus.freedesktop.org/doc/dbus-specification.html
> All returned object paths are children of the object path implementing
> this interface, i.e. their object paths start with the ObjectManager's
> object path plus '/'

Both test scripts and ELL abuse this by returning application interfaces
via ObjectManager attached to the same path, but other D-Bus
implementations do not, making Attach() fail because mandatory
interfaces cannot be found.

This patch fixes the issue by scanning hierarchy returned by
GetManagedObjects for object implementing org.bluez.mesh.Application1
interface and keeping that as node's app_path.
---
 doc/mesh-api.txt | 52 ++++++++++++++++++++++++++----------------------
 mesh/node.c      | 22 +++++++++++---------
 mesh/node.h      |  8 ++++----
 3 files changed, 45 insertions(+), 37 deletions(-)

diff --git a/doc/mesh-api.txt b/doc/mesh-api.txt
index 30b7452e2..ebff8492a 100644
--- a/doc/mesh-api.txt
+++ b/doc/mesh-api.txt
@@ -8,13 +8,13 @@ Interface	org.bluez.mesh.Network1
 Object path	/org/bluez/mesh
 
 Methods:
-	void Join(object app_defined_root, array{byte}[16] uuid)
+	void Join(object app_root, array{byte}[16] uuid)
 
 		This is the first method that an application has to call to
 		become a provisioned node on a mesh network. The call will
 		initiate broadcasting of Unprovisioned Device Beacon.
 
-		The app_defined_root parameter is a D-Bus object root path of
+		The app_root parameter is a D-Bus object root path of
 		the application that implements org.bluez.mesh.Application1
 		interface. The application represents a node where child mesh
 		elements have their own objects that implement
@@ -22,7 +22,7 @@ Methods:
 		also contains a provision agent object that implements
 		org.bluez.mesh.ProvisionAgent1 interface. The standard
 		DBus.ObjectManager interface must be available on the
-		app_defined_root path.
+		app_root path.
 
 		The uuid parameter is a 16-byte array that contains Device UUID.
 		This UUID must be unique (at least from the daemon perspective),
@@ -39,18 +39,18 @@ Methods:
 		method.
 
 	object node, array{byte, array{(uint16, dict)}} configuration
-			Attach(object app_defined_root, uint64 token)
+			Attach(object app_root, uint64 token)
 
 		This is the first method that an application must call to get
 		access to mesh node functionalities.
 
-		The app_defined_root parameter is a D-Bus object root path of
+		The app_root parameter is a D-Bus object root path of
 		the application that implements org.bluez.mesh.Application1
 		interface. The application represents a node where child mesh
 		elements have their own objects that implement
 		org.bluez.mesh.Element1 interface. The standard
 		DBus.ObjectManager interface must be available on the
-		app_defined_root path.
+		app_root path.
 
 		The token parameter is a 64-bit number that has been assigned to
 		the application when it first got provisioned/joined mesh
@@ -701,30 +701,34 @@ Mesh Application Hierarchy
 ==========================
 Service		unique name
 Interface	org.bluez.mesh.Application1
-Object path	<app_defined_root>
+Object path	<app_root>
 
 An application is a collection of elements that host SIG defined and vendor
 specific models. It is expected that an application implements
-org.freedesktop.DBus.ObjectManager interface.
+org.freedesktop.DBus.ObjectManager interface at app_root path.
 
 An example mesh application hierarchy may look like this:
 
-		-> /com/example
-			|   - org.freedesktop.DBus.ObjectManager
-			|   - org.bluez.mesh.Application1
-			|   - org.bluez.mesh.Attention1 (optional)
-			|   - org.bluez.mesh.Provisioner1 (optional,Provisioner)
-			|
-			-> /com/example/agent
-			| |   - org.bluez.mesh.ProvisionAgent1
-			|
-			-> /com/example/ele00
-			| |   - org.bluez.mesh.Element1
-			-> /com/example/ele01
-			| |   - org.bluez.mesh.Element1
-			...
-			-> /com/example/elexx
-			| |   - org.bluez.mesh.Element1
+-> /com/example
+  |   - org.freedesktop.DBus.ObjectManager
+  |
+  -> /com/example/application
+  |   - org.bluez.mesh.Application1
+  |   - org.bluez.mesh.Attention1 (optional)
+  |   - org.bluez.mesh.Provisioner1 (optional,Provisioner)
+  |
+  -> /com/example/agent
+  |   - org.bluez.mesh.ProvisionAgent1
+  |
+  -> /com/example/ele00
+  |   - org.bluez.mesh.Element1
+  |
+  -> /com/example/ele01
+  |   - org.bluez.mesh.Element1
+  |
+  ...
+  -> /com/example/elexx
+      - org.bluez.mesh.Element1
 
 Methods:
 	void JoinComplete(uint64 token)
diff --git a/mesh/node.c b/mesh/node.c
index c8a1dae78..28afe608f 100644
--- a/mesh/node.c
+++ b/mesh/node.c
@@ -1522,6 +1522,11 @@ static void get_managed_objects_cb(struct l_dbus_message *msg, void *user_data)
 					goto fail;
 			} else if (!strcmp(MESH_APPLICATION_INTERFACE,
 								interface)) {
+				if (have_app)
+					goto fail;
+
+				req->node->app_path = l_strdup(path);
+
 				res = get_app_properties(node, path,
 								&properties);
 				if (!res)
@@ -1665,7 +1670,7 @@ fail:
 }
 
 /* Establish relationship between application and mesh node */
-int node_attach(const char *app_path, const char *sender, uint64_t token,
+int node_attach(const char *app_root, const char *sender, uint64_t token,
 					node_ready_func_t cb, void *user_data)
 {
 	struct managed_obj_request *req;
@@ -1688,14 +1693,13 @@ int node_attach(const char *app_path, const char *sender, uint64_t token,
 	 * application. Existing node is passed in req->attach.
 	 */
 	req->node = node_new(node->uuid);
-	req->node->app_path = l_strdup(app_path);
 	req->node->owner = l_strdup(sender);
 	req->ready_cb = cb;
 	req->pending_msg = user_data;
 	req->attach = node;
 	req->type = REQUEST_TYPE_ATTACH;
 
-	l_dbus_method_call(dbus_get_bus(), sender, app_path,
+	l_dbus_method_call(dbus_get_bus(), sender, app_root,
 					L_DBUS_INTERFACE_OBJECT_MANAGER,
 					"GetManagedObjects", NULL,
 					get_managed_objects_cb,
@@ -1706,7 +1710,7 @@ int node_attach(const char *app_path, const char *sender, uint64_t token,
 
 
 /* Create a temporary pre-provisioned node */
-void node_join(const char *app_path, const char *sender, const uint8_t *uuid,
+void node_join(const char *app_root, const char *sender, const uint8_t *uuid,
 						node_join_ready_func_t cb)
 {
 	struct managed_obj_request *req;
@@ -1718,14 +1722,14 @@ void node_join(const char *app_path, const char *sender, const uint8_t *uuid,
 	req->join_ready_cb = cb;
 	req->type = REQUEST_TYPE_JOIN;
 
-	l_dbus_method_call(dbus_get_bus(), sender, app_path,
+	l_dbus_method_call(dbus_get_bus(), sender, app_root,
 					L_DBUS_INTERFACE_OBJECT_MANAGER,
 					"GetManagedObjects", NULL,
 					get_managed_objects_cb,
 					req, l_free);
 }
 
-bool node_import(const char *app_path, const char *sender, const uint8_t *uuid,
+bool node_import(const char *app_root, const char *sender, const uint8_t *uuid,
 			const uint8_t dev_key[16], const uint8_t net_key[16],
 			uint16_t net_idx, bool kr, bool ivu,
 			uint32_t iv_index, uint16_t unicast,
@@ -1752,7 +1756,7 @@ bool node_import(const char *app_path, const char *sender, const uint8_t *uuid,
 
 	req->type = REQUEST_TYPE_IMPORT;
 
-	l_dbus_method_call(dbus_get_bus(), sender, app_path,
+	l_dbus_method_call(dbus_get_bus(), sender, app_root,
 						L_DBUS_INTERFACE_OBJECT_MANAGER,
 						"GetManagedObjects", NULL,
 						get_managed_objects_cb,
@@ -1760,7 +1764,7 @@ bool node_import(const char *app_path, const char *sender, const uint8_t *uuid,
 	return true;
 }
 
-void node_create(const char *app_path, const char *sender, const uint8_t *uuid,
+void node_create(const char *app_root, const char *sender, const uint8_t *uuid,
 					node_ready_func_t cb, void *user_data)
 {
 	struct managed_obj_request *req;
@@ -1773,7 +1777,7 @@ void node_create(const char *app_path, const char *sender, const uint8_t *uuid,
 	req->pending_msg = user_data;
 	req->type = REQUEST_TYPE_CREATE;
 
-	l_dbus_method_call(dbus_get_bus(), sender, app_path,
+	l_dbus_method_call(dbus_get_bus(), sender, app_root,
 					L_DBUS_INTERFACE_OBJECT_MANAGER,
 					"GetManagedObjects", NULL,
 					get_managed_objects_cb,
diff --git a/mesh/node.h b/mesh/node.h
index 7448756ae..c718c038d 100644
--- a/mesh/node.h
+++ b/mesh/node.h
@@ -31,7 +31,7 @@ typedef void (*node_join_ready_func_t) (struct mesh_node *node,
 						struct mesh_agent *agent);
 
 void node_remove(struct mesh_node *node);
-void node_join(const char *app_path, const char *sender, const uint8_t *uuid,
+void node_join(const char *app_root, const char *sender, const uint8_t *uuid,
 						node_join_ready_func_t cb);
 uint8_t *node_uuid_get(struct mesh_node *node);
 struct mesh_net *node_get_net(struct mesh_node *node);
@@ -82,13 +82,13 @@ const char *node_get_app_path(struct mesh_node *node);
 bool node_add_pending_local(struct mesh_node *node, void *info);
 void node_attach_io_all(struct mesh_io *io);
 void node_attach_io(struct mesh_node *node, struct mesh_io *io);
-int node_attach(const char *app_path, const char *sender, uint64_t token,
+int node_attach(const char *app_root, const char *sender, uint64_t token,
 					node_ready_func_t cb, void *user_data);
 void node_build_attach_reply(struct mesh_node *node,
 						struct l_dbus_message *reply);
-void node_create(const char *app_path, const char *sender, const uint8_t *uuid,
+void node_create(const char *app_root, const char *sender, const uint8_t *uuid,
 					node_ready_func_t cb, void *user_data);
-bool node_import(const char *app_path, const char *sender, const uint8_t *uuid,
+bool node_import(const char *app_root, const char *sender, const uint8_t *uuid,
 			const uint8_t dev_key[16], const uint8_t net_key[16],
 			uint16_t net_idx, bool kr, bool ivu,
 			uint32_t iv_index, uint16_t unicast,
-- 
2.19.1


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH BlueZ] mesh: Fix getting managed objects from ObjectManager
  2019-12-17 14:54 [PATCH BlueZ] mesh: Fix getting managed objects from ObjectManager Michał Lowas-Rzechonek
@ 2019-12-18 15:49 ` Gix, Brian
  0 siblings, 0 replies; 2+ messages in thread
From: Gix, Brian @ 2019-12-18 15:49 UTC (permalink / raw)
  To: michal.lowas-rzechonek, linux-bluetooth

Applied, Thanks

On Tue, 2019-12-17 at 15:54 +0100, Michał Lowas-Rzechonek wrote:
> D-Bus spec mandates that GetManagedObjects method of
> org.freedesktop.DBus.ObjectManager interface returns *children* only:
> 
> https://dbus.freedesktop.org/doc/dbus-specification.html
> > All returned object paths are children of the object path implementing
> > this interface, i.e. their object paths start with the ObjectManager's
> > object path plus '/'
> 
> Both test scripts and ELL abuse this by returning application interfaces
> via ObjectManager attached to the same path, but other D-Bus
> implementations do not, making Attach() fail because mandatory
> interfaces cannot be found.
> 
> This patch fixes the issue by scanning hierarchy returned by
> GetManagedObjects for object implementing org.bluez.mesh.Application1
> interface and keeping that as node's app_path.
> ---
>  doc/mesh-api.txt | 52 ++++++++++++++++++++++++++----------------------
>  mesh/node.c      | 22 +++++++++++---------
>  mesh/node.h      |  8 ++++----
>  3 files changed, 45 insertions(+), 37 deletions(-)
> 
> diff --git a/doc/mesh-api.txt b/doc/mesh-api.txt
> index 30b7452e2..ebff8492a 100644
> --- a/doc/mesh-api.txt
> +++ b/doc/mesh-api.txt
> @@ -8,13 +8,13 @@ Interface	org.bluez.mesh.Network1
>  Object path	/org/bluez/mesh
>  
>  Methods:
> -	void Join(object app_defined_root, array{byte}[16] uuid)
> +	void Join(object app_root, array{byte}[16] uuid)
>  
>  		This is the first method that an application has to call to
>  		become a provisioned node on a mesh network. The call will
>  		initiate broadcasting of Unprovisioned Device Beacon.
>  
> -		The app_defined_root parameter is a D-Bus object root path of
> +		The app_root parameter is a D-Bus object root path of
>  		the application that implements org.bluez.mesh.Application1
>  		interface. The application represents a node where child mesh
>  		elements have their own objects that implement
> @@ -22,7 +22,7 @@ Methods:
>  		also contains a provision agent object that implements
>  		org.bluez.mesh.ProvisionAgent1 interface. The standard
>  		DBus.ObjectManager interface must be available on the
> -		app_defined_root path.
> +		app_root path.
>  
>  		The uuid parameter is a 16-byte array that contains Device UUID.
>  		This UUID must be unique (at least from the daemon perspective),
> @@ -39,18 +39,18 @@ Methods:
>  		method.
>  
>  	object node, array{byte, array{(uint16, dict)}} configuration
> -			Attach(object app_defined_root, uint64 token)
> +			Attach(object app_root, uint64 token)
>  
>  		This is the first method that an application must call to get
>  		access to mesh node functionalities.
>  
> -		The app_defined_root parameter is a D-Bus object root path of
> +		The app_root parameter is a D-Bus object root path of
>  		the application that implements org.bluez.mesh.Application1
>  		interface. The application represents a node where child mesh
>  		elements have their own objects that implement
>  		org.bluez.mesh.Element1 interface. The standard
>  		DBus.ObjectManager interface must be available on the
> -		app_defined_root path.
> +		app_root path.
>  
>  		The token parameter is a 64-bit number that has been assigned to
>  		the application when it first got provisioned/joined mesh
> @@ -701,30 +701,34 @@ Mesh Application Hierarchy
>  ==========================
>  Service		unique name
>  Interface	org.bluez.mesh.Application1
> -Object path	<app_defined_root>
> +Object path	<app_root>
>  
>  An application is a collection of elements that host SIG defined and vendor
>  specific models. It is expected that an application implements
> -org.freedesktop.DBus.ObjectManager interface.
> +org.freedesktop.DBus.ObjectManager interface at app_root path.
>  
>  An example mesh application hierarchy may look like this:
>  
> -		-> /com/example
> -			|   - org.freedesktop.DBus.ObjectManager
> -			|   - org.bluez.mesh.Application1
> -			|   - org.bluez.mesh.Attention1 (optional)
> -			|   - org.bluez.mesh.Provisioner1 (optional,Provisioner)
> -			|
> -			-> /com/example/agent
> -			| |   - org.bluez.mesh.ProvisionAgent1
> -			|
> -			-> /com/example/ele00
> -			| |   - org.bluez.mesh.Element1
> -			-> /com/example/ele01
> -			| |   - org.bluez.mesh.Element1
> -			...
> -			-> /com/example/elexx
> -			| |   - org.bluez.mesh.Element1
> +-> /com/example
> +  |   - org.freedesktop.DBus.ObjectManager
> +  |
> +  -> /com/example/application
> +  |   - org.bluez.mesh.Application1
> +  |   - org.bluez.mesh.Attention1 (optional)
> +  |   - org.bluez.mesh.Provisioner1 (optional,Provisioner)
> +  |
> +  -> /com/example/agent
> +  |   - org.bluez.mesh.ProvisionAgent1
> +  |
> +  -> /com/example/ele00
> +  |   - org.bluez.mesh.Element1
> +  |
> +  -> /com/example/ele01
> +  |   - org.bluez.mesh.Element1
> +  |
> +  ...
> +  -> /com/example/elexx
> +      - org.bluez.mesh.Element1
>  
>  Methods:
>  	void JoinComplete(uint64 token)
> diff --git a/mesh/node.c b/mesh/node.c
> index c8a1dae78..28afe608f 100644
> --- a/mesh/node.c
> +++ b/mesh/node.c
> @@ -1522,6 +1522,11 @@ static void get_managed_objects_cb(struct l_dbus_message *msg, void *user_data)
>  					goto fail;
>  			} else if (!strcmp(MESH_APPLICATION_INTERFACE,
>  								interface)) {
> +				if (have_app)
> +					goto fail;
> +
> +				req->node->app_path = l_strdup(path);
> +
>  				res = get_app_properties(node, path,
>  								&properties);
>  				if (!res)
> @@ -1665,7 +1670,7 @@ fail:
>  }
>  
>  /* Establish relationship between application and mesh node */
> -int node_attach(const char *app_path, const char *sender, uint64_t token,
> +int node_attach(const char *app_root, const char *sender, uint64_t token,
>  					node_ready_func_t cb, void *user_data)
>  {
>  	struct managed_obj_request *req;
> @@ -1688,14 +1693,13 @@ int node_attach(const char *app_path, const char *sender, uint64_t token,
>  	 * application. Existing node is passed in req->attach.
>  	 */
>  	req->node = node_new(node->uuid);
> -	req->node->app_path = l_strdup(app_path);
>  	req->node->owner = l_strdup(sender);
>  	req->ready_cb = cb;
>  	req->pending_msg = user_data;
>  	req->attach = node;
>  	req->type = REQUEST_TYPE_ATTACH;
>  
> -	l_dbus_method_call(dbus_get_bus(), sender, app_path,
> +	l_dbus_method_call(dbus_get_bus(), sender, app_root,
>  					L_DBUS_INTERFACE_OBJECT_MANAGER,
>  					"GetManagedObjects", NULL,
>  					get_managed_objects_cb,
> @@ -1706,7 +1710,7 @@ int node_attach(const char *app_path, const char *sender, uint64_t token,
>  
>  
>  /* Create a temporary pre-provisioned node */
> -void node_join(const char *app_path, const char *sender, const uint8_t *uuid,
> +void node_join(const char *app_root, const char *sender, const uint8_t *uuid,
>  						node_join_ready_func_t cb)
>  {
>  	struct managed_obj_request *req;
> @@ -1718,14 +1722,14 @@ void node_join(const char *app_path, const char *sender, const uint8_t *uuid,
>  	req->join_ready_cb = cb;
>  	req->type = REQUEST_TYPE_JOIN;
>  
> -	l_dbus_method_call(dbus_get_bus(), sender, app_path,
> +	l_dbus_method_call(dbus_get_bus(), sender, app_root,
>  					L_DBUS_INTERFACE_OBJECT_MANAGER,
>  					"GetManagedObjects", NULL,
>  					get_managed_objects_cb,
>  					req, l_free);
>  }
>  
> -bool node_import(const char *app_path, const char *sender, const uint8_t *uuid,
> +bool node_import(const char *app_root, const char *sender, const uint8_t *uuid,
>  			const uint8_t dev_key[16], const uint8_t net_key[16],
>  			uint16_t net_idx, bool kr, bool ivu,
>  			uint32_t iv_index, uint16_t unicast,
> @@ -1752,7 +1756,7 @@ bool node_import(const char *app_path, const char *sender, const uint8_t *uuid,
>  
>  	req->type = REQUEST_TYPE_IMPORT;
>  
> -	l_dbus_method_call(dbus_get_bus(), sender, app_path,
> +	l_dbus_method_call(dbus_get_bus(), sender, app_root,
>  						L_DBUS_INTERFACE_OBJECT_MANAGER,
>  						"GetManagedObjects", NULL,
>  						get_managed_objects_cb,
> @@ -1760,7 +1764,7 @@ bool node_import(const char *app_path, const char *sender, const uint8_t *uuid,
>  	return true;
>  }
>  
> -void node_create(const char *app_path, const char *sender, const uint8_t *uuid,
> +void node_create(const char *app_root, const char *sender, const uint8_t *uuid,
>  					node_ready_func_t cb, void *user_data)
>  {
>  	struct managed_obj_request *req;
> @@ -1773,7 +1777,7 @@ void node_create(const char *app_path, const char *sender, const uint8_t *uuid,
>  	req->pending_msg = user_data;
>  	req->type = REQUEST_TYPE_CREATE;
>  
> -	l_dbus_method_call(dbus_get_bus(), sender, app_path,
> +	l_dbus_method_call(dbus_get_bus(), sender, app_root,
>  					L_DBUS_INTERFACE_OBJECT_MANAGER,
>  					"GetManagedObjects", NULL,
>  					get_managed_objects_cb,
> diff --git a/mesh/node.h b/mesh/node.h
> index 7448756ae..c718c038d 100644
> --- a/mesh/node.h
> +++ b/mesh/node.h
> @@ -31,7 +31,7 @@ typedef void (*node_join_ready_func_t) (struct mesh_node *node,
>  						struct mesh_agent *agent);
>  
>  void node_remove(struct mesh_node *node);
> -void node_join(const char *app_path, const char *sender, const uint8_t *uuid,
> +void node_join(const char *app_root, const char *sender, const uint8_t *uuid,
>  						node_join_ready_func_t cb);
>  uint8_t *node_uuid_get(struct mesh_node *node);
>  struct mesh_net *node_get_net(struct mesh_node *node);
> @@ -82,13 +82,13 @@ const char *node_get_app_path(struct mesh_node *node);
>  bool node_add_pending_local(struct mesh_node *node, void *info);
>  void node_attach_io_all(struct mesh_io *io);
>  void node_attach_io(struct mesh_node *node, struct mesh_io *io);
> -int node_attach(const char *app_path, const char *sender, uint64_t token,
> +int node_attach(const char *app_root, const char *sender, uint64_t token,
>  					node_ready_func_t cb, void *user_data);
>  void node_build_attach_reply(struct mesh_node *node,
>  						struct l_dbus_message *reply);
> -void node_create(const char *app_path, const char *sender, const uint8_t *uuid,
> +void node_create(const char *app_root, const char *sender, const uint8_t *uuid,
>  					node_ready_func_t cb, void *user_data);
> -bool node_import(const char *app_path, const char *sender, const uint8_t *uuid,
> +bool node_import(const char *app_root, const char *sender, const uint8_t *uuid,
>  			const uint8_t dev_key[16], const uint8_t net_key[16],
>  			uint16_t net_idx, bool kr, bool ivu,
>  			uint32_t iv_index, uint16_t unicast,

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2019-12-18 15:49 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-12-17 14:54 [PATCH BlueZ] mesh: Fix getting managed objects from ObjectManager Michał Lowas-Rzechonek
2019-12-18 15:49 ` Gix, Brian

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.