diff options
author | Richard Henderson <richard.henderson@linaro.org> | 2022-04-29 12:15:14 -0700 |
---|---|---|
committer | Richard Henderson <richard.henderson@linaro.org> | 2022-06-28 04:35:52 +0530 |
commit | 40f1219a8b2f95808ed5a18798dbce1b57fef211 (patch) | |
tree | c4838d2783f9be34e280708c2153f31fc94993d2 | |
parent | aa915bd0a67d6c0a214b45372ed841521c5cd07a (diff) | |
download | qemu-40f1219a8b2f95808ed5a18798dbce1b57fef211.zip qemu-40f1219a8b2f95808ed5a18798dbce1b57fef211.tar.gz qemu-40f1219a8b2f95808ed5a18798dbce1b57fef211.tar.bz2 |
semihosting: Bound length for semihost_sys_{read,write}
Fixes a minor bug in which a 64-bit guest on a 32-bit host could
truncate the length. This would only ever cause a problem if
there were no bits set in the low 32, so that it truncates to 0.
Reviewed-by: Luc Michel <lmichel@kalray.eu>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
-rw-r--r-- | semihosting/syscalls.c | 16 |
1 files changed, 16 insertions, 0 deletions
diff --git a/semihosting/syscalls.c b/semihosting/syscalls.c index 5cb12d6..eefbae7 100644 --- a/semihosting/syscalls.c +++ b/semihosting/syscalls.c @@ -283,6 +283,14 @@ void semihost_sys_close(CPUState *cs, gdb_syscall_complete_cb complete, int fd) void semihost_sys_read_gf(CPUState *cs, gdb_syscall_complete_cb complete, GuestFD *gf, target_ulong buf, target_ulong len) { + /* + * Bound length for 64-bit guests on 32-bit hosts, not overlowing ssize_t. + * Note the Linux kernel does this with MAX_RW_COUNT, so it's not a bad + * idea to do this unconditionally. + */ + if (len > INT32_MAX) { + len = INT32_MAX; + } switch (gf->type) { case GuestFDGDB: gdb_read(cs, complete, gf, buf, len); @@ -313,6 +321,14 @@ void semihost_sys_read(CPUState *cs, gdb_syscall_complete_cb complete, void semihost_sys_write_gf(CPUState *cs, gdb_syscall_complete_cb complete, GuestFD *gf, target_ulong buf, target_ulong len) { + /* + * Bound length for 64-bit guests on 32-bit hosts, not overlowing ssize_t. + * Note the Linux kernel does this with MAX_RW_COUNT, so it's not a bad + * idea to do this unconditionally. + */ + if (len > INT32_MAX) { + len = INT32_MAX; + } switch (gf->type) { case GuestFDGDB: gdb_write(cs, complete, gf, buf, len); |