commit b1a37ed00d7908a991c1d0f18a8cba3c2aa99bdc upstream.
Presently, when a report is processed, its proposed size, provided by
the user of the API (as Report Size * Report Count) is compared against
the subsystem default HID_MAX_BUFFER_SIZE (16k). However, some
low-level HID drivers allocate a reduced amount of memory to their
buffers (e.g. UHID only allocates UHID_DATA_MAX (4k) buffers), rending
this check inadequate in some cases.
In these circumstances, if the received report ends up being smaller
than the proposed report size, the remainder of the buffer is zeroed.
That is, the space between sizeof(csize) (size of the current report)
and the rsize (size proposed i.e. Report Size * Report Count), which can
be handled up to HID_MAX_BUFFER_SIZE (16k). Meaning that memset()
shoots straight past the end of the buffer boundary and starts zeroing
out in-use values, often resulting in calamity.
This patch introduces a new variable into 'struct hid_ll_driver' where
individual low-level drivers can over-ride the default maximum value of
HID_MAX_BUFFER_SIZE (16k) with something more sympathetic to the
interface.
Signed-off-by: Lee Jones <lee(a)kernel.org>
Signed-off-by: Jiri Kosina <jkosina(a)suse.cz>
Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
[Lee: Backported to v4.9.y]
Signed-off-by: Lee Jones <lee(a)kernel.org>
---
drivers/hid/hid-core.c | 18 +++++++++++++-----
include/linux/hid.h | 3 +++
2 files changed, 16 insertions(+), 5 deletions(-)
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index c5207ed5d65b1..b9e6c51173571 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -246,6 +246,7 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign
unsigned usages;
unsigned offset;
unsigned i;
+ unsigned int max_buffer_size = HID_MAX_BUFFER_SIZE;
report = hid_register_report(parser->device, report_type, parser->global.report_id);
if (!report) {
@@ -269,8 +270,11 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign
offset = report->size;
report->size += parser->global.report_size * parser->global.report_count;
+ if (parser->device->ll_driver->max_buffer_size)
+ max_buffer_size = parser->device->ll_driver->max_buffer_size;
+
/* Total size check: Allow for possible report index byte */
- if (report->size > (HID_MAX_BUFFER_SIZE - 1) << 3) {
+ if (report->size > (max_buffer_size - 1) << 3) {
hid_err(parser->device, "report is too long\n");
return -1;
}
@@ -1548,6 +1552,7 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size,
struct hid_report_enum *report_enum = hid->report_enum + type;
struct hid_report *report;
struct hid_driver *hdrv;
+ int max_buffer_size = HID_MAX_BUFFER_SIZE;
unsigned int a;
u32 rsize, csize = size;
u8 *cdata = data;
@@ -1564,10 +1569,13 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size,
rsize = hid_compute_report_size(report);
- if (report_enum->numbered && rsize >= HID_MAX_BUFFER_SIZE)
- rsize = HID_MAX_BUFFER_SIZE - 1;
- else if (rsize > HID_MAX_BUFFER_SIZE)
- rsize = HID_MAX_BUFFER_SIZE;
+ if (hid->ll_driver->max_buffer_size)
+ max_buffer_size = hid->ll_driver->max_buffer_size;
+
+ if (report_enum->numbered && rsize >= max_buffer_size)
+ rsize = max_buffer_size - 1;
+ else if (rsize > max_buffer_size)
+ rsize = max_buffer_size;
if (csize < rsize) {
dbg_hid("report %d is too short, (%d < %d)\n", report->id,
diff --git a/include/linux/hid.h b/include/linux/hid.h
index a07fa623fd0c2..be12e7d14c4a1 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -736,6 +736,7 @@ struct hid_driver {
* @raw_request: send raw report request to device (e.g. feature report)
* @output_report: send output report to device
* @idle: send idle request to device
+ * @max_buffer_size: over-ride maximum data buffer size (default: HID_MAX_BUFFER_SIZE)
*/
struct hid_ll_driver {
int (*start)(struct hid_device *hdev);
@@ -760,6 +761,8 @@ struct hid_ll_driver {
int (*output_report) (struct hid_device *hdev, __u8 *buf, size_t len);
int (*idle)(struct hid_device *hdev, int report, int idle, int reqtype);
+
+ unsigned int max_buffer_size;
};
extern struct hid_ll_driver i2c_hid_ll_driver;
--
2.40.0.rc1.284.g88254d51c5-goog
The patch below does not apply to the 6.1-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable(a)vger.kernel.org>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.1.y
git checkout FETCH_HEAD
git cherry-pick -x 5da28edd7bd5518f97175ecea77615bb729a7a28
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<stable(a)vger.kernel.org>' --in-reply-to '167931300423217(a)kroah.com' --subject-prefix 'PATCH 6.1.y' HEAD^..
Possible dependencies:
5da28edd7bd5 ("io_uring/msg_ring: let target know allocated index")
172113101641 ("io_uring: extract a io_msg_install_complete helper")
11373026f296 ("io_uring: get rid of double locking")
b529c96a896b ("io_uring: remove overflow param from io_post_aux_cqe")
a77ab745f28d ("io_uring: make io_fill_cqe_aux static")
9b8c54755a2b ("io_uring: add io_aux_cqe which allows deferred completion")
931147ddfa6e ("io_uring: allow defer completion for aux posted cqes")
1bec951c3809 ("io_uring: iopoll protect complete_post")
fa18fa2272c7 ("io_uring: inline __io_req_complete_put()")
f9d567c75ec2 ("io_uring: inline __io_req_complete_post()")
e2ad599d1ed3 ("io_uring: allow multishot recv CQEs to overflow")
515e26961295 ("io_uring: revert "io_uring fix multishot accept ordering"")
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 5da28edd7bd5518f97175ecea77615bb729a7a28 Mon Sep 17 00:00:00 2001
From: Pavel Begunkov <asml.silence(a)gmail.com>
Date: Thu, 16 Mar 2023 12:11:42 +0000
Subject: [PATCH] io_uring/msg_ring: let target know allocated index
msg_ring requests transferring files support auto index selection via
IORING_FILE_INDEX_ALLOC, however they don't return the selected index
to the target ring and there is no other good way for the userspace to
know where is the receieved file.
Return the index for allocated slots and 0 otherwise, which is
consistent with other fixed file installing requests.
Cc: stable(a)vger.kernel.org # v6.0+
Fixes: e6130eba8a848 ("io_uring: add support for passing fixed file descriptors")
Signed-off-by: Pavel Begunkov <asml.silence(a)gmail.com>
Link: https://github.com/axboe/liburing/issues/809
Signed-off-by: Jens Axboe <axboe(a)kernel.dk>
diff --git a/io_uring/msg_ring.c b/io_uring/msg_ring.c
index 8803c0979e2a..85fd7ce5f05b 100644
--- a/io_uring/msg_ring.c
+++ b/io_uring/msg_ring.c
@@ -202,7 +202,7 @@ static int io_msg_install_complete(struct io_kiocb *req, unsigned int issue_flag
* completes with -EOVERFLOW, then the sender must ensure that a
* later IORING_OP_MSG_RING delivers the message.
*/
- if (!io_post_aux_cqe(target_ctx, msg->user_data, msg->len, 0))
+ if (!io_post_aux_cqe(target_ctx, msg->user_data, ret, 0))
ret = -EOVERFLOW;
out_unlock:
io_double_unlock_ctx(target_ctx);
@@ -229,6 +229,8 @@ static int io_msg_send_fd(struct io_kiocb *req, unsigned int issue_flags)
struct io_ring_ctx *ctx = req->ctx;
struct file *src_file = msg->src_file;
+ if (msg->len)
+ return -EINVAL;
if (target_ctx == ctx)
return -EINVAL;
if (target_ctx->flags & IORING_SETUP_R_DISABLED)
Greg,
Following backports catch up with recent 5.15.y xfs backports.
Patches 1-3 are the backports from the previous 5.15 xfs backports
round that Chandan requested for 5.4 [1].
Patches 4-14 are the SGID fixes that I collaborated with Leah [2].
Christian has reviewed the backports of his vfs patches to 5.10.
Patch 15 is a fix for a build warning caused by one of the SGID fixes
that you applied to 5.15.y.
This series has gone through the usual xfs test/review routine.
Thanks,
Amir.
[1] https://lore.kernel.org/linux-xfs/874jrtzlgp.fsf@debian-BULLSEYE-live-build…
[2] https://lore.kernel.org/linux-xfs/20230307185922.125907-1-leah.rumancik@gma…
Amir Goldstein (4):
attr: add in_group_or_capable()
fs: move should_remove_suid()
attr: add setattr_should_drop_sgid()
attr: use consistent sgid stripping checks
Christian Brauner (1):
fs: use consistent setgid checks in is_sxid()
Darrick J. Wong (3):
xfs: purge dquots after inode walk fails during quotacheck
xfs: don't leak btree cursor when insrec fails after a split
xfs: use setattr_copy to set vfs inode attributes
Dave Chinner (4):
xfs: don't assert fail on perag references on teardown
xfs: remove XFS_PREALLOC_SYNC
xfs: fallocate() should call file_modified()
xfs: set prealloc flag in xfs_alloc_file_space()
Gaosheng Cui (1):
xfs: remove xfs_setattr_time() declaration
Yang Xu (2):
fs: add mode_strip_sgid() helper
fs: move S_ISGID stripping into the vfs_*() helpers
Documentation/trace/ftrace.rst | 2 +-
fs/attr.c | 70 ++++++++++++++++++++++++++---
fs/inode.c | 80 +++++++++++++++++++---------------
fs/internal.h | 6 +++
fs/namei.c | 80 ++++++++++++++++++++++++++++------
fs/ocfs2/file.c | 4 +-
fs/ocfs2/namei.c | 1 +
fs/open.c | 6 +--
fs/xfs/libxfs/xfs_btree.c | 8 ++--
fs/xfs/xfs_bmap_util.c | 9 ++--
fs/xfs/xfs_file.c | 24 +++++-----
fs/xfs/xfs_iops.c | 56 ++----------------------
fs/xfs/xfs_iops.h | 1 -
fs/xfs/xfs_mount.c | 3 +-
fs/xfs/xfs_pnfs.c | 9 ++--
fs/xfs/xfs_qm.c | 9 +++-
include/linux/fs.h | 5 ++-
17 files changed, 229 insertions(+), 144 deletions(-)
--
2.34.1
The patch below does not apply to the 5.10-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable(a)vger.kernel.org>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.10.y
git checkout FETCH_HEAD
git cherry-pick -x a52e5cdbe8016d4e3e6322fd93d71afddb9a5af9
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<stable(a)vger.kernel.org>' --in-reply-to '16793039081369(a)kroah.com' --subject-prefix 'PATCH 5.10.y' HEAD^..
Possible dependencies:
a52e5cdbe801 ("s390/ipl: add missing intersection check to ipl_report handling")
84733284f67b ("s390/boot: introduce boot data 'initrd_data'")
9f744abb4639 ("s390/boot: replace magic string check with a bootdata flag")
73045a08cf55 ("s390: unify identity mapping limits handling")
d7e7fbba67a3 ("s390/early: rewrite program parameter setup in C")
0c4ec024a481 ("s390/kasan: move memory needs estimation into a function")
92bca2fe61f5 ("s390/kasan: avoid confusing naming")
90178c190079 ("s390/mm: let vmalloc area size depend on physical memory size")
a3453d923ece ("s390/kasan: remove 3-level paging support")
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From a52e5cdbe8016d4e3e6322fd93d71afddb9a5af9 Mon Sep 17 00:00:00 2001
From: Sven Schnelle <svens(a)linux.ibm.com>
Date: Tue, 7 Mar 2023 14:35:23 +0100
Subject: [PATCH] s390/ipl: add missing intersection check to ipl_report
handling
The code which handles the ipl report is searching for a free location
in memory where it could copy the component and certificate entries to.
It checks for intersection between the sections required for the kernel
and the component/certificate data area, but fails to check whether
the data structures linking these data areas together intersect.
This might cause the iplreport copy code to overwrite the iplreport
itself. Fix this by adding two addtional intersection checks.
Cc: <stable(a)vger.kernel.org>
Fixes: 9641b8cc733f ("s390/ipl: read IPL report at early boot")
Signed-off-by: Sven Schnelle <svens(a)linux.ibm.com>
Reviewed-by: Vasily Gorbik <gor(a)linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor(a)linux.ibm.com>
diff --git a/arch/s390/boot/ipl_report.c b/arch/s390/boot/ipl_report.c
index 9b14045065b6..74b5cd264862 100644
--- a/arch/s390/boot/ipl_report.c
+++ b/arch/s390/boot/ipl_report.c
@@ -57,11 +57,19 @@ static unsigned long find_bootdata_space(struct ipl_rb_components *comps,
if (IS_ENABLED(CONFIG_BLK_DEV_INITRD) && initrd_data.start && initrd_data.size &&
intersects(initrd_data.start, initrd_data.size, safe_addr, size))
safe_addr = initrd_data.start + initrd_data.size;
+ if (intersects(safe_addr, size, (unsigned long)comps, comps->len)) {
+ safe_addr = (unsigned long)comps + comps->len;
+ goto repeat;
+ }
for_each_rb_entry(comp, comps)
if (intersects(safe_addr, size, comp->addr, comp->len)) {
safe_addr = comp->addr + comp->len;
goto repeat;
}
+ if (intersects(safe_addr, size, (unsigned long)certs, certs->len)) {
+ safe_addr = (unsigned long)certs + certs->len;
+ goto repeat;
+ }
for_each_rb_entry(cert, certs)
if (intersects(safe_addr, size, cert->addr, cert->len)) {
safe_addr = cert->addr + cert->len;