mirror of
https://github.com/apache/nuttx.git
synced 2026-06-02 17:48:54 +08:00
drivers/rpmsg: fix struct alignment issue by removing zero array member
This commit fixes a memory alignment issue in the rpmsg subsystem. The previous implementation used a flexible array member (rdev[0]) in struct rpmsg_s, but due to automatic 8-byte padding, rpmsg->rdev could differ from the transport layer's rdev address (e.g., rpmsg_virtio->rvdev.rdev), causing potential memory corruption. Changes: - Remove rdev[0] flexible array member from struct rpmsg_s - Add rpmsg_get_rdev_by_rpmsg() inline helper to calculate rdev address as (rpmsg + 1), ensuring correct pointer arithmetic - Update all rpmsg->rdev references to use the new helper function - Fix rpmsg_virtio_notify_wait() to use correct container_of macro Signed-off-by: Yongrong Wang <wangyongrong@xiaomi.com>
This commit is contained in:
committed by
Xiang Xiao
parent
fea492cf6f
commit
aa567d43f6
+17
-13
@@ -96,7 +96,7 @@ rpmsg_get_by_rdev(FAR struct rpmsg_device *rdev)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return metal_container_of(rdev, struct rpmsg_s, rdev);
|
return (FAR struct rpmsg_s *)((FAR char *)rdev - sizeof(struct rpmsg_s));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rpmsg_dev_ioctl_(FAR struct rpmsg_s *rpmsg, int cmd,
|
static int rpmsg_dev_ioctl_(FAR struct rpmsg_s *rpmsg, int cmd,
|
||||||
@@ -248,6 +248,7 @@ int rpmsg_register_callback(FAR void *priv,
|
|||||||
{
|
{
|
||||||
FAR struct rpmsg_s *rpmsg =
|
FAR struct rpmsg_s *rpmsg =
|
||||||
metal_container_of(node, struct rpmsg_s, node);
|
metal_container_of(node, struct rpmsg_s, node);
|
||||||
|
FAR struct rpmsg_device *rdev = rpmsg_get_rdev_by_rpmsg(rpmsg);
|
||||||
|
|
||||||
if (!rpmsg->init)
|
if (!rpmsg->init)
|
||||||
{
|
{
|
||||||
@@ -256,7 +257,7 @@ int rpmsg_register_callback(FAR void *priv,
|
|||||||
|
|
||||||
if (device_created)
|
if (device_created)
|
||||||
{
|
{
|
||||||
device_created(rpmsg->rdev, priv);
|
device_created(rdev, priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ns_bind == NULL)
|
if (ns_bind == NULL)
|
||||||
@@ -273,11 +274,11 @@ again:
|
|||||||
FAR struct rpmsg_bind_s *bind =
|
FAR struct rpmsg_bind_s *bind =
|
||||||
metal_container_of(bnode, struct rpmsg_bind_s, node);
|
metal_container_of(bnode, struct rpmsg_bind_s, node);
|
||||||
|
|
||||||
if (ns_match(rpmsg->rdev, priv, bind->name, bind->dest))
|
if (ns_match(rdev, priv, bind->name, bind->dest))
|
||||||
{
|
{
|
||||||
metal_list_del(bnode);
|
metal_list_del(bnode);
|
||||||
nxrmutex_unlock(&rpmsg->lock);
|
nxrmutex_unlock(&rpmsg->lock);
|
||||||
ns_bind(rpmsg->rdev, priv, bind->name, bind->dest);
|
ns_bind(rdev, priv, bind->name, bind->dest);
|
||||||
|
|
||||||
kmm_free(bind);
|
kmm_free(bind);
|
||||||
goto again;
|
goto again;
|
||||||
@@ -326,10 +327,11 @@ void rpmsg_unregister_callback(FAR void *priv,
|
|||||||
{
|
{
|
||||||
FAR struct rpmsg_s *rpmsg =
|
FAR struct rpmsg_s *rpmsg =
|
||||||
metal_container_of(pnode, struct rpmsg_s, node);
|
metal_container_of(pnode, struct rpmsg_s, node);
|
||||||
|
FAR struct rpmsg_device *rdev = rpmsg_get_rdev_by_rpmsg(rpmsg);
|
||||||
|
|
||||||
if (rpmsg->init)
|
if (rpmsg->init)
|
||||||
{
|
{
|
||||||
device_destroy(rpmsg->rdev, priv);
|
device_destroy(rdev, priv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -403,6 +405,7 @@ void rpmsg_ns_unbind(FAR struct rpmsg_device *rdev,
|
|||||||
|
|
||||||
void rpmsg_device_created(FAR struct rpmsg_s *rpmsg)
|
void rpmsg_device_created(FAR struct rpmsg_s *rpmsg)
|
||||||
{
|
{
|
||||||
|
FAR struct rpmsg_device *rdev = rpmsg_get_rdev_by_rpmsg(rpmsg);
|
||||||
FAR struct metal_list *node;
|
FAR struct metal_list *node;
|
||||||
FAR struct metal_list *tmp;
|
FAR struct metal_list *tmp;
|
||||||
|
|
||||||
@@ -414,7 +417,7 @@ void rpmsg_device_created(FAR struct rpmsg_s *rpmsg)
|
|||||||
|
|
||||||
if (cb->device_created)
|
if (cb->device_created)
|
||||||
{
|
{
|
||||||
cb->device_created(rpmsg->rdev, cb->priv);
|
cb->device_created(rdev, cb->priv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -422,15 +425,16 @@ void rpmsg_device_created(FAR struct rpmsg_s *rpmsg)
|
|||||||
up_write(&g_rpmsg_lock);
|
up_write(&g_rpmsg_lock);
|
||||||
|
|
||||||
#ifdef CONFIG_RPMSG_PING
|
#ifdef CONFIG_RPMSG_PING
|
||||||
rpmsg_ping_init(rpmsg->rdev, &rpmsg->ping);
|
rpmsg_ping_init(rdev, &rpmsg->ping);
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_RPMSG_TEST
|
#ifdef CONFIG_RPMSG_TEST
|
||||||
rpmsg_test_init(rpmsg->rdev, &rpmsg->test);
|
rpmsg_test_init(rdev, &rpmsg->test);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpmsg_device_destory(FAR struct rpmsg_s *rpmsg)
|
void rpmsg_device_destory(FAR struct rpmsg_s *rpmsg)
|
||||||
{
|
{
|
||||||
|
FAR struct rpmsg_device *rdev = rpmsg_get_rdev_by_rpmsg(rpmsg);
|
||||||
FAR struct metal_list *node;
|
FAR struct metal_list *node;
|
||||||
FAR struct metal_list *tmp;
|
FAR struct metal_list *tmp;
|
||||||
FAR struct rpmsg_endpoint *ept;
|
FAR struct rpmsg_endpoint *ept;
|
||||||
@@ -467,7 +471,7 @@ void rpmsg_device_destory(FAR struct rpmsg_s *rpmsg)
|
|||||||
|
|
||||||
if (cb->device_destroy)
|
if (cb->device_destroy)
|
||||||
{
|
{
|
||||||
cb->device_destroy(rpmsg->rdev, cb->priv);
|
cb->device_destroy(rdev, cb->priv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -475,8 +479,8 @@ void rpmsg_device_destory(FAR struct rpmsg_s *rpmsg)
|
|||||||
|
|
||||||
/* Release all ept attached to current rpmsg device */
|
/* Release all ept attached to current rpmsg device */
|
||||||
|
|
||||||
metal_mutex_acquire(&rpmsg->rdev->lock);
|
metal_mutex_acquire(&rdev->lock);
|
||||||
metal_list_for_each_safe(&rpmsg->rdev->endpoints, tmp, node)
|
metal_list_for_each_safe(&rdev->endpoints, tmp, node)
|
||||||
{
|
{
|
||||||
ept = metal_container_of(node, struct rpmsg_endpoint, node);
|
ept = metal_container_of(node, struct rpmsg_endpoint, node);
|
||||||
if (ept->ns_unbind_cb)
|
if (ept->ns_unbind_cb)
|
||||||
@@ -489,7 +493,7 @@ void rpmsg_device_destory(FAR struct rpmsg_s *rpmsg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
metal_mutex_release(&rpmsg->rdev->lock);
|
metal_mutex_release(&rdev->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
int rpmsg_register(FAR const char *path, FAR struct rpmsg_s *rpmsg,
|
int rpmsg_register(FAR const char *path, FAR struct rpmsg_s *rpmsg,
|
||||||
@@ -583,7 +587,7 @@ void rpmsg_dump_all(void)
|
|||||||
void rpmsg_modify_signals(FAR struct rpmsg_s *rpmsg,
|
void rpmsg_modify_signals(FAR struct rpmsg_s *rpmsg,
|
||||||
int setflags, int clrflags)
|
int setflags, int clrflags)
|
||||||
{
|
{
|
||||||
FAR struct rpmsg_device *rdev = rpmsg->rdev;
|
FAR struct rpmsg_device *rdev = rpmsg_get_rdev_by_rpmsg(rpmsg);
|
||||||
FAR struct rpmsg_endpoint *ept;
|
FAR struct rpmsg_endpoint *ept;
|
||||||
FAR struct metal_list *node;
|
FAR struct metal_list *node;
|
||||||
bool needlock;
|
bool needlock;
|
||||||
|
|||||||
@@ -594,8 +594,9 @@ int rpmsg_port_initialize(FAR struct rpmsg_port_s *port,
|
|||||||
void rpmsg_port_uninitialize(FAR struct rpmsg_port_s *port)
|
void rpmsg_port_uninitialize(FAR struct rpmsg_port_s *port)
|
||||||
{
|
{
|
||||||
FAR struct rpmsg_s *rpmsg = &port->rpmsg;
|
FAR struct rpmsg_s *rpmsg = &port->rpmsg;
|
||||||
|
FAR struct rpmsg_device *rdev = rpmsg_get_rdev_by_rpmsg(rpmsg);
|
||||||
|
|
||||||
metal_mutex_deinit(&rpmsg->rdev->lock);
|
metal_mutex_deinit(&rdev->lock);
|
||||||
rpmsg_port_destroy_queues(port);
|
rpmsg_port_destroy_queues(port);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -789,7 +790,7 @@ static void rpmsg_port_dump_buffer(FAR struct rpmsg_device *rdev,
|
|||||||
static void rpmsg_port_dump(FAR struct rpmsg_s *rpmsg)
|
static void rpmsg_port_dump(FAR struct rpmsg_s *rpmsg)
|
||||||
{
|
{
|
||||||
FAR struct rpmsg_port_s *port = (FAR struct rpmsg_port_s *)rpmsg;
|
FAR struct rpmsg_port_s *port = (FAR struct rpmsg_port_s *)rpmsg;
|
||||||
FAR struct rpmsg_device *rdev = rpmsg->rdev;
|
FAR struct rpmsg_device *rdev = rpmsg_get_rdev_by_rpmsg(rpmsg);
|
||||||
FAR struct rpmsg_endpoint *ept;
|
FAR struct rpmsg_endpoint *ept;
|
||||||
FAR struct metal_list *node;
|
FAR struct metal_list *node;
|
||||||
bool needunlock = false;
|
bool needunlock = false;
|
||||||
|
|||||||
@@ -403,7 +403,7 @@ static void rpmsg_virtio_dump(FAR struct rpmsg_s *rpmsg)
|
|||||||
FAR struct rpmsg_virtio_priv_s *priv =
|
FAR struct rpmsg_virtio_priv_s *priv =
|
||||||
(FAR struct rpmsg_virtio_priv_s *)rpmsg;
|
(FAR struct rpmsg_virtio_priv_s *)rpmsg;
|
||||||
FAR struct rpmsg_virtio_device *rvdev = &priv->rvdev;
|
FAR struct rpmsg_virtio_device *rvdev = &priv->rvdev;
|
||||||
FAR struct rpmsg_device *rdev = rpmsg->rdev;
|
FAR struct rpmsg_device *rdev = &rvdev->rdev;
|
||||||
FAR struct rpmsg_endpoint *ept;
|
FAR struct rpmsg_endpoint *ept;
|
||||||
FAR struct metal_list *node;
|
FAR struct metal_list *node;
|
||||||
bool needunlock = false;
|
bool needunlock = false;
|
||||||
@@ -515,8 +515,8 @@ static void rpmsg_virtio_tx_notify(FAR struct virtqueue *vq)
|
|||||||
static int rpmsg_virtio_notify_wait(FAR struct rpmsg_device *rdev,
|
static int rpmsg_virtio_notify_wait(FAR struct rpmsg_device *rdev,
|
||||||
uint32_t id)
|
uint32_t id)
|
||||||
{
|
{
|
||||||
FAR struct rpmsg_virtio_priv_s *priv = (FAR struct rpmsg_virtio_priv_s *)
|
FAR struct rpmsg_virtio_priv_s *priv =
|
||||||
metal_container_of(rdev, struct rpmsg_s, rdev);
|
metal_container_of(rdev, struct rpmsg_virtio_priv_s, rvdev);
|
||||||
|
|
||||||
if (!rpmsg_virtio_is_recursive(priv))
|
if (!rpmsg_virtio_is_recursive(priv))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -475,8 +475,8 @@ static void rpmsg_virtio_lite_dump(FAR struct rpmsg_s *rpmsg)
|
|||||||
{
|
{
|
||||||
FAR struct rpmsg_virtio_lite_priv_s *priv =
|
FAR struct rpmsg_virtio_lite_priv_s *priv =
|
||||||
(FAR struct rpmsg_virtio_lite_priv_s *)rpmsg;
|
(FAR struct rpmsg_virtio_lite_priv_s *)rpmsg;
|
||||||
|
FAR struct rpmsg_device *rdev = rpmsg_get_rdev_by_rpmsg(rpmsg);
|
||||||
FAR struct rpmsg_virtio_device *rvdev = &priv->rvdev;
|
FAR struct rpmsg_virtio_device *rvdev = &priv->rvdev;
|
||||||
FAR struct rpmsg_device *rdev = rpmsg->rdev;
|
|
||||||
FAR struct rpmsg_endpoint *ept;
|
FAR struct rpmsg_endpoint *ept;
|
||||||
FAR struct metal_list *node;
|
FAR struct metal_list *node;
|
||||||
bool needlock = true;
|
bool needlock = true;
|
||||||
|
|||||||
@@ -68,7 +68,6 @@ struct rpmsg_s
|
|||||||
struct rpmsg_endpoint test;
|
struct rpmsg_endpoint test;
|
||||||
#endif
|
#endif
|
||||||
atomic_int signals;
|
atomic_int signals;
|
||||||
struct rpmsg_device rdev[0];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -108,6 +107,17 @@ extern "C"
|
|||||||
#define EXTERN extern
|
#define EXTERN extern
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static inline FAR struct rpmsg_device *
|
||||||
|
rpmsg_get_rdev_by_rpmsg(FAR struct rpmsg_s *rpmsg)
|
||||||
|
{
|
||||||
|
if (!rpmsg)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (FAR struct rpmsg_device *)(rpmsg + 1);
|
||||||
|
}
|
||||||
|
|
||||||
int rpmsg_wait(FAR struct rpmsg_endpoint *ept, FAR sem_t *sem);
|
int rpmsg_wait(FAR struct rpmsg_endpoint *ept, FAR sem_t *sem);
|
||||||
int rpmsg_post(FAR struct rpmsg_endpoint *ept, FAR sem_t *sem);
|
int rpmsg_post(FAR struct rpmsg_endpoint *ept, FAR sem_t *sem);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user