2022-04-12 14:17:37

by Takashi Sakamoto

[permalink] [raw]
Subject: [PATCH 0/3] firewire: fixes for kernel v4.9 or later

Hi,

This patchset respins patches posted before to fix some bugs for Linux
FireWire subsystem. I expect them to be sent to Linus via pull request
by maintainer of Linux sound subsystem since the path appears to be
available after a short conversation with the maintainer. This patchset
is expected to be applied to 'for-linus' branch for v5.18 kernel, and
to stable kernels based on v4.9 or later.

This patchset includes below patches:

* [PATCH V2] drivers/firewire: use struct_size over open coded arithmetic
* https://lore.kernel.org/lkml/[email protected]/
* [PATCH] firewire: core: extend card->lock in fw_core_handle_bus_reset
* https://lore.kernel.org/lkml/[email protected]/
* [PATCH] firewire: remove check of list iterator against head past the loop body
* https://lore.kernel.org/lkml/[email protected]/

Chengfeng Ye (1):
firewire: fix potential uaf in outbound_phy_packet_callback()

Jakob Koschel (1):
firewire: remove check of list iterator against head past the loop
body

Niels Dossche (1):
firewire: core: extend card->lock in fw_core_handle_bus_reset

drivers/firewire/core-card.c | 3 +++
drivers/firewire/core-cdev.c | 4 +++-
drivers/firewire/core-topology.c | 9 +++------
drivers/firewire/core-transaction.c | 30 +++++++++++++++--------------
drivers/firewire/sbp2.c | 13 +++++++------
5 files changed, 32 insertions(+), 27 deletions(-)

--
2.34.1


2022-04-12 20:51:03

by Takashi Sakamoto

[permalink] [raw]
Subject: [PATCH 1/3] firewire: fix potential uaf in outbound_phy_packet_callback()

From: Chengfeng Ye <[email protected]>

&e->event and e point to the same address, and &e->event could
be freed in queue_event. So there is a potential uaf issue if
we dereference e after calling queue_event(). Fix this by adding
a temporary variable to maintain e->client in advance, this can
avoid the potential uaf issue.

