summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2026-06-01 17:50:38 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2026-06-01 17:50:38 +0200
commit108c8b6c06b7c77787fd85f92d15a1e992fa1de4 (patch)
tree97e62ff2f5464da5f87f9c61f8342a698b333225
parente43ffb69e0438cddd72aaa30898b4dc446f664f8 (diff)
parent4db2bd2ed4785dbadaeeab9f4e346b21ac5fb8eb (diff)
downloadlinux-stable-108c8b6c06b7c77787fd85f92d15a1e992fa1de4.tar.gz
linux-stable-108c8b6c06b7c77787fd85f92d15a1e992fa1de4.zip
Merge tag 'thunderbolt-for-v7.1-rc7' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/westeri/thunderbolt into usb-linus
Mika writes: thunderbolt: Fixes for v7.1-rc7 This includes more fixes to harden XDomain message handling against possible malicious hosts. All these have been in linux-next with no reported issues. * tag 'thunderbolt-for-v7.1-rc7' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/westeri/thunderbolt: thunderbolt: Limit XDomain response copy to actual frame size thunderbolt: Validate XDomain request packet size before type cast thunderbolt: Clamp XDomain response data copy to allocation size thunderbolt: Bound root directory content to block size thunderbolt: Reject zero-length property entries in validator
-rw-r--r--drivers/thunderbolt/property.c6
-rw-r--r--drivers/thunderbolt/xdomain.c14
2 files changed, 17 insertions, 3 deletions
diff --git a/drivers/thunderbolt/property.c b/drivers/thunderbolt/property.c
index da2c59a17db5..59beab43f90a 100644
--- a/drivers/thunderbolt/property.c
+++ b/drivers/thunderbolt/property.c
@@ -60,6 +60,8 @@ static bool tb_property_entry_valid(const struct tb_property_entry *entry,
case TB_PROPERTY_TYPE_DIRECTORY:
case TB_PROPERTY_TYPE_DATA:
case TB_PROPERTY_TYPE_TEXT:
+ if (!entry->length)
+ return false;
if (entry->length > block_len)
return false;
if (check_add_overflow(entry->value, entry->length, &end) ||
@@ -185,6 +187,10 @@ static struct tb_property_dir *__tb_property_parse_dir(const u32 *block,
if (is_root) {
content_offset = dir_offset + 2;
content_len = dir_len;
+ if (content_offset + content_len > block_len) {
+ tb_property_free_dir(dir);
+ return NULL;
+ }
} else {
if (dir_len < 4) {
tb_property_free_dir(dir);
diff --git a/drivers/thunderbolt/xdomain.c b/drivers/thunderbolt/xdomain.c
index 754808c43f00..1fd1cf4295a2 100644
--- a/drivers/thunderbolt/xdomain.c
+++ b/drivers/thunderbolt/xdomain.c
@@ -55,6 +55,7 @@ static const char * const state_names[] = {
struct xdomain_request_work {
struct work_struct work;
struct tb_xdp_header *pkg;
+ size_t pkg_len;
struct tb *tb;
};
@@ -122,7 +123,9 @@ static bool tb_xdomain_match(const struct tb_cfg_request *req,
static bool tb_xdomain_copy(struct tb_cfg_request *req,
const struct ctl_pkg *pkg)
{
- memcpy(req->response, pkg->buffer, req->response_size);
+ size_t len = min_t(size_t, pkg->frame.size, req->response_size);
+
+ memcpy(req->response, pkg->buffer, len);
req->result.err = 0;
return true;
}
@@ -393,6 +396,8 @@ static int tb_xdp_properties_request(struct tb_ctl *ctl, u64 route,
}
}
+ if (req.offset + len > data_len)
+ len = data_len - req.offset;
memcpy(data + req.offset, res->data, len * 4);
req.offset += len;
} while (!data_len || req.offset < data_len);
@@ -731,6 +736,7 @@ static void tb_xdp_handle_request(struct work_struct *work)
struct xdomain_request_work *xw = container_of(work, typeof(*xw), work);
const struct tb_xdp_header *pkg = xw->pkg;
const struct tb_xdomain_header *xhdr = &pkg->xd_hdr;
+ size_t pkg_len = xw->pkg_len;
struct tb *tb = xw->tb;
struct tb_ctl *ctl = tb->ctl;
struct tb_xdomain *xd;
@@ -762,7 +768,7 @@ static void tb_xdp_handle_request(struct work_struct *work)
switch (pkg->type) {
case PROPERTIES_REQUEST:
tb_dbg(tb, "%llx: received XDomain properties request\n", route);
- if (xd) {
+ if (xd && pkg_len >= sizeof(struct tb_xdp_properties)) {
ret = tb_xdp_properties_response(tb, ctl, xd, sequence,
(const struct tb_xdp_properties *)pkg);
}
@@ -816,7 +822,8 @@ static void tb_xdp_handle_request(struct work_struct *work)
tb_dbg(tb, "%llx: received XDomain link state change request\n",
route);
- if (xd && xd->state == XDOMAIN_STATE_BONDING_UUID_HIGH) {
+ if (xd && xd->state == XDOMAIN_STATE_BONDING_UUID_HIGH &&
+ pkg_len >= sizeof(struct tb_xdp_link_state_change)) {
const struct tb_xdp_link_state_change *lsc =
(const struct tb_xdp_link_state_change *)pkg;
@@ -868,6 +875,7 @@ tb_xdp_schedule_request(struct tb *tb, const struct tb_xdp_header *hdr,
kfree(xw);
return false;
}
+ xw->pkg_len = size;
xw->tb = tb_domain_get(tb);
schedule_work(&xw->work);