mirror of
https://github.com/torvalds/linux.git
synced 2026-06-03 12:03:54 +02:00
thunderbolt: Fixes for v7.1-rc5
This includes three patches that harden the XDomain property parser against possible malicious hosts. All these have been in linux-next with no reported issues. -----BEGIN PGP SIGNATURE----- iQJUBAABCgA+FiEEVTdhRGBbNzLrSUBaAP2fSd+ZWKAFAmoMN6kgHG1pa2Eud2Vz dGVyYmVyZ0BsaW51eC5pbnRlbC5jb20ACgkQAP2fSd+ZWKA8Ag//ZxXcy8i84eU9 VIFBtR4jxwQXWJ6aOkJl/y3sZQXbOAY3CfbB54+0zFMx4qxSfCx4P4bMLYDqK64U YjWF+sxlcFtLv+u9YMfBFzcutK8qA5K0YEFP894gWyYRqdLzA6gGoJt7Vn+zARxZ eWTvmW8DJjy9Azh4opnfd8yvdh3wxslaGbU1/PRX7FLOPWxU0skn+N+T1583pJ4m bUxNw+jyGRKz49a0Foo4Ql5RCHg2wTFSGikrzvJreWF7kpz9NFoL/bkzLBbj5sKy Eyg8fxNAV2BVFRlp3CSHJsjRFEpg4o5LVNiRLHdeAATXHztsgFvqr3xRhQnfbuwa P8rkse1rIW6uFCkrLfpMdL9cdmDfrTBKsEp1YmtmtRHGBri+c7umf0vrDSliX2SO p/PfLKGHWeaIo1d8BDsnbsHIs+BLR7JZcjMJ4cIoUcCqTYzdtXibWTBVeHbT/CWm vgXfPyQ0g9L1kLxvdNQ7UD5hIB+PvlEhGprU5xjteBhVkM2IwczGxo1rxKacPh0q 1qwF+/yKorGhVB5vFcjE3uQSSOaRw7kkfAO1biidPdNnXWPydEJM3RGQsB462dCL XQRg46Ynes/K+Ya1n2TyI8hnnr+gz+qKl8hYqI4O99fDiiFGKgmpVP+0ap9q9nzZ itAOtz3N2RdSFX5LmUfP8Q7dUGaPHtw= =fKQQ -----END PGP SIGNATURE----- Merge tag 'thunderbolt-for-v7.1-rc5' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/westeri/thunderbolt into usb-linus Mika writes: thunderbolt: Fixes for v7.1-rc5 This includes three patches that harden the XDomain property parser against possible malicious hosts. All these have been in linux-next with no reported issues. * tag 'thunderbolt-for-v7.1-rc5' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/westeri/thunderbolt: thunderbolt: property: Cap recursion depth in __tb_property_parse_dir() thunderbolt: property: Reject dir_len < 4 to prevent size_t underflow thunderbolt: property: Reject u32 wrap in tb_property_entry_valid()
This commit is contained in:
commit
8320de248d
|
|
@ -8,6 +8,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/overflow.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/uuid.h>
|
||||
|
|
@ -34,10 +35,11 @@ struct tb_property_dir_entry {
|
|||
};
|
||||
|
||||
#define TB_PROPERTY_ROOTDIR_MAGIC 0x55584401
|
||||
#define TB_PROPERTY_MAX_DEPTH 8
|
||||
|
||||
static struct tb_property_dir *__tb_property_parse_dir(const u32 *block,
|
||||
size_t block_len, unsigned int dir_offset, size_t dir_len,
|
||||
bool is_root);
|
||||
bool is_root, unsigned int depth);
|
||||
|
||||
static inline void parse_dwdata(void *dst, const void *src, size_t dwords)
|
||||
{
|
||||
|
|
@ -52,13 +54,16 @@ static inline void format_dwdata(void *dst, const void *src, size_t dwords)
|
|||
static bool tb_property_entry_valid(const struct tb_property_entry *entry,
|
||||
size_t block_len)
|
||||
{
|
||||
u32 end;
|
||||
|
||||
switch (entry->type) {
|
||||
case TB_PROPERTY_TYPE_DIRECTORY:
|
||||
case TB_PROPERTY_TYPE_DATA:
|
||||
case TB_PROPERTY_TYPE_TEXT:
|
||||
if (entry->length > block_len)
|
||||
return false;
|
||||
if (entry->value + entry->length > block_len)
|
||||
if (check_add_overflow(entry->value, entry->length, &end) ||
|
||||
end > block_len)
|
||||
return false;
|
||||
break;
|
||||
|
||||
|
|
@ -93,7 +98,8 @@ tb_property_alloc(const char *key, enum tb_property_type type)
|
|||
}
|
||||
|
||||
static struct tb_property *tb_property_parse(const u32 *block, size_t block_len,
|
||||
const struct tb_property_entry *entry)
|
||||
const struct tb_property_entry *entry,
|
||||
unsigned int depth)
|
||||
{
|
||||
char key[TB_PROPERTY_KEY_SIZE + 1];
|
||||
struct tb_property *property;
|
||||
|
|
@ -114,7 +120,7 @@ static struct tb_property *tb_property_parse(const u32 *block, size_t block_len,
|
|||
switch (property->type) {
|
||||
case TB_PROPERTY_TYPE_DIRECTORY:
|
||||
dir = __tb_property_parse_dir(block, block_len, entry->value,
|
||||
entry->length, false);
|
||||
entry->length, false, depth + 1);
|
||||
if (!dir) {
|
||||
kfree(property);
|
||||
return NULL;
|
||||
|
|
@ -159,21 +165,31 @@ static struct tb_property *tb_property_parse(const u32 *block, size_t block_len,
|
|||
}
|
||||
|
||||
static struct tb_property_dir *__tb_property_parse_dir(const u32 *block,
|
||||
size_t block_len, unsigned int dir_offset, size_t dir_len, bool is_root)
|
||||
size_t block_len, unsigned int dir_offset, size_t dir_len, bool is_root,
|
||||
unsigned int depth)
|
||||
{
|
||||
const struct tb_property_entry *entries;
|
||||
size_t i, content_len, nentries;
|
||||
unsigned int content_offset;
|
||||
struct tb_property_dir *dir;
|
||||
|
||||
if (depth > TB_PROPERTY_MAX_DEPTH)
|
||||
return NULL;
|
||||
|
||||
dir = kzalloc_obj(*dir);
|
||||
if (!dir)
|
||||
return NULL;
|
||||
|
||||
INIT_LIST_HEAD(&dir->properties);
|
||||
|
||||
if (is_root) {
|
||||
content_offset = dir_offset + 2;
|
||||
content_len = dir_len;
|
||||
} else {
|
||||
if (dir_len < 4) {
|
||||
tb_property_free_dir(dir);
|
||||
return NULL;
|
||||
}
|
||||
dir->uuid = kmemdup(&block[dir_offset], sizeof(*dir->uuid),
|
||||
GFP_KERNEL);
|
||||
if (!dir->uuid) {
|
||||
|
|
@ -187,12 +203,10 @@ static struct tb_property_dir *__tb_property_parse_dir(const u32 *block,
|
|||
entries = (const struct tb_property_entry *)&block[content_offset];
|
||||
nentries = content_len / (sizeof(*entries) / 4);
|
||||
|
||||
INIT_LIST_HEAD(&dir->properties);
|
||||
|
||||
for (i = 0; i < nentries; i++) {
|
||||
struct tb_property *property;
|
||||
|
||||
property = tb_property_parse(block, block_len, &entries[i]);
|
||||
property = tb_property_parse(block, block_len, &entries[i], depth);
|
||||
if (!property) {
|
||||
tb_property_free_dir(dir);
|
||||
return NULL;
|
||||
|
|
@ -231,7 +245,7 @@ struct tb_property_dir *tb_property_parse_dir(const u32 *block,
|
|||
return NULL;
|
||||
|
||||
return __tb_property_parse_dir(block, block_len, 0, rootdir->length,
|
||||
true);
|
||||
true, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user