Merge tag 'linux-user-for-v11.1-pull-request' of https://github.com/hdeller/qemu-hppa into staging

linux-user-for-v11.1 pull request

Please pull two fixes for linux-user for v11.1:
- Validate guest-passed dm_ioctl data_size
- Alpha: Fix programs using getauxval(AT_HWCAP) to detect BWX/FIX/CIX

# -----BEGIN PGP SIGNATURE-----
#
# iHUEABYKAB0WIQS86RI+GtKfB8BJu973ErUQojoPXwUCalT3fwAKCRD3ErUQojoP
# X7twAPsH/PcMbDMiwKluAOE+/r1rZ95Qp9YXuKfZhUypoizivwEAs5IdB5PKwI5s
# lGaJdOpkm7HWAEbjiYgr25d+dPBcagg=
# =zCLL
# -----END PGP SIGNATURE-----
# gpg: Signature made Mon 13 Jul 2026 15:34:39 BST
# gpg:                using EDDSA key BCE9123E1AD29F07C049BBDEF712B510A23A0F5F
# gpg: Good signature from "Helge Deller <deller@gmx.de>" [unknown]
# gpg:                 aka "Helge Deller <deller@kernel.org>" [unknown]
# gpg:                 aka "Helge Deller <deller@debian.org>" [unknown]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 4544 8228 2CD9 10DB EF3D  25F8 3E5F 3D04 A7A2 4603
#      Subkey fingerprint: BCE9 123E 1AD2 9F07 C049  BBDE F712 B510 A23A 0F5F

* tag 'linux-user-for-v11.1-pull-request' of https://github.com/hdeller/qemu-hppa:
  linux-user/alpha: populate AT_HWCAP from env->amask
  linux-user: Validate guest-passed dm_ioctl data_size

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Stefan Hajnoczi
2026-07-14 07:25:06 +01:00
3 changed files with 38 additions and 4 deletions

View File

@@ -6,6 +6,17 @@
#include "target_elf.h"
abi_ulong get_elf_hwcap(CPUState *cs)
{
/*
* The Linux kernel computes ELF_HWCAP as ~amask(-1), which clears a bit
* for each supported ISA extension. env->amask stores exactly those bits
* set for the extensions supported by the emulated CPU model, matching
* the kernel's convention: bit set in AT_HWCAP ↔ extension present.
*/
return cpu_env(cs)->amask;
}
void elf_core_copy_regs(target_elf_gregset_t *r, const CPUAlphaState *env)
{
int i;

View File

@@ -12,6 +12,7 @@
#define ELF_MACHINE EM_ALPHA
#define HAVE_ELF_CORE_DUMP 1
#define HAVE_ELF_HWCAP 1
/*
* Matches the kernel's elf_gregset_t (ELF_NGREG = 33):

View File

@@ -5088,6 +5088,9 @@ do_ioctl_usbdevfs_submiturb(const IOCTLEntry *ie, uint8_t *buf_temp,
}
#endif /* CONFIG_USBFS */
#define DM_MAX_TARGETS 1048576
#define DM_MAX_TARGET_PARAMS 1024
static abi_long do_ioctl_dm(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
int cmd, abi_long arg)
{
@@ -5100,6 +5103,7 @@ static abi_long do_ioctl_dm(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
abi_long ret;
void *big_buf = NULL;
char *host_data;
const size_t minimum_data_size = offsetof(struct dm_ioctl, data);
arg_type++;
target_size = thunk_type_size(arg_type, 0);
@@ -5111,9 +5115,26 @@ static abi_long do_ioctl_dm(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
unlock_user(argptr, arg, 0);
/* buf_temp is too small, so fetch things into a bigger buffer */
big_buf = g_malloc0(((struct dm_ioctl*)buf_temp)->data_size * 2);
memcpy(big_buf, buf_temp, target_size);
/* At this point this includes the size of the fixed dm_ioctl parts */
guest_data_size = ((struct dm_ioctl *)buf_temp)->data_size;
if (guest_data_size < minimum_data_size ||
guest_data_size > DM_MAX_TARGETS * DM_MAX_TARGET_PARAMS) {
ret = -TARGET_EINVAL;
goto out;
}
/*
* buf_temp is too small, so fetch things into a bigger buffer. Here
* we copy all of the fixed parts of struct dm_ioctl but not the
* data at the end (which in the struct is "char data[7]" but in
* reality is command-specific and might be nothing or might be
* much larger, as defined by data_size). We know struct dm_ioctl's
* size is not target specific so we don't need to distinguish between
* its minimum size for the host vs the target.
*/
big_buf = g_malloc0(guest_data_size * 2);
memcpy(big_buf, buf_temp, minimum_data_size);
buf_temp = big_buf;
host_dm = big_buf;
@@ -5122,7 +5143,8 @@ static abi_long do_ioctl_dm(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
ret = -TARGET_EINVAL;
goto out;
}
guest_data_size = host_dm->data_size - host_dm->data_start;
/* Adjust down to only the size of the payload */
guest_data_size -= host_dm->data_start;
host_data = (char*)host_dm + host_dm->data_start;
argptr = lock_user(VERIFY_READ, guest_data, guest_data_size, 1);