Cc: <[email protected]>
Signed-off-by: Chengfeng Ye <[email protected]>
Signed-off-by: Takashi Sakamoto <[email protected]>
---
drivers/firewire/core-cdev.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c
index 9f89c17730b1..708e417200f4 100644
--- a/drivers/firewire/core-cdev.c
+++ b/drivers/firewire/core-cdev.c
@@ -1500,6 +1500,7 @@ static void outbound_phy_packet_callback(struct fw_packet *packet,
{
struct outbound_phy_packet_event *e =
container_of(packet, struct outbound_phy_packet_event, p);
+ struct client *e_client;

switch (status) {
/* expected: */
@@ -1516,9 +1517,10 @@ static void outbound_phy_packet_callback(struct fw_packet *packet,
}
e->phy_packet.data[0] = packet->timestamp;

+ e_client = e->client;
queue_event(e->client, &e->event, &e->phy_packet,
sizeof(e->phy_packet) + e->phy_packet.length, NULL, 0);
- client_put(e->client);
+ client_put(e_client);
}

static int ioctl_send_phy_packet(struct client *client, union ioctl_arg *arg)
--
2.34.1

2022-04-12 23:50:18

by Takashi Sakamoto

[permalink] [raw]
Subject: [PATCH 3/3] firewire: core: extend card->lock in fw_core_handle_bus_reset

From: Niels Dossche <[email protected]>

card->local_node and card->bm_retries are both always accessed under
card->lock.
fw_core_handle_bus_reset has a check whose condition depends on
card->local_node and whose body writes to card->bm_retries.
Both of these accesses are not under card->lock. Move the lock acquiring
of card->lock to before this check such that these accesses do happen
when card->lock is held.
fw_destroy_nodes is called inside the check.
Since fw_destroy_nodes already acquires card->lock inside its function
body, move this out to the callsites of fw_destroy_nodes.
Also add a comment to indicate which locking is necessary when calling
fw_destroy_nodes.

Cc: <[email protected]>
Signed-off-by: Niels Dossche <[email protected]>
Signed-off-by: Takashi Sakamoto <[email protected]>
---
drivers/firewire/core-card.c | 3 +++
drivers/firewire/core-topology.c | 9 +++------
2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c
index 54be88167c60..f3b3953cac83 100644
--- a/drivers/firewire/core-card.c
+++ b/drivers/firewire/core-card.c
@@ -668,6 +668,7 @@ EXPORT_SYMBOL_GPL(fw_card_release);
void fw_core_remove_card(struct fw_card *card)
{
struct fw_card_driver dummy_driver = dummy_driver_template;
+ unsigned long flags;

card->driver->update_phy_reg(card, 4,
PHY_LINK_ACTIVE | PHY_CONTENDER, 0);
@@ -682,7 +683,9 @@ void fw_core_remove_card(struct fw_card *card)
dummy_driver.stop_iso = card->driver->stop_iso;
card->driver = &dummy_driver;

+ spin_lock_irqsave(&card->lock, flags);
fw_destroy_nodes(card);
+ spin_unlock_irqrestore(&card->lock, flags);

/* Wait for all users, especially device workqueue jobs, to finish. */
fw_card_put(card);
diff --git a/drivers/firewire/core-topology.c b/drivers/firewire/core-topology.c
index b63d55f5ebd3..f40c81534381 100644
--- a/drivers/firewire/core-topology.c
+++ b/drivers/firewire/core-topology.c
@@ -375,16 +375,13 @@ static void report_found_node(struct fw_card *card,
card->bm_retries = 0;
}

+/* Must be called with card->lock held */
void fw_destroy_nodes(struct fw_card *card)
{
- unsigned long flags;
-
- spin_lock_irqsave(&card->lock, flags);
card->color++;
if (card->local_node != NULL)
for_each_fw_node(card, card->local_node, report_lost_node);
card->local_node = NULL;
- spin_unlock_irqrestore(&card->lock, flags);
}

static void move_tree(struct fw_node *node0, struct fw_node *node1, int port)
@@ -510,6 +507,8 @@ void fw_core_handle_bus_reset(struct fw_card *card, int node_id, int generation,
struct fw_node *local_node;
unsigned long flags;

+ spin_lock_irqsave(&card->lock, flags);
+
/*
* If the selfID buffer is not the immediate successor of the
* previously processed one, we cannot reliably compare the
@@ -521,8 +520,6 @@ void fw_core_handle_bus_reset(struct fw_card *card, int node_id, int generation,
card->bm_retries = 0;
}

- spin_lock_irqsave(&card->lock, flags);
-
card->broadcast_channel_allocated = card->broadcast_channel_auto_allocated;
card->node_id = node_id;
/*
--
2.34.1

2022-04-25 10:32:03

by Takashi Iwai

[permalink] [raw]
Subject: Re: [PATCH 0/3] firewire: fixes for kernel v4.9 or later

On Sat, 09 Apr 2022 06:12:40 +0200,
Takashi Sakamoto wrote:
>
> Hi,
>
> This patchset respins patches posted before to fix some bugs for Linux
> FireWire subsystem. I expect them to be sent to Linus via pull request
> by maintainer of Linux sound subsystem since the path appears to be
> available after a short conversation with the maintainer. This patchset
> is expected to be applied to 'for-linus' branch for v5.18 kernel, and
> to stable kernels based on v4.9 or later.
>
> This patchset includes below patches:
>
> * [PATCH V2] drivers/firewire: use struct_size over open coded arithmetic
> * https://lore.kernel.org/lkml/[email protected]/
> * [PATCH] firewire: core: extend card->lock in fw_core_handle_bus_reset
> * https://lore.kernel.org/lkml/[email protected]/
> * [PATCH] firewire: remove check of list iterator against head past the loop body
> * https://lore.kernel.org/lkml/[email protected]/
>
> Chengfeng Ye (1):
> firewire: fix potential uaf in outbound_phy_packet_callback()
>
> Jakob Koschel (1):
> firewire: remove check of list iterator against head past the loop
> body
>
> Niels Dossche (1):
> firewire: core: extend card->lock in fw_core_handle_bus_reset

Now I applied all those pending patches to topic/firewire branch,
merged into for-linus branch.


thanks,

Takashi