[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <202306201148.716CFF3@keescook>
Date: Tue, 20 Jun 2023 12:32:36 -0700
From: Kees Cook <keescook@...omium.org>
To: Bagas Sanjaya <bagasdotme@...il.com>
Cc: Linux Kernel Mailing List <linux-kernel@...r.kernel.org>,
Linux Wireless <linux-wireless@...r.kernel.org>,
Linux Networking <netdev@...r.kernel.org>,
M Chetan Kumar <m.chetan.kumar@...ux.intel.com>,
"David S. Miller" <davem@...emloft.net>,
Florian Klink <flokli@...kli.de>,
linux-hardening@...r.kernel.org
Subject: Re: Fwd: iosm: detected field-spanning write for XMM7360
[regressions list to Bcc]
On Tue, Jun 20, 2023 at 11:12:40AM +0200, Linux regression tracking (Thorsten Leemhuis) wrote:
> On 20.06.23 10:44, Bagas Sanjaya wrote:
> > I notice a regression report on Bugzilla [1]. Quoting from it:
> [...]
> >> [Sa Jun 17 20:10:09 2023] memcpy: detected field-spanning write (size 16) of single field "&adth->dg" at drivers/net/wwan/iosm/iosm_ipc_mux_codec.c:852 (size 8)
> [...]
> > [1]: https://bugzilla.kernel.org/show_bug.cgi?id=217569
This looks like a legitimate bug.
Here are the structures used by drivers/net/wwan/iosm/iosm_ipc_mux_codec.c
leading up to the memcpy() triggering this warning at line 852, with
commentary from me added:
struct mux_adb {
struct sk_buff *dest_skb;
u8 *buf; // <- unbounded array
...
};
/**
* struct mux_adth - Structure of the Aggregated Datagram Table Header.
...
* @dg: datagramm table with variable length // variable length you say? :)
*/
struct mux_adth {
...
struct mux_adth_dg dg; // <- destination of memcpy
};
struct mux_adth_dg {
__le32 datagram_index;
__le16 datagram_length;
u8 service_class;
u8 reserved;
}; // 8 byte structure
static void ipc_mux_ul_encode_adth(struct iosm_mux *ipc_mux,
struct mux_adb *ul_adb, int *out_offset)
{
...
struct mux_adth *adth;
...
// Assignment of fixed-sized structure on an
// unbounded string (i.e. minimum size
// constraint is now defined by structure
// layout, which is a good thing.)
adth = (struct mux_adth *)&ul_adb->buf[offset];
...
// This appears to be preparing for having
// _multiple_ "dg" structs at the end of
// struct mux_adth_dg, not just 1. (And, if so,
// should be using the struct_size(), or really,
// given the later subtraction, the flex_size(),
// helper.)
adth_dg_size = offsetof(struct mux_adth, dg) +
ul_adb->dg_count[i] * sizeof(*dg);
...
adth_dg_size -= offsetof(struct mux_adth, dg);
memcpy(&adth->dg, ul_adb->dg[i], adth_dg_size);
&adth->dg is 8 bytes, so the warning message is correct. However, it
seems like "ul_adb->dg_count[i]" contains a _count_ of "dg" structures
to copy, and, in the reported case, is "2".
The fix appears to be adjusting struct mux_adth with:
- struct mux_adth_dg dg;
+ struct mux_adth_dg dg[];
But, since this is an implicit "1-element array to flexible array"
conversion[1], we need to double-check "sizeof" uses.
I only see 3 cases of sizeof(struct mux_adth). This one removes the
"extra" "dg" element for bounds checking:
if (le16_to_cpu(adth->table_length) < (sizeof(struct mux_adth) -
sizeof(struct mux_adth_dg)))
This one adds it back in after subtracting 1 too many:
nr_of_dg = (le16_to_cpu(adth->table_length) -
sizeof(struct mux_adth) +
sizeof(struct mux_adth_dg)) /
sizeof(struct mux_adth_dg);
As does this one:
nr_of_dg = (le16_to_cpu(adth->table_length) -
sizeof(struct mux_adth) +
sizeof(struct mux_adth_dg)) /
sizeof(struct mux_adth_dg);
So they can be simplified to avoid the extra math.
I'll send a patch...
-Kees
[1] https://github.com/KSPP/linux/issues/79
--
Kees Cook
Powered by blists - more mailing lists