| CVE |
Vendors |
Products |
Updated |
CVSS v3.1 |
| In the Linux kernel, the following vulnerability has been resolved:
HID: intel-thc-hid: intel-quickspi: validate report size before copy
write_cmd_to_txdma() builds an output report in qsdev->report_buf, a heap
buffer allocated in quickspi_alloc_report_buf() to the device-descriptor
derived max_report_len (a few hundred bytes for a touch controller). It
copies the caller-supplied report into that buffer:
memcpy(write_buf->content, report_buf, report_buf_len);
The HID core caps a report at HID_MAX_BUFFER_SIZE (16384) by default, and
quickspi_hid_ll_driver does not set max_buffer_size, so the length reaches
the driver unbounded. A hidraw SET_REPORT/SET_FEATURE ioctl carrying a
report larger than max_report_len therefore overflows report_buf with
attacker-controlled length and content.
Record the report_buf allocation size and reject reports that do not fit
before copying, matching the equivalent guard in the intel-quicki2c
sibling (quicki2c_init_write_buf()) and the hid-goodix-spi fix.
write_cmd_to_txdma() writes the output report header ahead of the content
in the same buffer, so size the allocation to cover the header as well.
That keeps the added bound from rejecting a maximum-sized report. |
| In the Linux kernel, the following vulnerability has been resolved:
ntfs: bound the free-cluster bitmap scan to the volume
vol->lcn_empty_bits_per_page is sized from vol->nr_clusters at mount, but
ntfs_cluster_alloc() bounds its scan of that array by the size of $Bitmap.
Those are independent on-disk quantities and the mount-time check only
rejects a $Bitmap that is too small, so an image whose $Bitmap covers more
clusters than the volume has lets the scan index past the array. A run
whose LCN lies in that gap takes the allocator straight there, since the
caller passes the file's own last LCN as its locality hint. KASAN reports
a slab out-of-bounds read when a file on such a volume is extended.
Clamp the scan to what that array covers, mirroring the max_index
calculation the mount-time scan already uses, and reject a decoded LCN
at or beyond nr_clusters in the mapping pairs decoder. Conforming
volumes are unaffected. |
| In the Linux kernel, the following vulnerability has been resolved:
forcedeth: fix off-by-one when saving/restoring non-PCI config space
nv_suspend() and nv_resume() walk the non-PCI configuration space with
for (i = 0; i <= np->register_size/sizeof(u32); i++)
which runs one iteration too many. saved_config_space is declared as
u32 saved_config_space[NV_PCI_REGSZ_MAX/4];
and NV_PCI_REGSZ_VER3 is equal to NV_PCI_REGSZ_MAX (0x604), so on a VER3
device register_size/sizeof(u32) is exactly the array length and the last
iteration addresses one element past the end.
The element it lands on is np->name_rx[0..3]: saved_config_space[] is
followed immediately by char name_rx[IFNAMSIZ + 3], and char needs no
padding. Nothing observable is corrupted by that, because nv_request_irq()
rewrites name_rx with sprintf() before it is ever passed to request_irq().
The bug is the out-of-bounds access itself, which UBSAN reports and which
CONFIG_UBSAN_TRAP=y turns into a trap that aborts the running kernel code,
plus an MMIO read and, on resume, an MMIO writel() to base + 0x604, one
dword past the range the driver mapped:
np->base = ioremap(addr, np->register_size);
VER1 and VER2 devices stay inside the array, but they too get the stray
read and the stray write one dword past their own window.
Caught by UBSAN on an Apple Macmini3,1 (MCP79) during a deep S3 cycle.
The splat below is trimmed: the build path in the file name, the CPU
and taint lines, the Workqueue line, the "?" hint frames, and the
frames below device_suspend are all cut. The kernel was tainted, with
an out-of-tree nouveau and CPU_OUT_OF_SPEC; forcedeth itself was the
stock module.
UBSAN: array-index-out-of-bounds in drivers/net/ethernet/nvidia/forcedeth.c:6225:25
index 385 is out of range for type 'u32 [385]'
Call Trace:
dump_stack_lvl+0x5d/0x80
ubsan_epilogue+0x5/0x2b
__ubsan_handle_out_of_bounds.cold+0x54/0x59
__this_module+0xe398c/0xe9010 [forcedeth]
pci_pm_suspend+0x80/0x170
dpm_run_callback+0x51/0x160
device_suspend+0x1a2/0x4a0
...
Both loops are hit. UBSAN reports each source location only once per module
load (__ubsan_handle_out_of_bounds() calls suppress_report(), which does
test_and_set_bit(REPORTED_BIT, ...) on the struct source_location), so the
two splats land in the first S3 cycle after the module is loaded and later
cycles are silent even though the access still runs off the end every time.
In that first cycle line 6225 is reported from pci_pm_suspend and line 6240
from pci_pm_resume.
The same off-by-one was fixed in nv_get_regs() by commit ba9aa134287f
("forcedeth: fix buffer overflow") in 2012; these two loops were missed.
The suspend and resume side was reported on LKML in September 2013 by Marc
Weber, with the same analysis and the same one-character fix, but the patch
was attached rather than sent inline and the thread ended there.
Use < instead of <=, which saves and restores exactly register_size bytes. |
| In the Linux kernel, the following vulnerability has been resolved:
ACPI: pfr_update: fix stack buffer overflow in query_capability()
query_capability() copies four ACPI buffer objects returned by the
firmware _DSM into fixed-size u8[16] fields in struct
pfru_update_cap_info using memcpy with the firmware-supplied length:
memcpy(&cap_hdr->code_type,
elements[CAP_CODE_TYPE_IDX].buffer.pointer,
elements[CAP_CODE_TYPE_IDX].buffer.length);
The same pattern repeats for drv_type, platform_id, and oem_id.
If the firmware returns buffer.length > 16 for any of these fields,
memcpy writes past the destination array.
struct pfru_update_cap_info is stack-allocated in pfru_ioctl().
Confirmed with KASAN on 7.2-rc6: three stack-out-of-bounds reports
are generated when a DSM returns 64-byte buffers, with writes reaching
44 bytes past the end of cap_hdr's [64, 156) frame window into
adjacent stack redzones.
Introduce a helper pointer to out_obj->package.elements and use it
to validate each buffer length against its destination field size
before copying, returning -EINVAL if the firmware supplies an
oversized buffer. |
| In the Linux kernel, the following vulnerability has been resolved:
block: validate user space vectors during extraction
The bio-based drivers don't necessarily check the alignment split, and
stacking block drivers don't always handle a misalignment detected after
submitting the bio. Validate user vectors against the device's
dma_alignment as the bio is built from the iov_iter, rejecting
misaligned early with -EINVAL. |
| In the Linux kernel, the following vulnerability has been resolved:
Bluetooth: eir: Fix OOB read in eir_get_service_data()
eir_get_service_data() walks the advertising data for a Service Data
field with a matching UUID. On a mismatch it advances:
eir += dlen;
eir_len -= dlen;
eir_get_data() reports dlen as the field's data length, but the field
spans dlen + 2 bytes once its length and type bytes count, and more
when non-Service-Data fields were skipped to reach it. The pointer
lands correctly on the next field. eir_len does not, and the shortfall
compounds across fields until eir_get_data() reads the length and type
bytes of a "field" past the end of the buffer.
For an ISO broadcast sink that buffer is hcon->le_per_adv_data[], filled
from the periodic advertising reports of a remote broadcaster. A PA
payload packed with mismatching Service Data fields walks off the array
into the rest of struct hci_conn. A drifted field that matches the BAA
UUID puts those bytes in iso_pi(sk)->base, where user space reads them
back with getsockopt(BT_ISO_BASE).
Recompute eir_len from the end of the buffer each iteration. |
| In the Linux kernel, the following vulnerability has been resolved:
dm array: validate array block headers on read
array_block_check() validates blocknr and csum and nothing else, while
node_check(), next to it, has bounded the structural fields since both
were written. dm_array_cursor_next() takes its loop bound from the
on-disk nr_entries and element_at() is unguarded pointer arithmetic, so
a count larger than the block holds keeps the cursor in one block while
the index grows past it and the read walks off the dm-bufio buffer --
dm_cache_load_mappings() drives it once per cache block at activation.
Check the header against itself: reject a zero value_size, require
max_entries to equal calc_max_entries() for that value_size and block
size, and require nr_entries to fit. Equality rather than an upper bound,
since a count below the real capacity trips BUG_ON() in fill_ablock() and
trim_ablock(). Metadata dm-array writes satisfies all three. |
| In the Linux kernel, the following vulnerability has been resolved:
cxl/features: bound fwctl command payload to the input buffer
fwctl_cmd_rpc() copies cmd->in_len bytes into inbuf = kvzalloc(cmd->in_len)
and passes inbuf and in_len to ->fw_rpc(). The CXL callback cxlctl_fw_rpc()
ignores in_len and never checks the user-controlled op_size against it.
cxlctl_set_feature() bounds op_size only from below
(op_size <= sizeof(feat_in->hdr)) and then reads op_size - sizeof(hdr)
bytes from feat_in->feat_data via cxl_set_feature(). With a small in_len
and a large op_size the first memcpy() already reads past the
kvzalloc(in_len) buffer; the out-of-bounds bytes are placed in the mailbox
payload and sent to the device, and a large enough op_size can walk into
unmapped memory and oops the kernel. The Get paths pin op_size to a fixed
size but likewise read the input struct without checking in_len.
Reject, at the single dispatch point, any request whose fixed header plus
op_size does not fit in the copied-in buffer. The lower-bound test guards
the subtraction and ensures op_size was copied in before it is read. |
| In the Linux kernel, the following vulnerability has been resolved:
landlock: Require LANDLOCK_ACCESS_FS_MAKE_REG for whiteout creation
Whiteout objects are used in the upper layer of an OverlayFS to
indicate that the file with this name does not exist in the unified
view, even if it is present in one of the lower layer file systems.
For the userspace implementations of OverlayFS (fuse-overlayfs),
whiteout objects can be created from userspace as well:
* mknod(2) with S_IFCHR and makedev(0, 0)
* renameat2(2) with RENAME_WHITEOUT,
creating the whiteout in the old place of the moved file.
This commit guards whiteout creation in both of these cases with
LANDLOCK_ACCESS_FS_MAKE_REG. Whiteout objects are *not* considered
character devices and are not bound to a driver.
LANDLOCK_ACCESS_FS_MAKE_REG describes the same permission class as a
whiteout object: creating one is the only S_IFCHR creation that the VFS
exempts from CAP_MKNOD, so it is as unprivileged as creating a regular
file, while LANDLOCK_ACCESS_FS_MAKE_CHAR and
LANDLOCK_ACCESS_FS_MAKE_BLOCK keep meaning the creation of devices that
expose a kernel interface [1].
For the mknod(2) case, introduce a Landlock erratum. The creation of
whiteout objects through mknod(2) was previously guarded using
LANDLOCK_ACCESS_FS_MAKE_CHAR, and it is now guarded using
LANDLOCK_ACCESS_FS_MAKE_REG.
For the renameat2(2) case, fix a bug: Before this commit, renameat2(2)
with RENAME_WHITEOUT would create a directory entry even when all
LANDLOCK_ACCESS_FS_MAKE_* rights were denied.
This does not affect normal renames within layered OverlayFS mounts:
When doing a regular rename() on a mounted fuse-overlayfs, it is the
fuse-overlayfs daemon that exercises renameat2() with RENAME_WHITEOUT,
and only the Landlock domain of that daemon is checked there.
Depends-on: 49c9e09d9610 ("landlock: Fix handling of disconnected directories")
Depends-on: fe72ce6710cb ("landlock: Add errata documentation section")
[mic: Record why LANDLOCK_ACCESS_FS_MAKE_REG is the matching right, and
add link(2) to the user doc] |
| In the Linux kernel, the following vulnerability has been resolved:
SUNRPC: harden gss_krb5_unwrap_v2 against short tokens
gss_krb5_unwrap_v2() reads the EC and RRC header fields at ptr+4 and
ptr+6 before validating that the token is at least GSS_KRB5_TOK_HDR_LEN
(16) bytes long, and its rotate_left() helper passes buf->len - base
to xdr_buf_subsegment() without verifying that base <= buf->len. When
a caller hands in a sub-16-byte token, or a token whose declared len
leaves base past the end of the buffer, three distinct failures follow:
gss_krb5_unwrap_v2(offset, len, buf)
ptr = buf->head[0].iov_base + offset
ec = *(ptr + 4) /* OOB read on short head */
rrc = *(ptr + 6) /* OOB read on short head */
rotate_left(offset + 16, buf, rrc)
xdr_buf_subsegment(buf, &subbuf,
base, buf->len - base) /* u32 wrap when base > len */
_rotate_left(&subbuf, shift)
shift %= buf->len /* divide-by-zero when base == len */
After decryption, the cleanup arithmetic has the same shape:
movelen = min_t(unsigned int, buf->head[0].iov_len, len);
movelen -= offset + GSS_KRB5_TOK_HDR_LEN + headskip;
BUG_ON(offset + GSS_KRB5_TOK_HDR_LEN + headskip + movelen >
buf->head[0].iov_len);
The BUG_ON re-adds the value just subtracted, so it reduces to
min(A, B) > A and is permanently false; it cannot catch the unsigned
underflow of movelen, which then drives a ~UINT_MAX-byte memmove().
Add four defense-in-depth guards inside the unwrap core so it is safe
regardless of what its callers validate:
- reject tokens with len - offset < GSS_KRB5_TOK_HDR_LEN before
touching ptr+4/ptr+6;
- bail from rotate_left() when buf->len <= base, covering both the
underflow and zero-length cases;
- return early from _rotate_left() when buf->len is zero, so the
shift %= buf->len modulo cannot fault;
- replace the dead BUG_ON with a live check that returns
GSS_S_DEFECTIVE_TOKEN before the movelen subtraction. |
| In the Linux kernel, the following vulnerability has been resolved:
SUNRPC: harden gss_unwrap_resp_priv length checks
gss_unwrap_resp_priv() validates the RPCSEC_GSS opaque length with
offset = (u8 *)(p) - (u8 *)head->iov_base;
if (offset + opaque_len > rcv_buf->len)
goto unwrap_failed;
maj_stat = gss_unwrap(ctx->gc_gss_ctx, offset,
offset + opaque_len, rcv_buf);
Both operands are u32 and the sum is computed in u32. A reply with
opaque_len near 0xffffffff makes offset + opaque_len wrap to a small
value that is below rcv_buf->len, so the bound check passes and
gss_unwrap() is called with end < begin. The check also lacks a
lower bound, so any opaque_len in [0, GSS_KRB5_TOK_HDR_LEN) is
accepted and forwarded to gss_krb5_unwrap_v2(), whose pre-decrypt
header reads at ptr+4 and ptr+6 then run past the token.
A krb5p NFS server returning a crafted RPCSEC_GSS reply can drive
the client into out-of-bounds reads in gss_krb5_unwrap_v2() and the
rotate_left() loop that follows.
Fix by replacing the single combined check with three guards that
are safe in u32 arithmetic and that enforce the RFC 4121 minimum
outer token length:
if (offset > rcv_buf->len)
goto unwrap_failed;
if (opaque_len > rcv_buf->len - offset)
goto unwrap_failed;
if (opaque_len < GSS_KRB5_TOK_HDR_LEN)
goto unwrap_failed;
The first guard makes the subtraction in the second guard
unconditionally safe; offset is derived from a successful
xdr_inline_decode() in the head kvec, so in practice it already
satisfies the bound. The floor mirrors the server-side check added
in commit 5b757c2e57a5 ("SUNRPC: svcauth_gss: enforce krb5 token
minimum length"). |
| In the Linux kernel, the following vulnerability has been resolved:
SUNRPC: Reject short RFC 4121 MIC tokens in gss_krb5_verify_mic_v2
gss_krb5_verify_mic_v2() reads the token ID at ptr[0..1], the flags
byte at ptr[2], and padding at ptr[3..7], then passes
ptr + GSS_KRB5_TOK_HDR_LEN and cksum_len to gss_krb5_mic_build_sg().
None of these accesses check read_token->len first.
The minimum safe token size is GSS_KRB5_TOK_HDR_LEN (16) plus
ctx->krb5e->cksum_len (12-24, depending on the enctype). All callers
accept shorter tokens from the wire:
- gss_unwrap_resp_integ() enforces only an upper bound
(offset + len <= rcv_buf->len) before allocating
mic.data = kmalloc(len) and passing it to gss_verify_mic().
A malicious NFS server can therefore supply a short checksum
opaque, producing a small slab allocation that the Kerberos MIC
verifier reads past.
- gss_validate() enforces only len <= RPC_MAX_AUTH_SIZE (400)
before passing the wire-supplied length to
gss_validate_seqno_mic(), which constructs a mic xdr_netobj
and calls gss_verify_mic().
- svcauth_gss_verify_header() enforces only
checksum.len >= XDR_UNIT (4 bytes) before dispatching to
gss_verify_mic().
- svcauth_gss_unwrap_integ() checks only that the checksum fits
in gsd->gsd_scratch.
Add a length guard at the top of gss_krb5_verify_mic_v2(), before any
ptr[] access or scatterlist construction. Well-formed MIC tokens from
gss_krb5_get_mic_v2() already have exactly GSS_KRB5_TOK_HDR_LEN +
cksum_len bytes, so valid traffic is unaffected. |
| In the Linux kernel, the following vulnerability has been resolved:
svcrdma: Validate Read chunk positions before reconstruction
The RPC/RDMA Read chunk position field is supplied by the remote
client and stored verbatim in the parsed chunk list.
xdr_count_read_segments() checks only 4-byte alignment; it never
compares the position against the received inline body length.
In the single-chunk path, svc_rdma_read_complete_one() splits the
head and tail kvecs at ch_position. A position past the inline
body underflows the tail length, exposing adjacent slab memory to
the upper XDR decoder.
In the multi-chunk path, svc_rdma_read_multiple_chunks() computes
gap lengths between chunks as unsigned subtractions from
ch_position. Overlapping Read chunks cause these subtractions to
underflow. A final position past the inline body likewise
underflows the trailing gap length. svc_rdma_copy_inline_range()
then copies past the receive buffer into request pages that are
returned to the client through the Reply channel.
Bound inline-range copies in svc_rdma_copy_inline_range() against
the decoded inline RPC body saved in rc_saved_arg. Reject a
single Read chunk positioned beyond that body, and reject
multi-chunk lists where accumulated read bytes exceed the next
chunk's position. Apply the same position and overlap checks in
the call-chunk interleaving path. |
| In the Linux kernel, the following vulnerability has been resolved:
wifi: ath6kl: clamp assoc request/response lengths before subtracting IE offsets
ath6kl_cfg80211_connect_event() subtracts fixed IE offsets from
assoc_req_len (-= 4) and assoc_resp_len (-= 6), both u8, with no lower
bound. The aggregate check recently added to ath6kl_wmi_connect_event_rx()
bounds the declared lengths from above (their sum must fit the received
event), but an assoc request/response shorter than its fixed offset still
underflows here: the u8 wraps to ~250, and cfg80211_connect_result() /
cfg80211_roamed() then treat that wrapped value as the IE length and copy
that many bytes out of the small assoc_info buffer to user space via
nl80211, disclosing adjacent slab memory.
Clamp both lengths to their offsets before subtracting.
Found by 0sec (https://0sec.ai) using automated source analysis; the
missing lower bound is evident from source. Compile-tested. |
| In the Linux kernel, the following vulnerability has been resolved:
orangefs: skip leading spaces before parsing client debug masks
orangefs_prepare_cdm_array() sizes each client debug keyword buffer
with strcspn(cds_head, " "), but then parses the keyword with %s. The
%s conversion skips leading whitespace, while strcspn() does not.
If a client debug entry starts with a space, the allocation can be sized
for an empty keyword while sscanf() copies the following non-empty token.
This can write past the end of the allocated keyword buffer.
Skip leading spaces before computing the keyword length so the allocation
matches the string parsed by sscanf(). |
| In the Linux kernel, the following vulnerability has been resolved:
ocfs2: bound namelen in dlm_migrate_request_handler
Patch series "ocfs2/dlm: bound peer-controlled lengths in the o2dlm".
The o2dlm receive handlers trust u8 length and count fields from the wire
without bounding them, so a node in a DLM domain can corrupt or panic any
other node with a malformed message. Three defects:
- dlm_migrate_request_handler() passes migrate->namelen unchecked to
dlm_init_mle(), which memcpy()s it into the 32-byte mname[] of an
o2dlm_mle slab object: a heap out-of-bounds write of up to ~215
attacker-controlled bytes.
- dlm_mig_lockres_handler() passes mres->lockname_len unchecked to
dlm_init_lockres(), which memcpy()s it into the 32-byte o2dlm_lockname
slab object: a heap out-of-bounds write of up to ~223 bytes.
- the same handler trusts mres->num_locks without checking that the
message is large enough to hold that many entries, so
dlm_process_recovery_data() walks mres->ml[] past the kmalloc(data_len)
copy and trips a BUG_ON (an out-of-bounds read ending in a panic).
The other o2dlm receive handlers already reject an oversized name; the
migration and recovery handlers have omitted it since the DLM was added
(see the Fixes tags). Patch 1 bounds namelen; patch 2 validates
lockname_len, num_locks, and the payload size. Conforming recovery and
migration traffic is unaffected.
o2net authenticates peers only by the DLM domain key, so any node that has
joined the domain -- including a compromised or malicious member -- can
send these messages. There is no local trigger; the attacker must already
be a member of the cluster.
Each sink was confirmed under KASAN with an out-of-tree module mirroring
it exactly -- a kmem_cache/kmalloc of the real destination size, then the
same unclamped memcpy/loop: slab-out-of-bounds Write for the two writes,
Read for the recovery walk, and a panic. A userspace AddressSanitizer
build faults identically under -m32 and -m64. Scrubbed logs are available
on request.
I reported this privately to [email protected] and the ocfs2 maintainers
on 2026-06-20; with no response after the standard embargo period I am
posting the fix publicly. I have no embargo requirement.
This patch (of 2):
A node receiving a DLM_MIGRATE_REQUEST message trusts the peer-supplied
name length (migrate->namelen) without bounding it. dlm_init_mle() then
copies that many bytes into the fixed DLM_LOCKID_NAME_MAX-byte mname[]
array of an o2dlm_mle slab object, so a malformed message from a cluster
peer overflows the slab object by up to ~215 bytes: a heap out-of-bounds
write of attacker-controlled data, reachable by any node in the domain.
Reject an oversized name, the way dlm_master_request_handler() and the
other o2dlm receive handlers already do; the migration handler omits the
check entirely. Conforming messages are unaffected. |
| In the Linux kernel, the following vulnerability has been resolved:
power: supply: qcom_battmgr: terminate the strings from firmware
The qcom_battmgr_sc8280xp_strcpy() takes a Pascal-style string when the
firmware sends one. Otherwise it copies all BATTMGR_STRING_LEN bytes and
leaves the destination without a terminator.
Those destinations are model_number, serial_number and oem_info, each
BATTMGR_STRING_LEN and declared next to each other. They go out to user
space as val->strval, which power_supply_format_property() prints with
"%s", so a firmware string that fills the whole field makes that read run
into the following members.
Use strscpy() so the copy always terminates, the way the SM8350 path
already does for the same field. |
| In the Linux kernel, the following vulnerability has been resolved:
platform/x86: hp-bioscfg: fix heap OOB read on empty password write
validate_password_input() computes length = strlen(buf) and then
checks buf[length - 1] to strip a trailing newline, without checking
that length is nonzero first. Writing an empty string (a bare '\n')
to current_password or new_password gives length == 0, and
buf[length - 1] reads buf[-1], one byte before the heap allocation
holding the copied input.
KASAN confirms this directly:
BUG: KASAN: slab-out-of-bounds in store_password_instance.constprop.0+0x223/0x2a0 [hp_bioscfg]
Read of size 1 at addr ffff88811bd8da9f by task sh/13740
...
store_password_instance.constprop.0+0x223/0x2a0 [hp_bioscfg]
current_password_store+0x14/0x20 [hp_bioscfg]
...
The buggy address is located 23 bytes to the right of
allocated 8-byte region [ffff88811bd8da80, ffff88811bd8da88)
Reproduced identically via new_password_store. Execution continues
past the bad read (the garbage byte only affects whether "length" is
decremented by one), so the write completes and returns success; this
is a pure information read past the buffer, not a crash, but it is
still an out-of-bounds access KASAN correctly flags.
Fix by only checking buf[length - 1] when length is nonzero. |
| In the Linux kernel, the following vulnerability has been resolved:
net/smc: carry oversized SMC-Rv2 LLC messages in the queue entry
smc_llc_rmt_delete_rkey() and smc_llc_save_add_link_rkeys() read the part
of a v2 message that does not fit into the 44-byte union smc_llc_msg, and
both bound themselves by the size of the buffer it landed in, not by what
arrived. On a link with a shared v2 receive buffer a 44-byte
DELETE_RKEY_V2 declaring 255 rkeys reaches rkey[9..254] in whatever an
earlier message left in lgr->wr_rx_buf_v2, and passes each of them to
smc_rtoken_delete(). One of those 255 matched a registered rtoken and
deleted it. An ADD_LINK on such a link installs up to 255 rtokens from
the same bytes.
Copy the tail into the queue entry, so its length is the length of the
message that arrived, and declare the rkeys that fit inline as a member of
the union instead of reaching them through a cast. The same
DELETE_RKEY_V2 now processes the 9 rkeys it carries. The copy is limited
to the longest tail the two functions can read, so the peer does not pick
the size of the entry.
The bound the previous patch placed on links without a shared v2 receive
buffer is no longer needed. |
| In the Linux kernel, the following vulnerability has been resolved:
ALSA: 6fire: bound the MIDI event length from the device
usb6fire_comm_receiver_handler() forwards a MIDI event using a length
byte the device supplies, with no bound and no check that the transfer
delivered that many bytes:
if (!urb->status) {
if (rt->receiver_buffer[0] == 0x10) /* midi in event */
if (midi_rt)
midi_rt->in_received(midi_rt,
rt->receiver_buffer + 2,
rt->receiver_buffer[1]);
}
receiver_buffer is a 64-byte kzalloc() buffer (COMM_RECEIVER_BUFSIZE), so
only 62 bytes follow the two-byte header. receiver_buffer[1] is a u8 the
device chooses, so a device that answers with 0x10 and a length of 0xFF
makes snd_rawmidi_receive() read 255 bytes starting two bytes into a
64-byte object. The bytes past the buffer are handed to userspace
through the rawmidi read path.
urb->actual_length is not consulted either, so a short transfer leaves
both the type byte and the length byte at their previous values and the
handler acts on stale data.
The receiver URB is submitted from usb6fire_comm_init() at probe, so the
read happens on plug with no user action; forwarding to userspace also
needs a MIDI input substream open, since usb6fire_midi_in_received()
only calls snd_rawmidi_receive() when rt->in is set.
KASAN on 7.2.0-rc5 (arm64), single packet from an emulated device:
BUG: KASAN: slab-out-of-bounds in snd_rawmidi_receive
Read of size 255 at addr ffff000009f64682 by task bash/183
__asan_memcpy
snd_rawmidi_receive
usb6fire_midi_in_received [snd_usb_6fire]
usb6fire_comm_receiver_handler [snd_usb_6fire]
Allocated by task 11:
usb6fire_comm_init [snd_usb_6fire]
usb6fire_chip_probe [snd_usb_6fire]
The buggy address is located 2 bytes inside of
allocated 64-byte region [ffff000009f64680, ffff000009f646c0)
Reject the event when the length exceeds the bytes that follow the
header, and require the transfer to have delivered the header plus that
many bytes. The receiver URB is submitted with a 64-byte
transfer_buffer_length, so a genuine device cannot deliver an event
longer than those 62 bytes and nothing valid is dropped.
Discovered by XBOW, triaged by Baul Lee <[email protected]> |