From ace8e9a5c436b95d8a73d4264da4c7903741aef7ac95ad3fe7e5d9a1ca207479 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Tue, 21 Aug 2012 12:29:30 +0000 Subject: [PATCH] - fix getdent in linux-user - fix statfs in linux-user - disable FIEMAP support in linux-user OBS-URL: https://build.opensuse.org/package/show/Virtualization/qemu?expand=0&rev=102 --- ...-linux-user-fix-emulation-of-getdent.patch | 61 +++++++++++++++++++ 0031-linux-user-fix-statfs.patch.patch | 48 +++++++++++++++ ...-linux-user-XXX-disable-fiemap.patch.patch | 26 ++++++++ qemu.changes | 7 +++ qemu.spec | 6 ++ 5 files changed, 148 insertions(+) create mode 100644 0030-linux-user-fix-emulation-of-getdent.patch create mode 100644 0031-linux-user-fix-statfs.patch.patch create mode 100644 0032-linux-user-XXX-disable-fiemap.patch.patch diff --git a/0030-linux-user-fix-emulation-of-getdent.patch b/0030-linux-user-fix-emulation-of-getdent.patch new file mode 100644 index 00000000..1045bf3d --- /dev/null +++ b/0030-linux-user-fix-emulation-of-getdent.patch @@ -0,0 +1,61 @@ +From b08f65c466f03820436df6143b1a256f81a5a98a Mon Sep 17 00:00:00 2001 +From: Dmitry V. Levin +Date: Mon, 20 Aug 2012 12:13:12 +0000 +Subject: [PATCH] linux-user: fix emulation of getdents + +In case when TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64, the last +byte of the target dirent structure (aka d_type byte) was never copied +from the host dirent structure, thus breaking everything that relies +on valid d_type value, e.g. glob(3). + +Signed-off-by: Dmitry V. Levin +Signed-off-by: Alexander Graf +--- + linux-user/syscall.c | 11 +++++------ + linux-user/syscall_defs.h | 8 ++++---- + 2 files changed, 9 insertions(+), 10 deletions(-) + +diff --git a/linux-user/syscall.c b/linux-user/syscall.c +index d19efb8..df4a538 100644 +--- a/linux-user/syscall.c ++++ b/linux-user/syscall.c +@@ -7161,15 +7161,14 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, + tde = target_dirp; + while (len > 0) { + reclen = de->d_reclen; +- treclen = reclen - (2 * (sizeof(long) - sizeof(abi_long))); ++ tnamelen = reclen - offsetof(struct linux_dirent, d_name); ++ assert(tnamelen >= 0); ++ treclen = tnamelen + offsetof(struct target_dirent, d_name); ++ assert(count1 + treclen <= count); + tde->d_reclen = tswap16(treclen); + tde->d_ino = tswapal(de->d_ino); + tde->d_off = tswapal(de->d_off); +- tnamelen = treclen - (2 * sizeof(abi_long) + 2); +- if (tnamelen > 256) +- tnamelen = 256; +- /* XXX: may not be correct */ +- pstrcpy(tde->d_name, tnamelen, de->d_name); ++ memcpy(tde->d_name, de->d_name, tnamelen); + de = (struct linux_dirent *)((char *)de + reclen); + len -= reclen; + tde = (struct target_dirent *)((char *)tde + treclen); +diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h +index 349229d..d618414 100644 +--- a/linux-user/syscall_defs.h ++++ b/linux-user/syscall_defs.h +@@ -255,10 +255,10 @@ struct kernel_statfs { + }; + + struct target_dirent { +- abi_long d_ino; +- abi_long d_off; +- unsigned short d_reclen; +- char d_name[256]; /* We must not include limits.h! */ ++ abi_long d_ino; ++ abi_long d_off; ++ unsigned short d_reclen; ++ char d_name[]; + }; + + struct target_dirent64 { diff --git a/0031-linux-user-fix-statfs.patch.patch b/0031-linux-user-fix-statfs.patch.patch new file mode 100644 index 00000000..360e8127 --- /dev/null +++ b/0031-linux-user-fix-statfs.patch.patch @@ -0,0 +1,48 @@ +From 496ac41ba22b2dcda7eb0a90690dc55ae86c7c50 Mon Sep 17 00:00:00 2001 +From: Alexander Graf +Date: Tue, 21 Aug 2012 11:16:06 +0200 +Subject: [PATCH] linux-user: fix statfs + +The statfs syscall should always memset(0) its full struct extent before +writing to it. Newer versions of the syscall use one of the reserved fields +for flags, which would otherwise get stale values from uncleaned memory. + +This fixes libarchive for me, which got confused about the return value of +pathconf("/", _PC_REC_XFER_ALIGN) otherwise, as it some times gave old pointers +as return value. + +Signed-off-by: Alexander Graf +--- + linux-user/syscall.c | 12 ++++++++++++ + 1 files changed, 12 insertions(+), 0 deletions(-) + +diff --git a/linux-user/syscall.c b/linux-user/syscall.c +index df4a538..60cf77f 100644 +--- a/linux-user/syscall.c ++++ b/linux-user/syscall.c +@@ -6667,6 +6667,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, + __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]); + __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]); + __put_user(stfs.f_namelen, &target_stfs->f_namelen); ++ __put_user(stfs.f_frsize, &target_stfs->f_frsize); ++ __put_user(0, &target_stfs->f_spare[0]); ++ __put_user(0, &target_stfs->f_spare[1]); ++ __put_user(0, &target_stfs->f_spare[2]); ++ __put_user(0, &target_stfs->f_spare[3]); ++ __put_user(0, &target_stfs->f_spare[4]); + unlock_user_struct(target_stfs, arg2, 1); + } + break; +@@ -6695,6 +6701,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, + __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]); + __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]); + __put_user(stfs.f_namelen, &target_stfs->f_namelen); ++ __put_user(stfs.f_frsize, &target_stfs->f_frsize); ++ __put_user(0, &target_stfs->f_spare[0]); ++ __put_user(0, &target_stfs->f_spare[1]); ++ __put_user(0, &target_stfs->f_spare[2]); ++ __put_user(0, &target_stfs->f_spare[3]); ++ __put_user(0, &target_stfs->f_spare[4]); + unlock_user_struct(target_stfs, arg3, 1); + } + break; diff --git a/0032-linux-user-XXX-disable-fiemap.patch.patch b/0032-linux-user-XXX-disable-fiemap.patch.patch new file mode 100644 index 00000000..187eff69 --- /dev/null +++ b/0032-linux-user-XXX-disable-fiemap.patch.patch @@ -0,0 +1,26 @@ +From cb9b53ee9c4277f5b61038b37c1a7ef827652b4a Mon Sep 17 00:00:00 2001 +From: Alexander Graf +Date: Tue, 21 Aug 2012 14:20:40 +0200 +Subject: [PATCH] linux-user: XXX disable fiemap + +agraf: fiemap breaks in libarchive. Disable it for now. +--- + linux-user/syscall.c | 5 +++++ + 1 files changed, 5 insertions(+), 0 deletions(-) + +diff --git a/linux-user/syscall.c b/linux-user/syscall.c +index 60cf77f..21856f0 100644 +--- a/linux-user/syscall.c ++++ b/linux-user/syscall.c +@@ -3252,6 +3252,11 @@ static abi_long do_ioctl_fs_ioc_fiemap(const IOCTLEntry *ie, uint8_t *buf_temp, + uint32_t outbufsz; + int free_fm = 0; + ++ if (1) { ++ /* XXX agraf: fiemap breaks for me */ ++ return -TARGET_EINVAL; ++ } ++ + assert(arg_type[0] == TYPE_PTR); + assert(ie->access == IOC_RW); + arg_type++; diff --git a/qemu.changes b/qemu.changes index 09b81f39..3ca33c94 100644 --- a/qemu.changes +++ b/qemu.changes @@ -1,3 +1,10 @@ +------------------------------------------------------------------- +Tue Aug 21 12:21:49 UTC 2012 - agraf@suse.com + +- fix getdent in linux-user +- fix statfs in linux-user +- disable FIEMAP support in linux-user + ------------------------------------------------------------------- Tue Aug 21 08:21:20 UTC 2012 - agraf@suse.com diff --git a/qemu.spec b/qemu.spec index f9778b26..0400c221 100644 --- a/qemu.spec +++ b/qemu.spec @@ -53,6 +53,9 @@ Patch0026: 0026-linux-user-lock-tb-flushing-too.pat.patch Patch0027: 0027-linux-user-Fake-proc-cpuinfo.patch.patch Patch0028: 0028-linux-user-implement-FS_IOC_GETFLAG.patch Patch0029: 0029-linux-user-implement-FS_IOC_SETFLAG.patch +Patch0030: 0030-linux-user-fix-emulation-of-getdent.patch +Patch0031: 0031-linux-user-fix-statfs.patch.patch +Patch0032: 0032-linux-user-XXX-disable-fiemap.patch.patch # this is to make lint happy Source300: rpmlintrc Source302: bridge.conf @@ -193,6 +196,9 @@ run cross-architecture builds. %patch0027 -p1 %patch0028 -p1 %patch0029 -p1 +%patch0030 -p1 +%patch0031 -p1 +%patch0032 -p1 %build # build QEMU