|
The msg_qbytes field in the struct msqid64_ds userspace ABI is an unsigned
long. Commit 889b331724c82 ("ipc/msg.c: consolidate all xxxctl_down()
functions") passes that value to msgctl_down() as an int.
On ABIs where unsigned long is wider than unsigned int, this narrows
msg_qbytes before validation and assignment. For example, an unprivileged
queue owner can request msg_qbytes = 0x100000000. The conversion to int
changes this value to zero, which passes the msg_ctlmnb check. IPC_SET
then succeeds and sets q_qbytes to zero instead of rejecting the requested
value with EPERM.
For callers with CAP_SYS_RESOURCE, values with bit 31 set are also
incorrectly sign-extended when assigned to q_qbytes. In particular,
UINT_MAX becomes ULONG_MAX rather than the requested UINT_MAX.
Keep msg_qbytes as unsigned long through validation and assignment. Also
preserve its type in ipcctl_obtain_check(), which passes it to the
unsigned-long audit field.
Add a regression test which drops CAP_SYS_RESOURCE and verifies that
IPC_SET with a value above UINT_MAX fails with EPERM where unsigned long
is wider than unsigned int. Skip the test when it is not, capabilities
are unavailable, or System V message queues are unavailable.
Link: https://lore.kernel.org/20261029-ipc-msg-qbytes-v3-1-fc3f4307c85b@gentwo.org
Fixes: 889b331724c8 ("ipc/msg.c: consolidate all xxxctl_down() functions")
Signed-off-by: Shubhang Kaushik (Ampere) <sh@gentwo.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Lu Shuaibing <shuaibinglu@126.com>
Cc: Shubhang Kaushik <shubhang@os.amperecomputing.com>
Cc: Christopher Lameter (Ampere) <cl@gentwo.org>
Cc: Davidlohr Bueso <dave@stgolabs.net>
Cc: Manfred Spraul <manfred@colorfullife.com>
Cc: Jan Koester <jan.koester@tuxist.de>
Cc: <stable@vger.kernel.org>
|