* [PULL 1/4] linux-user: Add missing CDROM ioctls
2026-04-30 7:19 [PULL 0/4] Linux user next patches Helge Deller
@ 2026-04-30 7:19 ` Helge Deller
2026-04-30 7:19 ` [PULL 2/4] linux-user: Flush errors by using exit() instead of _exit() in error path Helge Deller
` (3 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Helge Deller @ 2026-04-30 7:19 UTC (permalink / raw)
To: qemu-devel; +Cc: Laurent Vivier, Helge Deller, Pierrick Bouvier
From: Helge Deller <deller@gmx.de>
Add the missing CDROM ioctls and bring them in same order as
documentation.
Signed-off-by: Helge Deller <deller@gmx.de>
---
linux-user/ioctls.h | 29 +++++++++++++++++------------
1 file changed, 17 insertions(+), 12 deletions(-)
diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
index 5b7d00e92f..aa485ee6e5 100644
--- a/linux-user/ioctls.h
+++ b/linux-user/ioctls.h
@@ -416,19 +416,18 @@
#endif
IOCTL(CDROMPAUSE, 0, TYPE_NULL)
- IOCTL(CDROMSTART, 0, TYPE_NULL)
- IOCTL(CDROMSTOP, 0, TYPE_NULL)
IOCTL(CDROMRESUME, 0, TYPE_NULL)
- IOCTL(CDROMEJECT, 0, TYPE_NULL)
- IOCTL(CDROMEJECT_SW, 0, TYPE_INT)
- IOCTL(CDROMCLOSETRAY, 0, TYPE_NULL)
- IOCTL(CDROMRESET, 0, TYPE_NULL)
IOCTL(CDROMPLAYMSF, IOC_W, MK_PTR(TYPE_INT))
IOCTL(CDROMPLAYTRKIND, IOC_W, MK_PTR(TYPE_INT))
IOCTL(CDROMREADTOCHDR, IOC_R, MK_PTR(TYPE_INT))
IOCTL(CDROMREADTOCENTRY, IOC_RW, MK_PTR(TYPE_INT))
+ IOCTL(CDROMSTOP, 0, TYPE_NULL)
+ IOCTL(CDROMSTART, 0, TYPE_NULL)
+ IOCTL(CDROMEJECT, 0, TYPE_NULL)
IOCTL(CDROMVOLCTRL, IOC_W, MK_PTR(TYPE_INT))
IOCTL(CDROMSUBCHNL, IOC_RW, MK_PTR(TYPE_INT))
+ IOCTL(CDROMEJECT_SW, IOC_W, TYPE_INT)
+ IOCTL(CDROMRESET, 0, TYPE_NULL)
/* XXX: incorrect (need specific handling) */
IOCTL(CDROMREADAUDIO, IOC_W, MK_PTR(MK_STRUCT(STRUCT_cdrom_read_audio)))
IOCTL(CDROMREADCOOKED, IOC_RW, MK_PTR(TYPE_INT))
@@ -438,16 +437,22 @@
IOCTL(CDROMREADALL, IOC_RW, MK_PTR(TYPE_INT))
IOCTL(CDROMMULTISESSION, IOC_RW, MK_PTR(TYPE_INT))
IOCTL(CDROM_GET_UPC, IOC_R, MK_PTR(TYPE_INT))
+ IOCTL(CDROM_LAST_WRITTEN, IOC_R, MK_PTR(TYPE_LONG))
IOCTL(CDROMVOLREAD, IOC_R, MK_PTR(TYPE_INT))
IOCTL(CDROMSEEK, IOC_W, MK_PTR(TYPE_INT))
IOCTL(CDROMPLAYBLK, IOC_W, MK_PTR(TYPE_INT))
- IOCTL(CDROM_MEDIA_CHANGED, 0, TYPE_NULL)
- IOCTL(CDROM_SET_OPTIONS, 0, TYPE_INT)
- IOCTL(CDROM_CLEAR_OPTIONS, 0, TYPE_INT)
- IOCTL(CDROM_SELECT_SPEED, 0, TYPE_INT)
- IOCTL(CDROM_SELECT_DISC, 0, TYPE_INT)
- IOCTL(CDROM_DRIVE_STATUS, 0, TYPE_NULL)
+ IOCTL(CDROMCLOSETRAY, 0, TYPE_NULL)
+ IOCTL(CDROM_SET_OPTIONS, IOC_W, TYPE_INT)
+ IOCTL(CDROM_CLEAR_OPTIONS, IOC_W, TYPE_INT)
+ IOCTL(CDROM_SELECT_SPEED, IOC_W, TYPE_INT)
+ IOCTL(CDROM_SELECT_DISC, IOC_W, TYPE_INT)
+ IOCTL(CDROM_MEDIA_CHANGED, IOC_W, TYPE_INT)
+ IOCTL(CDROM_DRIVE_STATUS, IOC_W, TYPE_INT)
IOCTL(CDROM_DISC_STATUS, 0, TYPE_NULL)
+ IOCTL(CDROM_CHANGER_NSLOTS, 0, TYPE_NULL)
+ IOCTL(CDROM_LOCKDOOR, IOC_W, TYPE_INT)
+ IOCTL(CDROM_DEBUG, IOC_W, TYPE_INT)
+ IOCTL(CDROM_GET_CAPABILITY, 0, TYPE_NULL)
IOCTL(CDROMAUDIOBUFSIZ, 0, TYPE_INT)
#if 0
--
2.53.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PULL 3/4] linux-user: Allow getsockopt() with NULL optval address
2026-04-30 7:19 [PULL 0/4] Linux user next patches Helge Deller
2026-04-30 7:19 ` [PULL 1/4] linux-user: Add missing CDROM ioctls Helge Deller
2026-04-30 7:19 ` [PULL 2/4] linux-user: Flush errors by using exit() instead of _exit() in error path Helge Deller
@ 2026-04-30 7:19 ` Helge Deller
2026-04-30 7:19 ` [PULL 4/4] linux-user: Translate errno in IP_RECVERR and IPV6_RECVERR Helge Deller
2026-04-30 17:35 ` [PULL 0/4] Linux user next patches Stefan Hajnoczi
4 siblings, 0 replies; 8+ messages in thread
From: Helge Deller @ 2026-04-30 7:19 UTC (permalink / raw)
To: qemu-devel; +Cc: Laurent Vivier, Helge Deller, Pierrick Bouvier
From: Helge Deller <deller@gmx.de>
Some programs test availability of socket options by asking for the
value with an NULL optval address, which currenrly always trigger an
EFAULT in qemu. Fix it by allowing a NULL address, in the same manner
as the Linux kernel on physical machines.
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/2390
Signed-off-by: Helge Deller <deller@gmx.de>
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@oss.qualcomm.com>
---
linux-user/syscall.c | 50 +++++++++++++++++++++++++-------------------
1 file changed, 28 insertions(+), 22 deletions(-)
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 4594909242..d68edb7afd 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -2644,6 +2644,10 @@ get_timeout:
if (ret < 0) {
return ret;
}
+ /* special case: destination address is NULL, return 0 */
+ if (optval_addr) {
+ len = 0;
+ }
if (len == sizeof(struct target__kernel_sock_timeval)) {
if (copy_to_user_timeval64(optval_addr, &tv)) {
return -TARGET_EFAULT;
@@ -2844,7 +2848,10 @@ get_timeout:
}
if (len > lv)
len = lv;
- if (len == 4) {
+ if (!optval_addr) {
+ /* writing to NULL does not give error */
+ len = 0;
+ } else if (len == 4) {
if (put_user_u32(val, optval_addr))
return -TARGET_EFAULT;
} else {
@@ -2877,18 +2884,24 @@ get_timeout:
return -TARGET_EINVAL;
lv = sizeof(lv);
ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
+write_ret:
if (ret < 0)
return ret;
- if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
+ if (!optval_addr) {
+ len = 0;
+ } else if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
len = 1;
- if (put_user_u32(len, optlen)
- || put_user_u8(val, optval_addr))
+ if (put_user_u8(val, optval_addr)) {
return -TARGET_EFAULT;
+ }
} else {
if (len > sizeof(int))
len = sizeof(int);
- if (put_user_u32(len, optlen)
- || put_user_u32(val, optval_addr))
+ if (put_user_u32(val, optval_addr)) {
+ return -TARGET_EFAULT;
+ }
+ }
+ if (put_user_u32(len, optlen)) {
return -TARGET_EFAULT;
}
break;
@@ -2939,20 +2952,7 @@ get_timeout:
return -TARGET_EINVAL;
lv = sizeof(lv);
ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
- if (ret < 0)
- return ret;
- if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
- len = 1;
- if (put_user_u32(len, optlen)
- || put_user_u8(val, optval_addr))
- return -TARGET_EFAULT;
- } else {
- if (len > sizeof(int))
- len = sizeof(int);
- if (put_user_u32(len, optlen)
- || put_user_u32(val, optval_addr))
- return -TARGET_EFAULT;
- }
+ goto write_ret;
break;
default:
ret = -TARGET_ENOPROTOOPT;
@@ -2986,8 +2986,14 @@ get_timeout:
if (ret < 0) {
return ret;
}
- if (put_user_u32(lv, optlen)
- || put_user_u32(val, optval_addr)) {
+ if (optval_addr) {
+ if (put_user_u32(val, optval_addr)) {
+ return -TARGET_EFAULT;
+ }
+ } else {
+ lv = 0;
+ }
+ if (put_user_u32(lv, optlen)) {
return -TARGET_EFAULT;
}
break;
--
2.53.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PULL 4/4] linux-user: Translate errno in IP_RECVERR and IPV6_RECVERR
2026-04-30 7:19 [PULL 0/4] Linux user next patches Helge Deller
` (2 preceding siblings ...)
2026-04-30 7:19 ` [PULL 3/4] linux-user: Allow getsockopt() with NULL optval address Helge Deller
@ 2026-04-30 7:19 ` Helge Deller
2026-04-30 17:35 ` [PULL 0/4] Linux user next patches Stefan Hajnoczi
4 siblings, 0 replies; 8+ messages in thread
From: Helge Deller @ 2026-04-30 7:19 UTC (permalink / raw)
To: qemu-devel; +Cc: Laurent Vivier, Helge Deller, Pierrick Bouvier
From: Helge Deller <deller@gmx.de>
Translate host error codes of IP_RECVERR and IPV6_RECVERR control messages to
target error codes before returning to the caller.
For example, this is important for architectures (e.g. hppa, alpha, sparc,
mips) on which the value of ECONNREFUSED is different to the value on a x86_64
host.
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/602
Signed-off-by: Helge Deller <deller@gmx.de>
---
linux-user/syscall.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index d68edb7afd..d3d9fffb54 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -2008,7 +2008,8 @@ static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
tgt_len != sizeof(struct errhdr_t)) {
goto unimplemented;
}
- __put_user(errh->ee.ee_errno, &target_errh->ee.ee_errno);
+ __put_user(host_to_target_errno(errh->ee.ee_errno),
+ &target_errh->ee.ee_errno);
__put_user(errh->ee.ee_origin, &target_errh->ee.ee_origin);
__put_user(errh->ee.ee_type, &target_errh->ee.ee_type);
__put_user(errh->ee.ee_code, &target_errh->ee.ee_code);
@@ -2062,7 +2063,8 @@ static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
tgt_len != sizeof(struct errhdr6_t)) {
goto unimplemented;
}
- __put_user(errh->ee.ee_errno, &target_errh->ee.ee_errno);
+ __put_user(host_to_target_errno(errh->ee.ee_errno),
+ &target_errh->ee.ee_errno);
__put_user(errh->ee.ee_origin, &target_errh->ee.ee_origin);
__put_user(errh->ee.ee_type, &target_errh->ee.ee_type);
__put_user(errh->ee.ee_code, &target_errh->ee.ee_code);
--
2.53.0
^ permalink raw reply related [flat|nested] 8+ messages in thread