Re: [Qemu-devel] RFC: x86_64 Best way to fix 'cast to pointer from integer of different size' problems?
On Tue, 6 Nov 2007, Paul Brook wrote: If you're not careful you get double-copying. Once copying the struct from guest to host space, and then again when converting layout/endianess. Yes, it would be easy to do that by mistake. The approach that has been taken has been to use typed copy_*_user_() routines for the structs instead of using a seperate untyped copy_*_user() followed by a convert_() routine. The copy_*_user_() routines do the copy and convert in a single step. This will never be as fast as an optimized buffer copy, but it will also not be as slow as having seperate routines. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149
Re: [Qemu-devel] RFC: x86_64 Best way to fix 'cast to pointer from integer of different size' problems?
On Tue, 6 Nov 2007, Fabrice Bellard wrote: Paul Brook wrote: [...] Personally I like the locking interface as it allows a zero-copy implementation. However the kernel uses a copying interface, and my understanding is that other qemu maintainers also prefer the copying interface. At least I don't think it is critical performance wise, especially if the page flag checks are added ! Before you added the current zero copy interface, my plan was to use a zero copy interface just for big buffers such as the one for read/write. By the time you consider the different combinations of targets & hosts, most of the opportunities for zero copy are eliminated anyway. Byte ordering and structure packing amd content differences mean that we can't do zero-copy except in the rare circumstance that the host & target match is all of these respects. The read & write buffers would still benefit from zero copy, but nearly everything else has to be touched anyway. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149
Re: [Qemu-devel] Re: [PATCH] linux-user utimensat() syscall
On Sun, 23 Sep 2007, Thiemo Seufer wrote: Thayne Harbaugh wrote: This patch adds the utimensat syscall to linux-user. Doesn't build: gcc-3.4 -g -Wl,-T,/home/ths/qemu/qemu-work/ppc.ld -o qemu-arm main.o syscall.o mmap.o signal.o path.o osdep.o thunk.o elfload.o linuxload.o flatload.o nwfpe/fpa11.o nwfpe/fpa11_cpdo.o nwfpe/fpa11_cpdt.o nwfpe/fpa11_cprt.o nwfpe/fpopcode.o nwfpe/single_cpdo.o nwfpe/double_cpdo.o nwfpe/extended_cpdo.o arm-semi.o libqemu.a gdbstub.o -lm -lrt syscall.o: In function `do_syscall': /home/ths/qemu/qemu-work/linux-user/syscall.c:4665: undefined reference to `copy_from_user_timespec' /home/ths/qemu/qemu-work/linux-user/syscall.c:4665: undefined reference to `copy_from_user_timespec' It's looking for something that is in the EFAULT patch. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149
Re: [Qemu-devel] RFC: [0/11] EFAULT patch
On Wed, 19 Sep 2007, Paul Brook wrote: No. We're doing more than most 32-64 syscall thunks. To a first approximation the syscall thunks can bindly zero extend all values. In qemu we need to know whether something is a pointer or a value. Isn't that was the code in do_syscall() does? or am I looking at something in the wrong way? Kernel and userspace addresses are not interchangeable in the kernel. Any place that does so is probably a bug. I said co-exist, not interchangeable. My point was that the 32-on-64 code didn't do any explicit mapping of pointers passed to it other than the normal API. I'm having trouble determining how you would like for things to be. Could you maybe provide a small sample of how all of this should work, and then I can probably see what I'm not quite getting. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149
Re: [Qemu-devel] RFC: [0/11] EFAULT patch
On Wed, 19 Sep 2007, J. Mayer wrote: Then, the changes you've done, changing long arguments (which should be target_long to be correct, you can take a look at the last patch I sent on the list) to pointers, for example in function prototypes, are incorrect. I just went, and looked at the linux code again for 32 on 64 for x86_64 and powerpc. In both of these cases (and I suspect the others as well), the parameters which are passed via registers are 0 extended from 32 bits to 64 bit in the syscall entry asm code. This way, once the C code is called via the sys_call_table, everything is dealt with as 64 bits. This actually keeps the rest of the code simpler as the rest of the kernel doesn't have to be extending & truncating pointers everywhere else. On x86_64 and powerpc, it appears that both user (ie target) and kernel pointers co-exist and that the code that maps structures assume that the __get_user()/__put_user() and copy_*_user() routines can handle any special situation. The pointers passed into functions like cp_compat_stat() are 64-bits for both the structure located in the kernel, and the one located in user space. My understanding is that we want to do as the kernel does as much as possible. In light of this, wouldn't we want to be decreasing the use of target_long where pointers may be involved instead of increasing it? Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149
Re: [Qemu-devel] RFC: [0/11] EFAULT patch
On Wed, 19 Sep 2007, J. Mayer wrote: The idea is great but there seem to be a problem in those patches: you directly cast syscall arguments, which are (or should be) target_ulong to pointers in the host environment. You should to use the g2h / h2g macros to get the pointer in the host memory from the offset in the target address space. I was explicitly told to _not_ use these in this code. Offset in the target address space can not be assumed to be the same size as an address in the host address space, And in fact, they definitely are not the same in certain cobinations. thus can never be casted directly to host pointer. At some point, we have to convert things from target_long to a host pointer. If we can agree on what that right mechanism it to do this, I'd be glad to use it. So far, everything I've seen involved some form of type casting. This used to be handled by the lock_user functions and should be handled in your patch too... It was handled by g2h() which was just a typecast hidden behind the macro. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149
[Qemu-devel] RFC: [11/11] EFAULT patch
Last, but not least, this part contains the changes to the function that read and write iovec structures. This part will require one more pass to eliminate the inner calls to the old API. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149Index: qemu/linux-user/syscall.c === --- qemu.orig/linux-user/syscall.c 2007-09-16 16:03:46.0 -0400 +++ qemu/linux-user/syscall.c 2007-09-16 16:06:36.0 -0400 @@ -855,7 +855,7 @@ return ret; } -static void lock_iovec(struct iovec *vec, target_ulong target_addr, +static long copy_from_iovec(struct iovec *vec, target_ulong target_addr, int count, int copy) { struct target_iovec *target_vec; @@ -863,15 +863,18 @@ int i; target_vec = lock_user(target_addr, count * sizeof(struct target_iovec), 1); +if( !access_ok(VERIFY_READ, target_vec, count * sizeof(struct target_iovec)) ) return -1; for(i = 0;i < count; i++) { base = tswapl(target_vec[i].iov_base); vec[i].iov_len = tswapl(target_vec[i].iov_len); vec[i].iov_base = lock_user(base, vec[i].iov_len, copy); } unlock_user (target_vec, target_addr, 0); + +return 0; } -static void unlock_iovec(struct iovec *vec, target_ulong target_addr, +static long copy_to_iovec(struct iovec *vec, target_ulong target_addr, int count, int copy) { struct target_iovec *target_vec; @@ -879,11 +882,14 @@ int i; target_vec = lock_user(target_addr, count * sizeof(struct target_iovec), 1); +if( !access_ok(VERIFY_WRITE, target_vec, count * sizeof(struct target_iovec)) ) return -1; for(i = 0;i < count; i++) { base = tswapl(target_vec[i].iov_base); unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0); } unlock_user (target_vec, target_addr, 0); + +return 0; } static long do_socket(int domain, int type, int protocol) @@ -959,7 +965,7 @@ count = tswapl(msgp->msg_iovlen); vec = alloca(count * sizeof(struct iovec)); target_vec = tswapl(msgp->msg_iov); -lock_iovec(vec, target_vec, count, send); +if( copy_from_iovec(vec, target_vec, count, send) ) return -EFAULT; msg.msg_iovlen = count; msg.msg_iov = vec; @@ -971,7 +977,7 @@ if (!is_error(ret)) host_to_target_cmsg(msgp, &msg); } -unlock_iovec(vec, target_vec, count, !send); +if( copy_to_iovec(vec, target_vec, count, !send) ) return -EFAULT; return ret; } @@ -3913,9 +3919,9 @@ struct iovec *vec; vec = alloca(count * sizeof(struct iovec)); -lock_iovec(vec, arg2, count, 0); +if( copy_from_iovec(vec, arg2, count, 0) ) return -EFAULT; ret = get_errno(readv(arg1, vec, count)); -unlock_iovec(vec, arg2, count, 1); +if( copy_to_iovec(vec, arg2, count, 1) ) return -EFAULT; } break; case TARGET_NR_writev: @@ -3924,9 +3930,9 @@ struct iovec *vec; vec = alloca(count * sizeof(struct iovec)); -lock_iovec(vec, arg2, count, 1); +if( copy_from_iovec(vec, arg2, count, 1) ) return -EFAULT; ret = get_errno(writev(arg1, vec, count)); -unlock_iovec(vec, arg2, count, 0); +if( copy_to_iovec(vec, arg2, count, 0) ) return -EFAULT; } break; case TARGET_NR_getsid:
[Qemu-devel] RFC: [10/11] EFAULT patch
This part contains the rest of the updates to do_syscall() that contain the changes to the new API for several systcalls, including utime(), sigaction(), rt_sigaction(), rt_sigpending(), sigsuspend(), rt_sigtimedwait(), rt_sigqueueinfo(), stat() and stat64(). Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149Index: qemu/linux-user/syscall.c === --- qemu.orig/linux-user/syscall.c 2007-09-17 01:09:25.0 -0400 +++ qemu/linux-user/syscall.c 2007-09-17 01:12:47.0 -0400 @@ -2687,12 +2687,11 @@ case TARGET_NR_utime: { struct utimbuf tbuf, *host_tbuf; -struct target_utimbuf *target_tbuf; +struct target_utimbuf *target_tbuf = (struct target_utimbuf *)arg2; if (arg2) { -lock_user_struct(target_tbuf, arg2, 1); + if( !access_ok(VERIFY_READ,target_tbuf,sizeof(struct target_utimbuf)) ) return -EFAULT; tbuf.actime = tswapl(target_tbuf->actime); tbuf.modtime = tswapl(target_tbuf->modtime); -unlock_user_struct(target_tbuf, arg2, 0); host_tbuf = &tbuf; } else { host_tbuf = NULL; @@ -2878,37 +2877,35 @@ case TARGET_NR_sigaction: { #if !defined(TARGET_MIPS) -struct target_old_sigaction *old_act; +struct target_old_sigaction *old_act = (struct target_old_sigaction *)arg2; struct target_sigaction act, oact, *pact; if (arg2) { -lock_user_struct(old_act, arg2, 1); + if( !access_ok(VERIFY_READ,old_act,sizeof(*old_act)) ) return -EFAULT; act._sa_handler = old_act->_sa_handler; target_siginitset(&act.sa_mask, old_act->sa_mask); act.sa_flags = old_act->sa_flags; act.sa_restorer = old_act->sa_restorer; -unlock_user_struct(old_act, arg2, 0); pact = &act; } else { pact = NULL; } ret = get_errno(do_sigaction(arg1, pact, &oact)); if (!is_error(ret) && arg3) { -lock_user_struct(old_act, arg3, 0); +old_act = (struct target_old_sigaction *)arg3; + if( !access_ok(VERIFY_WRITE,old_act,sizeof(*old_act)) ) return -EFAULT; old_act->_sa_handler = oact._sa_handler; old_act->sa_mask = oact.sa_mask.sig[0]; old_act->sa_flags = oact.sa_flags; old_act->sa_restorer = oact.sa_restorer; -unlock_user_struct(old_act, arg3, 1); } #else struct target_sigaction act, oact, *pact, *old_act; if (arg2) { - lock_user_struct(old_act, arg2, 1); + if( !access_ok(VERIFY_READ,old_act,sizeof(*old_act)) ) return -EFAULT; act._sa_handler = old_act->_sa_handler; target_siginitset(&act.sa_mask, old_act->sa_mask.sig[0]); act.sa_flags = old_act->sa_flags; - unlock_user_struct(old_act, arg2, 0); pact = &act; } else { pact = NULL; @@ -2917,14 +2914,14 @@ ret = get_errno(do_sigaction(arg1, pact, &oact)); if (!is_error(ret) && arg3) { - lock_user_struct(old_act, arg3, 0); +old_act = (struct target_old_sigaction *)arg3; + if( !access_ok(VERIFY_WRITE,old_act,sizeof(*old_act)) ) return -EFAULT; old_act->_sa_handler = oact._sa_handler; old_act->sa_flags = oact.sa_flags; old_act->sa_mask.sig[0] = oact.sa_mask.sig[0]; old_act->sa_mask.sig[1] = 0; old_act->sa_mask.sig[2] = 0; old_act->sa_mask.sig[3] = 0; - unlock_user_struct(old_act, arg3, 1); } #endif } @@ -2932,22 +2929,20 @@ #endif case TARGET_NR_rt_sigaction: { -struct target_sigaction *act; -struct target_sigaction *oact; +struct target_sigaction *act = (struct target_sigaction *)arg2; +struct target_sigaction *oact = (struct target_sigaction *)arg3; -if (arg2) -lock_user_struct(act, arg2, 1); +if (arg2) { + if( !access_ok(VERIFY_READ,act,sizeof(*act)) ) return -EFAULT; +} else act = NULL; -if (arg3) -lock_user_struct(oact, arg3, 0); +if (arg3) { + if( !access_ok(VERIFY_WRITE,oact,sizeof(*oact)) ) return -EF
[Qemu-devel] RFC: [9/11] EFAULT patch
Thsi part updates stat(64)fs and fstat(64)fs implementations to use the new APIs in a more optimal manner. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149Index: qemu/linux-user/syscall.c === --- qemu.orig/linux-user/syscall.c 2007-09-17 01:06:41.0 -0400 +++ qemu/linux-user/syscall.c 2007-09-17 01:09:25.0 -0400 @@ -2462,7 +2462,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, long arg4, long arg5, long arg6) { -long ret; +long ret = 0; struct stat st; struct statfs stfs; void *p; @@ -3352,25 +3352,25 @@ #endif case TARGET_NR_statfs: p = lock_user_string(arg1); +if( !access_ok(VERIFY_READ,p,1) ) return -EFAULT; ret = get_errno(statfs(path(p), &stfs)); unlock_user(p, arg1, 0); convert_statfs: if (!is_error(ret)) { -struct target_statfs *target_stfs; +struct target_statfs *target_stfs = (struct target_statfs *)arg2;; -lock_user_struct(target_stfs, arg2, 0); -/* ??? put_user is probably wrong. */ -put_user(stfs.f_type, &target_stfs->f_type); -put_user(stfs.f_bsize, &target_stfs->f_bsize); -put_user(stfs.f_blocks, &target_stfs->f_blocks); -put_user(stfs.f_bfree, &target_stfs->f_bfree); -put_user(stfs.f_bavail, &target_stfs->f_bavail); -put_user(stfs.f_files, &target_stfs->f_files); -put_user(stfs.f_ffree, &target_stfs->f_ffree); -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); -unlock_user_struct(target_stfs, arg2, 1); +if( !access_ok(VERIFY_WRITE,target_stfs,sizeof(struct target_statfs)) ) return -EFAULT; +/* use __put_user since we just validated the entire bufffer. */ +__put_user(stfs.f_type, &target_stfs->f_type); +__put_user(stfs.f_bsize, &target_stfs->f_bsize); +__put_user(stfs.f_blocks, &target_stfs->f_blocks); +__put_user(stfs.f_bfree, &target_stfs->f_bfree); +__put_user(stfs.f_bavail, &target_stfs->f_bavail); +__put_user(stfs.f_files, &target_stfs->f_files); +__put_user(stfs.f_ffree, &target_stfs->f_ffree); +__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); } break; case TARGET_NR_fstatfs: @@ -3379,25 +3379,25 @@ #ifdef TARGET_NR_statfs64 case TARGET_NR_statfs64: p = lock_user_string(arg1); +if( !access_ok(VERIFY_READ,p,1) ) return -EFAULT; ret = get_errno(statfs(path(p), &stfs)); unlock_user(p, arg1, 0); convert_statfs64: if (!is_error(ret)) { -struct target_statfs64 *target_stfs; +struct target_statfs64 *target_stfs = (struct target_statfs64 *)arg3; -lock_user_struct(target_stfs, arg3, 0); -/* ??? put_user is probably wrong. */ -put_user(stfs.f_type, &target_stfs->f_type); -put_user(stfs.f_bsize, &target_stfs->f_bsize); -put_user(stfs.f_blocks, &target_stfs->f_blocks); -put_user(stfs.f_bfree, &target_stfs->f_bfree); -put_user(stfs.f_bavail, &target_stfs->f_bavail); -put_user(stfs.f_files, &target_stfs->f_files); -put_user(stfs.f_ffree, &target_stfs->f_ffree); -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); -unlock_user_struct(target_stfs, arg3, 0); +if( !access_ok(VERIFY_WRITE,target_stfs,sizeof(struct target_statfs64)) ) return -EFAULT; +/* use __put_user since we just validated the entire bufffer. */ +__put_user(stfs.f_type, &target_stfs->f_type); +__put_user(stfs.f_bsize, &target_stfs->f_bsize); +__put_user(stfs.f_blocks, &target_stfs->f_blocks); +__put_user(stfs.f_bfree, &target_stfs->f_bfree); +__put_user(stfs.f_bavail, &target_stfs->f_bavail); +__put_user(stfs.f_files, &target_stfs->f_files); +__put_user(stfs.f_ffree, &target_stfs->f_ffree); +__put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]); +
[Qemu-devel] RFC: [8/11] EFAULT patch
This part updates the functions that read and write struct timespec, and adjusts the places in do_syscall() that use it. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149Index: qemu/linux-user/syscall.c === --- qemu.orig/linux-user/syscall.c 2007-09-16 15:56:47.0 -0400 +++ qemu/linux-user/syscall.c 2007-09-16 15:56:49.0 -0400 @@ -2436,26 +2436,24 @@ } #endif -static inline void target_to_host_timespec(struct timespec *host_ts, - target_ulong target_addr) +static inline long copy_from_user_timespec(struct timespec *host_ts, + struct target_timespec *target_ts) { -struct target_timespec *target_ts; - -lock_user_struct(target_ts, target_addr, 1); +if( copy_from_user(host_ts,target_ts,sizeof(*target_ts)) ) return -1; host_ts->tv_sec = tswapl(target_ts->tv_sec); host_ts->tv_nsec = tswapl(target_ts->tv_nsec); -unlock_user_struct(target_ts, target_addr, 0); + +return 0; } -static inline void host_to_target_timespec(target_ulong target_addr, +static inline long copy_to_user_timespec(struct target_timespec *target_ts, struct timespec *host_ts) { -struct target_timespec *target_ts; - -lock_user_struct(target_ts, target_addr, 0); +if( copy_to_user(target_ts, host_ts, sizeof(*target_ts)) ) return -1; target_ts->tv_sec = tswapl(host_ts->tv_sec); target_ts->tv_nsec = tswapl(host_ts->tv_nsec); -unlock_user_struct(target_ts, target_addr, 1); + +return 0; } long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, @@ -3102,7 +3100,7 @@ unlock_user(p, arg1, 0); if (arg3) { puts = &uts; -target_to_host_timespec(puts, arg3); +copy_from_user_timespec(puts, (struct target_timespec *)arg3); } else { puts = NULL; } @@ -3997,17 +3995,17 @@ struct timespec ts; ret = get_errno(sched_rr_get_interval(arg1, &ts)); if (!is_error(ret)) { -host_to_target_timespec(arg2, &ts); +if( copy_to_user_timespec((struct target_timespec *)arg2, &ts) ) return -EFAULT; } } break; case TARGET_NR_nanosleep: { struct timespec req, rem; -target_to_host_timespec(&req, arg1); +if( copy_from_user_timespec(&req, (struct target_timespec *)arg1) ) return -EFAULT; ret = get_errno(nanosleep(&req, &rem)); if (is_error(ret) && arg2) { -host_to_target_timespec(arg2, &rem); +if( copy_to_user_timespec((struct target_timespec *)arg2, &rem) ) return -EFAULT; } } break; @@ -4615,7 +4613,7 @@ struct timespec ts; ret = get_errno(clock_gettime(arg1, &ts)); if (!is_error(ret)) { -host_to_target_timespec(arg2, &ts); +if( copy_to_user_timespec((struct target_timespec *)arg2, &ts) ) return -EFAULT; } break; } @@ -4626,7 +4624,7 @@ struct timespec ts; ret = get_errno(clock_getres(arg1, &ts)); if (!is_error(ret)) { -host_to_target_timespec(arg2, &ts); +if( copy_to_user_timespec((struct target_timespec *)arg2, &ts) ) return -EFAULT; } break; }
[Qemu-devel] RFC: [7/11] EFAULT patch
This part updates do_fcntl() to use the new kernel-like APIs. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149Index: qemu/linux-user/syscall.c === --- qemu.orig/linux-user/syscall.c 2007-09-17 01:02:17.0 -0400 +++ qemu/linux-user/syscall.c 2007-09-17 01:06:30.0 -0400 @@ -2242,73 +2242,69 @@ static long do_fcntl(int fd, int cmd, target_ulong arg) { struct flock fl; -struct target_flock *target_fl; +struct target_flock *target_fl = (struct target_flock *)arg; struct flock64 fl64; -struct target_flock64 *target_fl64; +struct target_flock64 *target_fl64 = (struct target_flock64 *)arg; long ret; switch(cmd) { case TARGET_F_GETLK: -lock_user_struct(target_fl, arg, 1); -fl.l_type = tswap16(target_fl->l_type); -fl.l_whence = tswap16(target_fl->l_whence); -fl.l_start = tswapl(target_fl->l_start); -fl.l_len = tswapl(target_fl->l_len); -fl.l_pid = tswapl(target_fl->l_pid); -unlock_user_struct(target_fl, arg, 0); +if( !access_ok(VERIFY_READ,target_fl,sizeof(struct target_flock)) ) return -EFAULT; +__get_user(fl.l_type, &target_fl->l_type); +__get_user(fl.l_whence, &target_fl->l_whence); +__get_user(fl.l_start, &target_fl->l_start); +__get_user(fl.l_len, &target_fl->l_len); +__get_user(fl.l_pid, &target_fl->l_pid); ret = fcntl(fd, cmd, &fl); if (ret == 0) { -lock_user_struct(target_fl, arg, 0); -target_fl->l_type = tswap16(fl.l_type); -target_fl->l_whence = tswap16(fl.l_whence); -target_fl->l_start = tswapl(fl.l_start); -target_fl->l_len = tswapl(fl.l_len); -target_fl->l_pid = tswapl(fl.l_pid); -unlock_user_struct(target_fl, arg, 1); +if( !access_ok(VERIFY_WRITE,target_fl,sizeof(struct target_flock)) ) return -EFAULT; +__put_user(fl.l_type, &target_fl->l_type); +__put_user(fl.l_whence, &target_fl->l_whence); +__put_user(fl.l_start, &target_fl->l_start); +__put_user(fl.l_len, &target_fl->l_len); +__put_user(fl.l_pid, &target_fl->l_pid); } break; case TARGET_F_SETLK: case TARGET_F_SETLKW: -lock_user_struct(target_fl, arg, 1); -fl.l_type = tswap16(target_fl->l_type); -fl.l_whence = tswap16(target_fl->l_whence); -fl.l_start = tswapl(target_fl->l_start); -fl.l_len = tswapl(target_fl->l_len); -fl.l_pid = tswapl(target_fl->l_pid); -unlock_user_struct(target_fl, arg, 0); +if( !access_ok(VERIFY_READ,target_fl,sizeof(struct target_flock)) ) return -EFAULT; +__get_user(fl.l_type, &target_fl->l_type); +__get_user(fl.l_whence, &target_fl->l_whence); +__get_user(fl.l_start, &target_fl->l_start); +__get_user(fl.l_len, &target_fl->l_len); ret = fcntl(fd, cmd, &fl); break; case TARGET_F_GETLK64: -lock_user_struct(target_fl64, arg, 1); -fl64.l_type = tswap16(target_fl64->l_type) >> 1; -fl64.l_whence = tswap16(target_fl64->l_whence); -fl64.l_start = tswapl(target_fl64->l_start); -fl64.l_len = tswapl(target_fl64->l_len); -fl64.l_pid = tswap16(target_fl64->l_pid); -unlock_user_struct(target_fl64, arg, 0); +if( !access_ok(VERIFY_READ,target_fl64,sizeof(struct target_flock64)) ) return -EFAULT; +__get_user(fl64.l_type, &target_fl64->l_type); +fl64.l_type >>= 1; +__get_user(fl64.l_whence, &target_fl64->l_whence); +__get_user(fl64.l_start, &target_fl64->l_start); +__get_user(fl64.l_len, &target_fl64->l_len); +__get_user(fl64.l_pid, &target_fl64->l_pid); ret = fcntl(fd, cmd >> 1, &fl64); if (ret == 0) { -lock_user_struct(target_fl64, arg, 0); -target_fl64->l_type = tswap16(fl64.l_type) >> 1; -target_fl64->l_whence = tswap16(fl64.l_whence); -target_fl64->l_start = tswapl(fl64.l_start); -target_fl64->l_len = tswapl(fl64.l_len); -target_fl64->l_pid = tswapl(fl64.l_pid); -unlock_user_struct(target_fl64, arg, 1); +if( !access_ok(VERIFY_WRITE,target_fl64,sizeof(struct target_flock64)) ) return -EFAULT; +__put_user(fl64.l_type, &target_fl64->l_type); +target_fl64->l_type >>= 1; +__put_user(fl64.l_whence, &target_fl64->l_whence); +__put_user(fl64.l_start, &target_fl64->l_start); +__put_user(fl64.l_len, &target_fl64->l_len);
[Qemu-devel] RFC: [6/11] EFAULT patch
This part contains the changes to write_ldt() to use the newer APIs. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149Index: qemu/linux-user/syscall.c === --- qemu.orig/linux-user/syscall.c 2007-09-17 01:37:05.0 -0400 +++ qemu/linux-user/syscall.c 2007-09-17 01:37:26.0 -0400 @@ -2040,22 +2040,21 @@ /* XXX: add locking support */ static int write_ldt(CPUX86State *env, - target_ulong ptr, unsigned long bytecount, int oldmode) + struct target_modify_ldt_ldt_s *target_ldt_info, unsigned long bytecount, int oldmode) { +long ret = 0; struct target_modify_ldt_ldt_s ldt_info; -struct target_modify_ldt_ldt_s *target_ldt_info; int seg_32bit, contents, read_exec_only, limit_in_pages; int seg_not_present, useable; uint32_t *lp, entry_1, entry_2; if (bytecount != sizeof(ldt_info)) return -EINVAL; -lock_user_struct(target_ldt_info, ptr, 1); +if( !access_ok(&target_ldt_info,target_ldt_info,sizeof(struct target_modify_ldt_ldt_s)) ) return -EFAULT; ldt_info.entry_number = tswap32(target_ldt_info->entry_number); ldt_info.base_addr = tswapl(target_ldt_info->base_addr); ldt_info.limit = tswap32(target_ldt_info->limit); ldt_info.flags = tswap32(target_ldt_info->flags); -unlock_user_struct(target_ldt_info, ptr, 0); if (ldt_info.entry_number >= TARGET_LDT_ENTRIES) return -EINVAL; @@ -2130,10 +2129,10 @@ ret = read_ldt(ptr, bytecount); break; case 1: -ret = write_ldt(env, ptr, bytecount, 1); +ret = write_ldt(env, (struct target_modify_ldt_ldt_s *)ptr, bytecount, 1); break; case 0x11: -ret = write_ldt(env, ptr, bytecount, 0); +ret = write_ldt(env, (struct target_modify_ldt_ldt_s *)ptr, bytecount, 0); break; } return ret;
[Qemu-devel] RFC: [5/11] EFAULT patch
This part contains the changes to the message queue IPC syscalls. The functions for reading and writing the msqid_ds structure have been updated to use the kernel-like APIs. Also, additional checking has been added to the implementations of msgsnd() and msgrecv(). Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149Index: qemu/linux-user/syscall.c === --- qemu.orig/linux-user/syscall.c 2007-09-16 15:56:37.0 -0400 +++ qemu/linux-user/syscall.c 2007-09-16 15:56:42.0 -0400 @@ -1468,53 +1468,59 @@ target_ulong __unused5; }; -static inline void target_to_host_msqid_ds(struct msqid_ds *host_md, - target_ulong target_addr) +static inline long copy_from_user_msqid_ds(struct msqid_ds *host_md, + struct target_msqid_ds *target_md) { -struct target_msqid_ds *target_md; +/* access has already been checked */ +copy_from_user_ipc_perm(&(host_md->msg_perm),&(target_md->msg_perm)); +__get_user(host_md->msg_stime, &target_md->msg_stime); +__get_user(host_md->msg_rtime, &target_md->msg_rtime); +__get_user(host_md->msg_ctime, &target_md->msg_ctime); +__get_user(host_md->__msg_cbytes, &target_md->__msg_cbytes); +__get_user(host_md->msg_qnum, &target_md->msg_qnum); +__get_user(host_md->msg_qbytes, &target_md->msg_qbytes); +__get_user(host_md->msg_lspid, &target_md->msg_lspid); +__get_user(host_md->msg_lrpid, &target_md->msg_lrpid); -lock_user_struct(target_md, target_addr, 1); -copy_from_user_ipc_perm(&(host_md->msg_perm),target_addr); -host_md->msg_stime = tswapl(target_md->msg_stime); -host_md->msg_rtime = tswapl(target_md->msg_rtime); -host_md->msg_ctime = tswapl(target_md->msg_ctime); -host_md->__msg_cbytes = tswapl(target_md->__msg_cbytes); -host_md->msg_qnum = tswapl(target_md->msg_qnum); -host_md->msg_qbytes = tswapl(target_md->msg_qbytes); -host_md->msg_lspid = tswapl(target_md->msg_lspid); -host_md->msg_lrpid = tswapl(target_md->msg_lrpid); -unlock_user_struct(target_md, target_addr, 0); +return 0; } -static inline void host_to_target_msqid_ds(target_ulong target_addr, +static inline long copy_to_usermsqid_ds(struct target_msqid_ds *target_md, struct msqid_ds *host_md) { -struct target_msqid_ds *target_md; +/* access has already been checked */ +copy_to_user_ipc_perm(&(target_md->msg_perm),&(host_md->msg_perm)); +__put_user(host_md->msg_stime, &target_md->msg_stime); +__put_user(host_md->msg_rtime, &target_md->msg_rtime); +__put_user(host_md->msg_ctime, &target_md->msg_ctime); +__put_user(host_md->__msg_cbytes, &target_md->__msg_cbytes); +__put_user(host_md->msg_qnum, &target_md->msg_qnum); +__put_user(host_md->msg_qbytes, &target_md->msg_qbytes); +__put_user(host_md->msg_lspid, &target_md->msg_lspid); +__put_user(host_md->msg_lrpid, &target_md->msg_lrpid); -lock_user_struct(target_md, target_addr, 0); -copy_to_user_ipc_perm(target_addr,&(host_md->msg_perm)); -target_md->msg_stime = tswapl(host_md->msg_stime); -target_md->msg_rtime = tswapl(host_md->msg_rtime); -target_md->msg_ctime = tswapl(host_md->msg_ctime); -target_md->__msg_cbytes = tswapl(host_md->__msg_cbytes); -target_md->msg_qnum = tswapl(host_md->msg_qnum); -target_md->msg_qbytes = tswapl(host_md->msg_qbytes); -target_md->msg_lspid = tswapl(host_md->msg_lspid); -target_md->msg_lrpid = tswapl(host_md->msg_lrpid); -unlock_user_struct(target_md, target_addr, 1); +return 0; } static inline long do_msgctl(long first, long second, long ptr) { struct msqid_ds dsarg; +struct target_msqid_ds *target_ds = (struct target_msqid_ds *)ptr; int cmd = second&0xff; long ret = 0; switch( cmd ) { case IPC_STAT: + if( copy_from_user(&dsarg,target_ds,sizeof(struct msqid_ds)) ) return -EFAULT; +copy_from_user_msqid_ds(&dsarg,target_ds); +ret = get_errno(msgctl(first, cmd, &dsarg)); +if( copy_to_usermsqid_ds(target_ds,&dsarg) ) return -EFAULT; + break; case IPC_SET: -target_to_host_msqid_ds(&dsarg,ptr); + if( copy_from_user(&dsarg,target_ds,sizeof(struct msqid_ds)) ) return -EFAULT; +copy_from_user_msqid_ds(&dsarg,target_ds); ret = get_errno(msgctl(first, cmd, &dsarg)); -host_to_target_msqid_ds(ptr,&dsarg); +if( copy_to_usermsqid_ds(target_ds,&dsarg) ) return -EFAULT; + break; default: ret = get_errno(msgctl(first, cmd, &dsarg)); } @@ -1522,41 +1528,45 @
[Qemu-devel] RFC: [4/11] EFAULT patch
This part contains the updates for the semaphore IPC syscalls. In addition to the changes to use the new APIs, there are also fixes for some of the semop() and semctl() actions. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149Index: qemu/linux-user/syscall.c === --- qemu.orig/linux-user/syscall.c 2007-09-16 15:56:36.0 -0400 +++ qemu/linux-user/syscall.c 2007-09-16 15:56:37.0 -0400 @@ -1289,64 +1289,50 @@ target_ulong __unused4; }; -static inline void target_to_host_ipc_perm(struct ipc_perm *host_ip, - target_ulong target_addr) +static inline void copy_from_user_ipc_perm(struct ipc_perm *host_ip, + struct target_ipc_perm *target_ip) { -struct target_ipc_perm *target_ip; -struct target_semid_ds *target_sd; - -lock_user_struct(target_sd, target_addr, 1); -target_ip=&(target_sd->sem_perm); -host_ip->__key = tswapl(target_ip->__key); -host_ip->uid = tswapl(target_ip->uid); -host_ip->gid = tswapl(target_ip->gid); -host_ip->cuid = tswapl(target_ip->cuid); -host_ip->cgid = tswapl(target_ip->cgid); -host_ip->mode = tswapl(target_ip->mode); -unlock_user_struct(target_sd, target_addr, 0); +/* access has already been checked */ +__get_user(host_ip->__key, &target_ip->__key); +__get_user(host_ip->uid, &target_ip->uid); +__get_user(host_ip->gid, &target_ip->gid); +__get_user(host_ip->cuid, &target_ip->cuid); +__get_user(host_ip->cgid, &target_ip->cgid); +__get_user(host_ip->mode, &target_ip->mode); +__get_user(host_ip->__seq, &target_ip->__seq); } -static inline void host_to_target_ipc_perm(target_ulong target_addr, +static inline void copy_to_user_ipc_perm(struct target_ipc_perm *target_ip, struct ipc_perm *host_ip) { -struct target_ipc_perm *target_ip; -struct target_semid_ds *target_sd; - -lock_user_struct(target_sd, target_addr, 0); -target_ip = &(target_sd->sem_perm); -target_ip->__key = tswapl(host_ip->__key); -target_ip->uid = tswapl(host_ip->uid); -target_ip->gid = tswapl(host_ip->gid); -target_ip->cuid = tswapl(host_ip->cuid); -target_ip->cgid = tswapl(host_ip->cgid); -target_ip->mode = tswapl(host_ip->mode); -unlock_user_struct(target_sd, target_addr, 1); -} - -static inline void target_to_host_semid_ds(struct semid_ds *host_sd, - target_ulong target_addr) -{ -struct target_semid_ds *target_sd; - -lock_user_struct(target_sd, target_addr, 1); -target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr); -host_sd->sem_nsems = tswapl(target_sd->sem_nsems); -host_sd->sem_otime = tswapl(target_sd->sem_otime); -host_sd->sem_ctime = tswapl(target_sd->sem_ctime); -unlock_user_struct(target_sd, target_addr, 0); +/* access has already been checked */ +__put_user(host_ip->__key, &target_ip->__key); +__put_user(host_ip->uid, &target_ip->uid); +__put_user(host_ip->gid, &target_ip->gid); +__put_user(host_ip->cuid, &target_ip->cuid); +__put_user(host_ip->cgid, &target_ip->cgid); +__put_user(host_ip->mode, &target_ip->mode); +__put_user(host_ip->__seq, &target_ip->__seq); +} + +static inline void copy_from_user_semid_ds(struct semid_ds *host_sd, + struct target_semid_ds *target_sd) +{ +/* access has already been checked */ +copy_from_user_ipc_perm(&(host_sd->sem_perm),&(target_sd->sem_perm)); +__get_user(host_sd->sem_nsems, &target_sd->sem_nsems); +__get_user(host_sd->sem_otime, &target_sd->sem_otime); +__get_user(host_sd->sem_ctime, &target_sd->sem_ctime); } -static inline void host_to_target_semid_ds(target_ulong target_addr, +static inline void copy_to_user_semid_ds(struct target_semid_ds *target_sd, struct semid_ds *host_sd) { -struct target_semid_ds *target_sd; - -lock_user_struct(target_sd, target_addr, 0); -host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm)); -target_sd->sem_nsems = tswapl(host_sd->sem_nsems); -target_sd->sem_otime = tswapl(host_sd->sem_otime); -target_sd->sem_ctime = tswapl(host_sd->sem_ctime); -unlock_user_struct(target_sd, target_addr, 1); +/* access has already been checked */ +copy_to_user_ipc_perm(&(target_sd->sem_perm),&(host_sd->sem_perm)); +__put_user(host_sd->sem_nsems, &target_sd->sem_nsems); +__put_user(host_sd->sem_otime, &target_sd->sem_otime); +__put_user(host_sd->sem_ctime, &target_sd->sem_ctime); } union se
[Qemu-devel] RFC: [3/11] EFAULT patch
This part contains the changes to teh socket interfaces. This includes updates to the functions for reading and writing struct sockaddr, as well as updates and some fixes to do_setsockopt() and do_getsockopt(). The implementations of bind() connect(), accept(), getpeername() and getsockname() have adjustments to use the newer kernel-like apis. the same is true for the functions that implement send(), sendto(), recv() and recvfrom(). Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149Index: qemu/linux-user/syscall.c === --- qemu.orig/linux-user/syscall.c 2007-09-17 00:55:34.0 -0400 +++ qemu/linux-user/syscall.c 2007-09-17 01:00:36.0 -0400 @@ -527,28 +527,24 @@ return ret; } -static inline void target_to_host_sockaddr(struct sockaddr *addr, - target_ulong target_addr, +static inline long copy_from_user_sockaddr(struct sockaddr *addr, + struct target_sockaddr * target_saddr, socklen_t len) { -struct target_sockaddr *target_saddr; +if( copy_from_user(addr,target_saddr,len) ) return -1; +__get_user(addr->sa_family, &target_saddr->sa_family); -target_saddr = lock_user(target_addr, len, 1); -memcpy(addr, target_saddr, len); -addr->sa_family = tswap16(target_saddr->sa_family); -unlock_user(target_saddr, target_addr, 0); +return 0; } -static inline void host_to_target_sockaddr(target_ulong target_addr, +static inline long copy_to_user_sockaddr(struct target_sockaddr *target_saddr, struct sockaddr *addr, socklen_t len) { -struct target_sockaddr *target_saddr; +if( copy_to_user(target_saddr,addr,len) ) return -1; +__put_user(addr->sa_family, &target_saddr->sa_family); -target_saddr = lock_user(target_addr, len, 0); -memcpy(target_saddr, addr, len); -target_saddr->sa_family = tswap16(addr->sa_family); -unlock_user(target_saddr, target_addr, len); +return 0; } /* ??? Should this also swap msgh->name? */ @@ -651,6 +647,8 @@ if (optlen < sizeof(uint32_t)) return -EINVAL; + if( !access_ok(VERIFY_READ, optval, optlen) ) +return -EFAULT; val = tget32(optval); ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val))); break; @@ -672,6 +670,8 @@ case IP_MULTICAST_TTL: case IP_MULTICAST_LOOP: val = 0; + if( !access_ok(VERIFY_READ, optval, optlen) ) +return -EFAULT; if (optlen >= sizeof(uint32_t)) { val = tget32(optval); } else if (optlen >= 1) { @@ -680,7 +680,7 @@ ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val))); break; default: -goto unimplemented; +goto unimplemented; } break; case TARGET_SOL_SOCKET: @@ -746,8 +746,11 @@ default: goto unimplemented; } - if (optlen < sizeof(uint32_t)) - return -EINVAL; +if (optlen < sizeof(uint32_t)) + return -EINVAL; +if( !access_ok(VERIFY_READ, optval, optlen) ) + return -EFAULT; + val = tget32(optval); ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, &val, sizeof(val))); @@ -755,13 +758,13 @@ default: unimplemented: gemu_log("Unsupported setsockopt level=%d optname=%d \n", level, optname); -ret = -ENOSYS; +ret = -ENOPROTOOPT; } return ret; } static long do_getsockopt(int sockfd, int level, int optname, - target_ulong optval, target_ulong optlen) + target_ulong optval, socklen_t *optlen) { int len, lv, val, ret; @@ -783,7 +786,10 @@ case SOL_TCP: /* TCP options all take an 'int' value. */ int_case: -len = tget32(optlen); + if( get_user(len,optlen) ) +return -EFAULT; + if( !access_ok(VERIFY_WRITE, optval,len) ) +return -EFAULT; if (len < 0) return -EINVAL; lv = sizeof(int); @@ -816,7 +822,10 @@ #endif case IP_MULTICAST_TTL: case IP_MULTICAST_LOOP: -len = tget32(optlen); + if( get_user(len,optlen) ) +return -EINVAL; + if( !access_ok(VERIFY_WRITE, optval,len) ) +return -EFAULT; if (len < 0) return -EINVAL; lv = sizeof(int); @@ -835
[Qemu-devel] RCF: [2/11] EFAULT patch
In this section, the functions for reading and writing fdsets, reading rusage, and reading and writing timevals have been updated to use the new kernel like interfaces. Also, places where these function have been used are adjusted to match, this includes do_select(), and the do_syscall() code for getrusage(), gettimeofday(), settimeofday() and setitimer(). Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149Index: qemu/linux-user/syscall.c === --- qemu.orig/linux-user/syscall.c 2007-09-17 16:17:38.0 -0400 +++ qemu/linux-user/syscall.c 2007-09-17 21:07:35.0 -0400 @@ -363,13 +363,15 @@ } } -static inline fd_set *target_to_host_fds(fd_set *fds, +#define FD_MASK_SIZE (FD_SETSIZE/NFDBITS) + +static inline long copy_from_user_fdset(fd_set *fds, target_long *target_fds, int n) { -#if !defined(BSWAP_NEEDED) && !defined(WORDS_BIGENDIAN) -return (fd_set *)target_fds; -#else int i, b; + +if( !access_ok(VERIFY_READ,target_fds,FD_MASK_SIZE) ) return -1; + if (target_fds) { FD_ZERO(fds); for(i = 0;i < n; i++) { @@ -378,22 +380,18 @@ if (b) FD_SET(i, fds); } -return fds; -} else { -return NULL; } -#endif +return 0; } -static inline void host_to_target_fds(target_long *target_fds, +static inline long copy_to_user_fdset(target_long *target_fds, fd_set *fds, int n) { -#if !defined(BSWAP_NEEDED) && !defined(WORDS_BIGENDIAN) -/* nothing to do */ -#else int i, nw, j, k; target_long v; +if( !access_ok(VERIFY_WRITE,target_fds,FD_MASK_SIZE) ) return -1; + if (target_fds) { nw = (n + TARGET_LONG_BITS - 1) / TARGET_LONG_BITS; k = 0; @@ -406,7 +404,7 @@ target_fds[i] = tswapl(v); } } -#endif +return 0; } #if defined(__alpha__) @@ -424,53 +422,50 @@ #endif } -static inline void host_to_target_rusage(target_ulong target_addr, +static inline long copy_to_user_rusage(struct target_rusage *target_rusage, const struct rusage *rusage) { -struct target_rusage *target_rusage; +if( !access_ok(VERIFY_WRITE,target_rusage,sizeof(*target_rusage)) ) return -1; +__put_user(rusage->ru_utime.tv_sec, &target_rusage->ru_utime.tv_sec); +__put_user(rusage->ru_utime.tv_usec, &target_rusage->ru_utime.tv_usec); +__put_user(rusage->ru_stime.tv_sec, &target_rusage->ru_stime.tv_sec); +__put_user(rusage->ru_stime.tv_usec, &target_rusage->ru_stime.tv_usec); +__put_user(rusage->ru_maxrss, &target_rusage->ru_maxrss); +__put_user(rusage->ru_ixrss, &target_rusage->ru_ixrss); +__put_user(rusage->ru_idrss, &target_rusage->ru_idrss); +__put_user(rusage->ru_isrss, &target_rusage->ru_isrss); +__put_user(rusage->ru_minflt, &target_rusage->ru_minflt); +__put_user(rusage->ru_majflt, &target_rusage->ru_majflt); +__put_user(rusage->ru_nswap, &target_rusage->ru_nswap); +__put_user(rusage->ru_inblock, &target_rusage->ru_inblock); +__put_user(rusage->ru_oublock, &target_rusage->ru_oublock); +__put_user(rusage->ru_msgsnd, &target_rusage->ru_msgsnd); +__put_user(rusage->ru_msgrcv, &target_rusage->ru_msgrcv); +__put_user(rusage->ru_nsignals, &target_rusage->ru_nsignals); +__put_user(rusage->ru_nvcsw, &target_rusage->ru_nvcsw); +__put_user(rusage->ru_nivcsw, &target_rusage->ru_nivcsw); -lock_user_struct(target_rusage, target_addr, 0); -target_rusage->ru_utime.tv_sec = tswapl(rusage->ru_utime.tv_sec); -target_rusage->ru_utime.tv_usec = tswapl(rusage->ru_utime.tv_usec); -target_rusage->ru_stime.tv_sec = tswapl(rusage->ru_stime.tv_sec); -target_rusage->ru_stime.tv_usec = tswapl(rusage->ru_stime.tv_usec); -target_rusage->ru_maxrss = tswapl(rusage->ru_maxrss); -target_rusage->ru_ixrss = tswapl(rusage->ru_ixrss); -target_rusage->ru_idrss = tswapl(rusage->ru_idrss); -target_rusage->ru_isrss = tswapl(rusage->ru_isrss); -target_rusage->ru_minflt = tswapl(rusage->ru_minflt); -target_rusage->ru_majflt = tswapl(rusage->ru_majflt); -target_rusage->ru_nswap = tswapl(rusage->ru_nswap); -target_rusage->ru_inblock = tswapl(rusage->ru_inblock); -target_rusage->ru_oublock = tswapl(rusage->ru_oublock); -target_rusage->ru_msgsnd = tswapl(rusage->ru_msgsnd); -target_rusage->ru_msgrcv = tswapl(rusage->ru_msgrcv); -target_rusage->ru_nsignals = tswapl(rusage->ru_nsignals); -target_rusage->ru_nvcsw = tswapl(rusage->ru_nvcsw); -target_rusage->ru_nivcsw = tswapl(rusage->ru_niv
[Qemu-devel] RFC: [1/11] EFAULT patch
This first part contains the additions to the existing infrastructure needed to implement the new interfaces used in the rest of the patch. In exec.c, page_check_range() has been added to take an address and a size and and check to see if it is contained in a valid page that belongs to the target. A flag is passed t indicate wether read or write access should be checked. In qemu.h, the access_ok macro has been given a real implemention, and implementations of copy_from_user() and copy_to_user() have been added. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149Index: qemu/exec.c === --- qemu.orig/exec.c2007-08-07 21:44:10.0 -0400 +++ qemu/exec.c 2007-08-07 21:44:16.0 -0400 @@ -1862,6 +1862,29 @@ spin_unlock(&tb_lock); } +int page_check_range(target_ulong start, target_ulong len, int flags) +{ +PageDesc *p; +target_ulong end; +target_ulong addr; + +end = TARGET_PAGE_ALIGN(start+len); /* must do before we loose bits in the next step */ +start = start & TARGET_PAGE_MASK; + +if( end < start ) return -1; /* we've wrapped around */ +for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) { +p = page_find(addr >> TARGET_PAGE_BITS); + if( !p ) return -1; + if( !(p->flags & PAGE_VALID) ) return -1; + +if (!(p->flags & PAGE_READ) && +(flags & PAGE_READ) ) return -1; +if (!(p->flags & PAGE_WRITE) && +(flags & PAGE_WRITE) ) return -1; +} +return 0; +} + /* called from signal handler: invalidate the code and unprotect the page. Return TRUE if the fault was succesfully handled. */ int page_unprotect(target_ulong address, unsigned long pc, void *puc) Index: qemu/cpu-all.h === --- qemu.orig/cpu-all.h 2007-08-07 21:44:10.0 -0400 +++ qemu/cpu-all.h 2007-08-07 21:44:16.0 -0400 @@ -691,6 +691,7 @@ int page_get_flags(target_ulong address); void page_set_flags(target_ulong start, target_ulong end, int flags); void page_unprotect_range(target_ulong data, target_ulong data_size); +int page_check_range(target_ulong start, target_ulong len, int flags); CPUState *cpu_copy(CPUState *env); Index: qemu/linux-user/qemu.h === --- qemu.orig/linux-user/qemu.h 2007-08-07 21:44:10.0 -0400 +++ qemu/linux-user/qemu.h 2007-08-08 17:54:18.0 -0400 @@ -171,7 +171,8 @@ #define VERIFY_READ 0 #define VERIFY_WRITE 1 -#define access_ok(type,addr,size) (1) +#define access_ok(type,addr,size) \ + (page_check_range((target_ulong)addr,size,(type==VERIFY_READ)?PAGE_READ:PAGE_WRITE)==0) /* NOTE get_user and put_user use host addresses. */ #define __put_user(x,ptr)\ @@ -238,6 +239,26 @@ __ret;\ }) +#define copy_from_user(hptr, gptr, len) \ +({ \ +int __cfu_ret=0;\ +if( access_ok(VERIFY_READ, gptr, (len) ) )\ +memcpy(hptr,gptr,(len)); \ +else \ +__cfu_ret=1;\ +__cfu_ret; \ +}) + +#define copy_to_user(gptr, hptr, len) \ +({ \ +int __ctu_ret=0;\ +if( access_ok(VERIFY_WRITE, gptr, (len)) )\ +memcpy(gptr,hptr,(len)); \ +else \ +__ctu_ret=1;\ +__ctu_ret; \ +}) + /* Functions for accessing guest memory. The tget and tput functions read/write single values, byteswapping as neccessary. The lock_user gets a pointer to a contiguous area of guest memory, but does not perform
[Qemu-devel] RFC: [0/11] EFAULT patch
Following this message, are the 11 parts of the patch that implements EFAULT detection in the linux-user mode. Hopefully, this reflects what was discussed following the first RFC of this patch. Also, hopefully, it is easier to digest in smaller pieces like this. In short, the (un)lock_user*() interfaces have been replaced by access_ok and copy_(to|from)_user() style interfaces. This code should now look more like some of the 32_on_64 code in the Linux kernel. As a side effect of these changes, and the more thorough testing that went along with them, several other bugs have been fixed in areas such as IPC and sockets. As before, the Linux Test Project test suite was used in an armel on x86_64 environment. Your comments would be appreciated as I'd like to finish beating these changes into shape so they can be accepted into the repository. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149
Re: [Qemu-devel] [PATCH] linux-user strace
On Sat, 21 Jul 2007, Andreas Schwab wrote: That's the problem. It does not return the string associated with the target errno, but something else. It depends on what is being passed in to it. Looking over it again this morning, I can see some paths where it is passed the host errno, and some paths where it is passed a target errno via "ret". So in the later case, it would be double mapping the errno, which would be wrong. I had suspected there may be a bit more work left in mapping errno values, but I wasn't yet sure what was needed where. I'd like to clear up the use of target_strerr() as part of that fix if that's ok with everyone. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149
Re: [Qemu-devel] [PATCH] linux-user strace
On Fri, 20 Jul 2007, Andreas Schwab wrote: Stuart Anderson <[EMAIL PROTECTED]> writes: Index: qemu/linux-user/syscall.c === --- qemu.orig/linux-user/syscall.c 2007-07-19 01:42:43.0 -0400 +++ qemu/linux-user/syscall.c 2007-07-19 01:43:18.0 -0400 @@ -312,6 +312,11 @@ return (unsigned long)ret >= (unsigned long)(-4096); } +char *target_strerror(int err) +{ + return strerror(host_to_target_errno(err)); +} + That looks backwards. strerror surely expects a host errno value, but host_to_target_errno returns the errno value for the target, doesn't it? The function is called target_strerror() 8-). It is used to display the errno string for the target, not the host. strerror() is just a simple map, so it doesn't really care. Regular strace on qemu itself will give the host error strings. This is used for gettign the error string of the target. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149
[Qemu-devel] [PATCH] linux-user discrete IPC calls
At least armel implements discreet IPC calls instead of multiplexing them through a single syscall. This patch adds support for this. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149Index: qemu/linux-user/syscall.c === --- qemu.orig/linux-user/syscall.c 2007-07-20 13:09:03.0 -0400 +++ qemu/linux-user/syscall.c 2007-07-20 13:10:08.0 -0400 @@ -3742,6 +3742,41 @@ ret = do_ipc(arg1, arg2, arg3, arg4, arg5, arg6); break; #endif +#ifdef TARGET_NR_semop +case TARGET_NR_semop: +ret = get_errno(semop(arg1,(struct sembuf *) arg2, arg3)); +break; +#endif +#ifdef TARGET_NR_semget +case TARGET_NR_semget: +ret = get_errno(semget(arg1, arg2, arg3)); +break; +#endif +#ifdef TARGET_NR_semctl +case TARGET_NR_semctl: +ret = do_semctl(arg1, arg2, arg3, arg4); +break; +#endif +#ifdef TARGET_NR_msgsnd +case TARGET_NR_msgsnd: +ret = do_msgsnd(arg1, arg2, arg3, arg4); +break; +#endif +#ifdef TARGET_NR_msgrcv +case TARGET_NR_msgrcv: +ret = do_msgrcv(arg1, arg2, arg3, arg4, arg5); +break; +#endif +#ifdef TARGET_NR_msgget +case TARGET_NR_msgget: + ret = get_errno(msgget(arg1, arg2)); +break; +#endif +#ifdef TARGET_NR_msgctl +case TARGET_NR_msgctl: +ret = do_msgctl(arg1, arg2, arg3); +break; +#endif case TARGET_NR_fsync: ret = get_errno(fsync(arg1)); break;
Re: [Qemu-devel] [PATCH] linux-user EFAULT implementation
On Tue, 10 Jul 2007, Fabrice Bellard wrote: I confirm that I expected g2h() to be completely removed in case the Linux user access API is used. I agree too that it should not be used. I'm testing ARM on x86_64, and used it in a few places to clean up some warnings. The real fix is to change what I was doing to not need this asignment anyway. I will take another look at how to bury this part in the copy* interfaces. Would it be OK to use g2h() inside the implementation of copy* ? Since you agree for the copying interface, I suggest to convert all the code to it. OK, I'll continue in this direction, after taking a fresh look at what I did yesterday. Thanks for the feedback. Stuart Stuart R. Anderson [EMAIL PROTECTED] Solutions Architect http://www.c2.net/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149
Re: [Qemu-devel] [PATCH] linux-user EFAULT implementation
On Mon, 9 Jul 2007, Stuart Anderson wrote: Attached is a diff ... Here's the diff. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149*** linux-user/syscall.c 2007-07-09 07:33:46.0 -0400 --- linux-user/syscall.c.stu 2007-07-09 07:01:12.0 -0400 *** *** 522,550 return ret; } ! static inline long copy_from_user_sockaddr(struct sockaddr *addr, target_ulong target_addr, !socklen_t len) { long ret = 0; ! struct target_sockaddr *target_saddr = (struct target_sockaddr *)target_addr; ! if( (ret=access_ok(VERIFY_READ,target_saddr,len)) != 0 ) return ret; memcpy(addr, target_saddr, len); addr->sa_family = tswap16(target_saddr->sa_family); return ret; } ! static inline long copy_to_user_sockaddr(target_ulong target_addr, struct sockaddr *addr, !socklen_t len) { long ret = 0; ! struct target_sockaddr *target_saddr = (struct target_sockaddr *)target_addr; ! if( (ret=access_ok(VERIFY_WRITE,target_saddr,len)) != 0 ) return ret; memcpy(target_saddr, addr, len); target_saddr->sa_family = tswap16(addr->sa_family); return ret; } --- 522,554 return ret; } ! static inline long target_to_host_sockaddr(struct sockaddr *addr, target_ulong target_addr, !socklen_t len, !int pg_access) { long ret = 0; ! struct target_sockaddr *target_saddr; ! if( (ret=lock_and_check_user_struct(&target_saddr,target_addr,len,1,pg_access)) != 0 ) return ret; memcpy(addr, target_saddr, len); addr->sa_family = tswap16(target_saddr->sa_family); + unlock_user(target_saddr, target_addr, 0); return ret; } ! static inline long host_to_target_sockaddr(target_ulong target_addr, struct sockaddr *addr, !socklen_t len, !int pg_access) { long ret = 0; ! struct target_sockaddr *target_saddr; ! if( (ret=lock_and_check_user_struct(&target_saddr,target_addr,len,1,pg_access)) != 0 ) return ret; memcpy(target_saddr, addr, len); target_saddr->sa_family = tswap16(addr->sa_family); + unlock_user(target_saddr, target_addr, len); return ret; } *** *** 909,915 long ret = 0; void *addr = alloca(addrlen); ! if( (ret=copy_from_user_sockaddr(addr, target_addr, addrlen)) != 0 ) return ret; return get_errno(bind(sockfd, addr, addrlen)); } --- 913,919 long ret = 0; void *addr = alloca(addrlen); ! if( (ret=target_to_host_sockaddr(addr, target_addr, addrlen,PAGE_READ)) != 0 ) return ret; return get_errno(bind(sockfd, addr, addrlen)); } *** *** 919,925 long ret = 0; void *addr = alloca(addrlen); ! if( (ret=copy_from_user_sockaddr(addr, target_addr, addrlen)) != 0 ) return ret; return get_errno(connect(sockfd, addr, addrlen)); } --- 923,929 long ret = 0; void *addr = alloca(addrlen); ! if( (ret=target_to_host_sockaddr(addr, target_addr, addrlen,PAGE_READ)) != 0 ) return ret; return get_errno(connect(sockfd, addr, addrlen)); } *** *** 944,956 msg.msg_namelen = tswap32(msgp->msg_namelen); msg.msg_name = alloca(msg.msg_namelen); if( send ) { ! if( (ret=copy_from_user_sockaddr(msg.msg_name, tswapl(msgp->msg_name), ! msg.msg_namelen)) != 0 ) return ret; } else { ! /* FIXME ! if( (ret=copy_from_user_sockaddr(msg.msg_name, tswapl(msgp->msg_name), msg.msg_namelen,PAGE_WRITE)) != 0 ) return ret; - */ } } else { msg.msg_name = NULL; --- 948,958 msg.msg_namelen = tswap32(msgp->msg_namelen); msg.msg_name = alloca(msg.msg_namelen); if( send ) { ! if( (ret=target_to_host_sockaddr(msg.msg_name, tswapl(msgp->msg_name), ! msg.msg_namelen,PAGE_READ)) != 0 ) return ret; } else { ! if( (ret=target_to_host_sockaddr(msg.msg_name, tswapl(msgp->msg_name), msg.msg_namelen,PAGE_WRITE)) != 0 ) return ret; } } else {
Re: [Qemu-devel] [PATCH] linux-user EFAULT implementation
On Fri, 6 Jul 2007, Stuart Anderson wrote: So, the question is: Can I simplify this code to assume that guest and host addresses coexist and use the copy_*_user() or just the access_ok() interfaces? Attached is a diff that shows what this will look like for the struct sockaddr handling case. In short, the two functions for mapping this structure get renamed target_to_host_sockaddr -> copy_from_user_sockaddr host_to_target_sockaddr -> copy_to_user_sockaddr and lose the pg_access parameter as read/write access is determined by wether we are copying to or from "user space". The macro access_ok() is used to check the validity of the memory being accessed. This change also completely drops the notion of locking and unlocking memory, which was the previous model being used. Fabrice, Is this change what you had in mind? Does it cause a problem for anyone else? Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149
Re: [Qemu-devel] [PATCH] linux-user EFAULT implementation
On Fri, 6 Jul 2007, Stuart Anderson wrote: Moreover, I believe using similar functions as Linux for memory access (copyfromuser, copytouser, get_user, put_user) would be cleaner. This makes sense. That code that I sent was based on the idea that I was just extending the model that was already there, instead of giving it a complete overhaul. I'll look into how much work the overhaul would be. After some digging, the one "design-level" issue I have found is that the current lock_user_struct() and the new lock_and_check_user_struct(), interfaces are based on the assumption that we need to map addresses between guest and host, so they provide a place to call g2h() and return the new address. This is different from copy_{to|from}_user(), which assumes all addresses are valid as is, but that the system just needs to ensure they are correctly mapped in for the data copy. Contrary to this, cpu-all.h has the following comment & code: #define GUEST_BASE 0 /* All direct uses of g2h and h2g need to go away for usermode softmmu. */ #define g2h(x) ((void *)((unsigned long)(x) + GUEST_BASE)) #define h2g(x) ((target_ulong)(x - GUEST_BASE)) It appears that g2h() and h2g() are mostly no-ops, with the typecasting being the only possible useful part remaining. So, the question is: Can I simplify this code to assume that guest and host addresses coexist and use the copy_*_user() or just the access_ok() interfaces? This would be one step closer to eliminating the use of g2h() and h2g() in the usermode code as is suggested by the comment in cpu-all.h. One other comment to make, is that in most cases, a simple copy is not sufficient. Unlike the real Linux kernel, in many places, we are doing structure mapping instead of a simple buffer copy. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149
Re: [Qemu-devel] [PATCH] linux-user EFAULT implementation
On Fri, 6 Jul 2007, Fabrice Bellard wrote: Please update page_check_range() (and other related functions) to return -EFAULT instead of EFAULT in case of error. Will do. Moreover, I believe using similar functions as Linux for memory access (copyfromuser, copytouser, get_user, put_user) would be cleaner. This makes sense. That code that I sent was based on the idea that I was just extending the model that was already there, instead of giving it a complete overhaul. I'll look into how much work the overhaul would be. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149
[Qemu-devel] [PATCH] tkill
This small patch implements tkill(). It parallels the tgkill() implementation that was added recently. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149Index: qemu/linux-user/syscall.c === --- qemu.orig/linux-user/syscall.c 2007-07-06 09:50:23.0 -0400 +++ qemu/linux-user/syscall.c 2007-07-06 10:00:55.0 -0400 @@ -154,6 +154,7 @@ #define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo #define __NR_sys_syslog __NR_syslog #define __NR_sys_tgkill __NR_tgkill +#define __NR_sys_tkill __NR_tkill #if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__) #define __NR__llseek __NR_lseek @@ -174,7 +175,12 @@ loff_t *, res, uint, wh); _syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo) _syscall3(int,sys_syslog,int,type,char*,bufp,int,len) +#ifdef TARGET_NR_tgkill _syscall3(int,sys_tgkill,int,tgid,int,pid,int,sig) +#endif +#ifdef TARGET_NR_tkill +_syscall2(int,sys_tkill,int,tid,int,sig) +#endif #ifdef __NR_exit_group _syscall1(int,exit_group,int,error_code) #endif @@ -4774,6 +4780,12 @@ break; #endif +#ifdef TARGET_NR_tkill +case TARGET_NR_tkill: +ret = get_errno(sys_tkill((int)arg1, (int)arg2)); +break; +#endif + #ifdef TARGET_NR_tgkill case TARGET_NR_tgkill: ret = get_errno(sys_tgkill((int)arg1, (int)arg2, (int)arg3));
Re: [Qemu-devel] [RFC] strace-like output for user-linux
On Mon, 4 Jun 2007, Mulyadi Santosa wrote: Hi Stuart I hope my little advice is correct... but overall, I think you add a nice usefuk feature here. +}--> don't you think we should break() here since we already found correct syscall num? otherwise we will continue the loop Yes indeed. Thanks for catching that. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149
Re: [Qemu-devel] [PATCH] linux-user semaphore structure mapping
On Fri, 1 Jun 2007, Thiemo Seufer wrote: Stuart Anderson wrote: This is a refresh (vs 5/28 cvs) of a patch sent several weeks ago. This patch implments the structure handling for the semaphore IPC related structures used by semctl(). It produces too many compiler warnings to be comfortable with, and breaks compilation of alpha-linux-user. Thiemo, I've attached both the semaphore and message queue patches to this message since there is a dependency between them (message queue patch must be applied on top of the semaphore patch). This is updated to 6/01 cvs, and includes the additional part to fix alpha the same as is done for the other archs. It also cleans up the warnings in the new code areas. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149Index: qemu/linux-user/i386/syscall.h === --- qemu.orig/linux-user/i386/syscall.h 2007-06-01 16:52:07.0 -0400 +++ qemu/linux-user/i386/syscall.h 2007-06-01 17:08:29.0 -0400 @@ -142,80 +142,4 @@ struct target_vm86plus_info_struct vm86plus; }; -/* ipcs */ - -#define TARGET_SEMOP 1 -#define TARGET_SEMGET 2 -#define TARGET_SEMCTL 3 -#define TARGET_MSGSND 11 -#define TARGET_MSGRCV 12 -#define TARGET_MSGGET 13 -#define TARGET_MSGCTL 14 -#define TARGET_SHMAT 21 -#define TARGET_SHMDT 22 -#define TARGET_SHMGET 23 -#define TARGET_SHMCTL 24 - -struct target_msgbuf { - int mtype; - char mtext[1]; -}; - -struct target_ipc_kludge { - unsigned int msgp; /* Really (struct msgbuf *) */ - int msgtyp; -}; - -struct target_ipc_perm { - int key; - unsigned short uid; - unsigned short gid; - unsigned short cuid; - unsigned short cgid; - unsigned short mode; - unsigned short seq; -}; - -struct target_msqid_ds { - struct target_ipc_perm msg_perm; - unsigned int msg_first; /* really struct target_msg* */ - unsigned int msg_last; /* really struct target_msg* */ - unsigned int msg_stime; /* really target_time_t */ - unsigned int msg_rtime; /* really target_time_t */ - unsigned int msg_ctime; /* really target_time_t */ - unsigned int wwait; /* really struct wait_queue* */ - unsigned int rwait; /* really struct wait_queue* */ - unsigned short msg_cbytes; - unsigned short msg_qnum; - unsigned short msg_qbytes; - unsigned short msg_lspid; - unsigned short msg_lrpid; -}; - -struct target_shmid_ds { - struct target_ipc_perm shm_perm; - int shm_segsz; - unsigned int shm_atime; /* really target_time_t */ - unsigned int shm_dtime; /* really target_time_t */ - unsigned int shm_ctime; /* really target_time_t */ - unsigned short shm_cpid; - unsigned short shm_lpid; - short shm_nattch; - unsigned short shm_npages; - unsigned long *shm_pages; - void *attaches; /* really struct shm_desc * */ -}; - -#define TARGET_IPC_RMID 0 -#define TARGET_IPC_SET 1 -#define TARGET_IPC_STAT 2 - -union target_semun { -int val; -unsigned int buf; /* really struct semid_ds * */ -unsigned int array; /* really unsigned short * */ -unsigned int __buf; /* really struct seminfo * */ -unsigned int __pad; /* really void* */ -}; - #define UNAME_MACHINE "i686" Index: qemu/linux-user/ppc/syscall.h === --- qemu.orig/linux-user/ppc/syscall.h 2007-06-01 16:52:07.0 -0400 +++ qemu/linux-user/ppc/syscall.h 2007-06-01 17:08:29.0 -0400 @@ -51,80 +51,4 @@ * flags masks */ -/* ipcs */ - -#define TARGET_SEMOP 1 -#define TARGET_SEMGET 2 -#define TARGET_SEMCTL 3 -#define TARGET_MSGSND 11 -#define TARGET_MSGRCV 12 -#define TARGET_MSGGET 13 -#define TARGET_MSGCTL 14 -#define TARGET_SHMAT 21 -#define TARGET_SHMDT 22 -#define TARGET_SHMGET 23 -#define TARGET_SHMCTL 24 - -struct target_msgbuf { - int mtype; - char mtext[1]; -}; - -struct target_ipc_kludge { - unsigned int msgp; /* Really (struct msgbuf *) */ - int msgtyp; -}; - -struct target_ipc_perm { - int key; - unsigned short uid; - unsigned short gid; - unsigned short cuid; - unsigned short cgid; - unsigned short mode; - unsigned short seq; -}; - -struct target_msqid_ds { - struct target_ipc_perm msg_perm; - unsigned int msg_first; /* really struct target_msg* */ - unsigned int msg_last; /* really struct target_msg* */ - unsigned int msg_stime; /* really target_time_t */ - unsigned int msg_rtime; /* really target_time_t */ - unsigned int msg_ctime; /* really target_time_t */ - unsigned int wwait; /* really struct wait_queue* */ - unsigned int rwait
Re: [Qemu-devel] [PATCH] message queue IPC structures
On Fri, 1 Jun 2007, Thiemo Seufer wrote: Stuart Anderson wrote: This is a refresh (vs 05/28 cvs) of a patch sent several weeks ago. This patch implements the structure handling for the structures used by the Message queue IPC interfaces msgctl(), msgrcv() and msgsnd(). This was tested using LTP on an ARM target. Breaks building i386-linux-user. I forgot to mention that this patch should be applied on top of the semaphore patch that was sent at the same time. It seems to be building OK for me when stacked as intended. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149
Re: [Qemu-devel] [PATCH] linux-user semaphore structure mapping
On Fri, 1 Jun 2007, Thiemo Seufer wrote: Stuart Anderson wrote: This is a refresh (vs 5/28 cvs) of a patch sent several weeks ago. This patch implments the structure handling for the semaphore IPC related structures used by semctl(). This was tested using LTP on an ARM target. Were there any objections to this patch? It produces too many compiler warnings to be comfortable with, and breaks compilation of alpha-linux-user. I think alpha was actually added after I first created this patch, and I haven't been building it as it's not one of the archs I normally use. Note to self to do a build w/ everything turned on more often. The fix for it is to remove the same stuff as is done for a couple of the other archs. I'll clean it up, and take another look at the warning for this and the message queue patch, and resubmit. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149
Re: [Qemu-devel] [PATCH] mips-linux-user errno mapping
On Thu, 31 May 2007, Thiemo Seufer wrote: Please clean up the compiler warnings. This one ist just the most obvious, I also see many more of the form: Sorry. I missed those in the noise caused by another, yet to be completed patch, which is also in my patch stack. Attached is the cleaned up patch. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149Index: qemu/linux-user/errno_defs.h === --- /dev/null 1970-01-01 00:00:00.0 + +++ qemu/linux-user/errno_defs.h 2007-05-31 08:15:03.0 -0400 @@ -0,0 +1,142 @@ +/* + * Target definitions of errnos. These may be overridden by an + * architecture specific header if needed. + * + * Taken from asm-generic/errno-base.h and asm-generic/errno.h + */ +#define TARGET_EPERM1 /* Operation not permitted */ +#define TARGET_ENOENT 2 /* No such file or directory */ +#define TARGET_ESRCH3 /* No such process */ +#define TARGET_EINTR4 /* Interrupted system call */ +#define TARGET_EIO 5 /* I/O error */ +#define TARGET_ENXIO6 /* No such device or address */ +#define TARGET_E2BIG7 /* Argument list too long */ +#define TARGET_ENOEXEC 8 /* TARGET_Exec format error */ +#define TARGET_EBADF9 /* Bad file number */ +#define TARGET_ECHILD 10 /* No child processes */ +#define TARGET_EAGAIN 11 /* Try again */ +#define TARGET_ENOMEM 12 /* Out of memory */ +#define TARGET_EACCES 13 /* Permission denied */ +#define TARGET_EFAULT 14 /* Bad address */ +#define TARGET_ENOTBLK 15 /* Block device required */ +#define TARGET_EBUSY 16 /* Device or resource busy */ +#define TARGET_EEXIST 17 /* File exists */ +#define TARGET_EXDEV 18 /* Cross-device link */ +#define TARGET_ENODEV 19 /* No such device */ +#define TARGET_ENOTDIR 20 /* Not a directory */ +#define TARGET_EISDIR 21 /* Is a directory */ +#define TARGET_EINVAL 22 /* Invalid argument */ +#define TARGET_ENFILE 23 /* File table overflow */ +#define TARGET_EMFILE 24 /* Too many open files */ +#define TARGET_ENOTTY 25 /* Not a typewriter */ +#define TARGET_ETXTBSY 26 /* Text file busy */ +#define TARGET_EFBIG 27 /* File too large */ +#define TARGET_ENOSPC 28 /* No space left on device */ +#define TARGET_ESPIPE 29 /* Illegal seek */ +#define TARGET_EROFS 30 /* Read-only file system */ +#define TARGET_EMLINK 31 /* Too many links */ +#define TARGET_EPIPE 32 /* Broken pipe */ +#define TARGET_EDOM33 /* Math argument out of domain of func */ +#define TARGET_ERANGE 34 /* Math result not representable */ + +#define TARGET_EDEADLK 35 /* Resource deadlock would occur */ +#define TARGET_ENAMETOOLONG36 /* File name too long */ +#define TARGET_ENOLCK 37 /* No record locks available */ +#define TARGET_ENOSYS 38 /* Function not implemented */ +#define TARGET_ENOTEMPTY 39 /* Directory not empty */ +#define TARGET_ELOOP 40 /* Too many symbolic links encountered */ + +#define TARGET_ENOMSG 42 /* No message of desired type */ +#define TARGET_EIDRM 43 /* Identifier removed */ +#define TARGET_ECHRNG 44 /* Channel number out of range */ +#define TARGET_EL2NSYNC45 /* Level 2 not synchronized */ +#define TARGET_EL3HLT 46 /* Level 3 halted */ +#define TARGET_EL3RST 47 /* Level 3 reset */ +#define TARGET_ELNRNG 48 /* Link number out of range */ +#define TARGET_EUNATCH 49 /* Protocol driver not attached */ +#define TARGET_ENOCSI 50 /* No CSI structure available */ +#define TARGET_EL2HLT 51 /* Level 2 halted */ +#define TARGET_EBADE 52 /* Invalid exchange */ +#define TARGET_EBADR 53 /* Invalid request descriptor */ +#define TARGET_EXFULL 54 /* TARGET_Exchange full */ +#define TARGET_ENOANO 55 /* No anode */ +#define TARGET_EBADRQC 56 /* Invalid request code */ +#define TARGET_EBADSLT 57 /* Invalid slot */ + +#define TARGET_EBFONT 59 /* Bad font file format */ +#define TARGET_ENOSTR 60 /* Device not a stream */ +#define TARGET_ENODATA 61 /* No data available */ +#define TARGET_ETIME
[Qemu-devel] [PATCH] mips-linux-user errno mapping
The linux user code was completely missing the ability to map errnos from the host to the target. This patch adds this ability, with the mapping needed for MIPS. With this patch, an appreciable number of the tests in LTP now PASS (remaining failures are due to other bugs not yet fixed). Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149Index: qemu/linux-user/errno_defs.h === --- /dev/null 1970-01-01 00:00:00.0 + +++ qemu/linux-user/errno_defs.h 2007-05-30 13:29:13.0 -0400 @@ -0,0 +1,143 @@ +#warning "errno_defs" +/* + * Target definitions of errnos. These may be overridden by an + * architecture specific header if needed. + * + * Taken from asm-generic/errno-base.h and asm-generic/errno.h + */ +#define TARGET_EPERM1 /* Operation not permitted */ +#define TARGET_ENOENT 2 /* No such file or directory */ +#define TARGET_ESRCH3 /* No such process */ +#define TARGET_EINTR4 /* Interrupted system call */ +#define TARGET_EIO 5 /* I/O error */ +#define TARGET_ENXIO6 /* No such device or address */ +#define TARGET_E2BIG7 /* Argument list too long */ +#define TARGET_ENOEXEC 8 /* TARGET_Exec format error */ +#define TARGET_EBADF9 /* Bad file number */ +#define TARGET_ECHILD 10 /* No child processes */ +#define TARGET_EAGAIN 11 /* Try again */ +#define TARGET_ENOMEM 12 /* Out of memory */ +#define TARGET_EACCES 13 /* Permission denied */ +#define TARGET_EFAULT 14 /* Bad address */ +#define TARGET_ENOTBLK 15 /* Block device required */ +#define TARGET_EBUSY 16 /* Device or resource busy */ +#define TARGET_EEXIST 17 /* File exists */ +#define TARGET_EXDEV 18 /* Cross-device link */ +#define TARGET_ENODEV 19 /* No such device */ +#define TARGET_ENOTDIR 20 /* Not a directory */ +#define TARGET_EISDIR 21 /* Is a directory */ +#define TARGET_EINVAL 22 /* Invalid argument */ +#define TARGET_ENFILE 23 /* File table overflow */ +#define TARGET_EMFILE 24 /* Too many open files */ +#define TARGET_ENOTTY 25 /* Not a typewriter */ +#define TARGET_ETXTBSY 26 /* Text file busy */ +#define TARGET_EFBIG 27 /* File too large */ +#define TARGET_ENOSPC 28 /* No space left on device */ +#define TARGET_ESPIPE 29 /* Illegal seek */ +#define TARGET_EROFS 30 /* Read-only file system */ +#define TARGET_EMLINK 31 /* Too many links */ +#define TARGET_EPIPE 32 /* Broken pipe */ +#define TARGET_EDOM33 /* Math argument out of domain of func */ +#define TARGET_ERANGE 34 /* Math result not representable */ + +#define TARGET_EDEADLK 35 /* Resource deadlock would occur */ +#define TARGET_ENAMETOOLONG36 /* File name too long */ +#define TARGET_ENOLCK 37 /* No record locks available */ +#define TARGET_ENOSYS 38 /* Function not implemented */ +#define TARGET_ENOTEMPTY 39 /* Directory not empty */ +#define TARGET_ELOOP 40 /* Too many symbolic links encountered */ + +#define TARGET_ENOMSG 42 /* No message of desired type */ +#define TARGET_EIDRM 43 /* Identifier removed */ +#define TARGET_ECHRNG 44 /* Channel number out of range */ +#define TARGET_EL2NSYNC45 /* Level 2 not synchronized */ +#define TARGET_EL3HLT 46 /* Level 3 halted */ +#define TARGET_EL3RST 47 /* Level 3 reset */ +#define TARGET_ELNRNG 48 /* Link number out of range */ +#define TARGET_EUNATCH 49 /* Protocol driver not attached */ +#define TARGET_ENOCSI 50 /* No CSI structure available */ +#define TARGET_EL2HLT 51 /* Level 2 halted */ +#define TARGET_EBADE 52 /* Invalid exchange */ +#define TARGET_EBADR 53 /* Invalid request descriptor */ +#define TARGET_EXFULL 54 /* TARGET_Exchange full */ +#define TARGET_ENOANO 55 /* No anode */ +#define TARGET_EBADRQC 56 /* Invalid request code */ +#define TARGET_EBADSLT 57 /* Invalid slot */ + +#define TARGET_EBFONT 59 /* Bad font file format */ +#define TARGET_ENOSTR 60 /* Device not a stream */ +#define TARGET_ENODATA 61 /* No data available */ +#define TARGET_ET
[Qemu-devel] [mips-linux-user] patch for pipe() result handling
pipe(2) on MIPS does some funny, non-standard stuff with it's return data. This patch implments this unusual handling. Without this patch, bash closes it's own stdin by mistake and therefore exits immediately after presenting the prompt. The LTP test results for the pipe() tests are improved with this patch as well. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149Index: qemu/linux-user/syscall.c === --- qemu.orig/linux-user/syscall.c 2007-05-29 22:42:04.0 -0400 +++ qemu/linux-user/syscall.c 2007-05-29 22:47:00.0 -0400 @@ -2916,8 +2916,13 @@ int host_pipe[2]; ret = get_errno(pipe(host_pipe)); if (!is_error(ret)) { +#if defined(TARGET_MIPS) + ((CPUMIPSState*)cpu_env)->gpr[3] = host_pipe[1]; + ret = host_pipe[0]; +#else tput32(arg1, host_pipe[0]); tput32(arg1 + 4, host_pipe[1]); +#endif } } break;
[Qemu-devel] [PATCH] message queue IPC structures
This is a refresh (vs 05/28 cvs) of a patch sent several weeks ago. This patch implements the structure handling for the structures used by the Message queue IPC interfaces msgctl(), msgrcv() and msgsnd(). This was tested using LTP on an ARM target. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149Index: qemu/linux-user/syscall.c === --- qemu.orig/linux-user/syscall.c 2007-03-23 09:06:14.0 -0400 +++ qemu/linux-user/syscall.c 2007-03-23 09:06:16.0 -0400 @@ -1322,6 +1322,117 @@ return ret; } +struct target_msqid_ds +{ + struct target_ipc_perm msg_perm; + target_ulong msg_stime; + target_ulong __unused1; + target_ulong msg_rtime; + target_ulong __unused2; + target_ulong msg_ctime; + target_ulong __unused3; + target_ulong __msg_cbytes; + target_ulong msg_qnum; + target_ulong msg_qbytes; + target_ulong msg_lspid; + target_ulong msg_lrpid; + target_ulong __unused4; + target_ulong __unused5; +}; + +static inline void target_to_host_msqid_ds(struct msqid_ds *host_md, + target_ulong target_addr) +{ +struct target_msqid_ds *target_md; + +lock_user_struct(target_md, target_addr, 1); +target_to_host_ipc_perm(&(host_md->msg_perm),target_addr); +host_md->msg_stime = tswapl(target_md->msg_stime); +host_md->msg_rtime = tswapl(target_md->msg_rtime); +host_md->msg_ctime = tswapl(target_md->msg_ctime); +host_md->__msg_cbytes = tswapl(target_md->__msg_cbytes); +host_md->msg_qnum = tswapl(target_md->msg_qnum); +host_md->msg_qbytes = tswapl(target_md->msg_qbytes); +host_md->msg_lspid = tswapl(target_md->msg_lspid); +host_md->msg_lrpid = tswapl(target_md->msg_lrpid); +unlock_user_struct(target_md, target_addr, 0); +} + +static inline void host_to_target_msqid_ds(target_ulong target_addr, + struct msqid_ds *host_md) +{ +struct target_msqid_ds *target_md; + +lock_user_struct(target_md, target_addr, 0); +host_to_target_ipc_perm(target_addr,&(host_md->msg_perm)); +target_md->msg_stime = tswapl(host_md->msg_stime); +target_md->msg_rtime = tswapl(host_md->msg_rtime); +target_md->msg_ctime = tswapl(host_md->msg_ctime); +target_md->__msg_cbytes = tswapl(host_md->__msg_cbytes); +target_md->msg_qnum = tswapl(host_md->msg_qnum); +target_md->msg_qbytes = tswapl(host_md->msg_qbytes); +target_md->msg_lspid = tswapl(host_md->msg_lspid); +target_md->msg_lrpid = tswapl(host_md->msg_lrpid); +unlock_user_struct(target_md, target_addr, 1); +} + +static inline long do_msgctl(long first, long second, long ptr) +{ +struct msqid_ds dsarg; +int cmd = second&0xff; +long ret = 0; +switch( cmd ) { +case IPC_STAT: +case IPC_SET: +target_to_host_msqid_ds(&dsarg,ptr); +ret = get_errno(msgctl(first, cmd, &dsarg)); +host_to_target_msqid_ds(ptr,&dsarg); +default: +ret = get_errno(msgctl(first, cmd, &dsarg)); +} +return ret; +} + +struct target_msgbuf { + target_ulong mtype; + char mtext[1]; +}; + +static inline long do_msgsnd(long msqid, long msgp, long msgsz, long msgflg) +{ +struct target_msgbuf *target_mb; +struct msgbuf *host_mb; +long ret = 0; + +lock_user_struct(target_mb,msgp,0); +host_mb = malloc(msgsz+sizeof(long)); +host_mb->mtype = tswapl(target_mb->mtype); +memcpy(host_mb->mtext,target_mb->mtext,msgsz); +ret = get_errno(msgsnd(msqid, host_mb, msgsz, msgflg)); +free(host_mb); +unlock_user_struct(target_mb, msgp, 0); + +return ret; +} + +static inline long do_msgrcv(long msqid, long msgp, long msgsz, long msgtype, long msgflg) +{ +struct target_msgbuf *target_mb; +struct msgbuf *host_mb; +long ret = 0; + +lock_user_struct(target_mb,msgp,0); +host_mb = malloc(msgsz+sizeof(long)); +ret = get_errno(msgrcv(msqid, host_mb, msgsz, 1, msgflg)); +if( ret > 0 ) + memcpy(target_mb->mtext,host_mb->mtext,ret); +target_mb->mtype = tswapl(host_mb->mtype); +free(host_mb); +unlock_user_struct(target_mb, msgp, 0); + +return ret; +} + /* ??? This only works with linear mappings. */ static long do_ipc(long call, long first, long second, long third, long ptr, long fifth) @@ -1358,27 +1469,27 @@ break; case IPCOP_msgsnd: - ret = get_errno(msgsnd(first, (struct msgbuf *) ptr, second, third)); + ret = do_msgsnd(first, ptr, second, third); break; case IPCOP_msgctl: - ret = get_errno(msgctl(first, second, (struct msqid_ds *) ptr)); + ret = do_msgctl(first, second, ptr); break; case IPCOP_msgrcv: - { - struct ipc_kludge -
[Qemu-devel] [PATCH] linux-user semaphore structure mapping
This is a refresh (vs 5/28 cvs) of a patch sent several weeks ago. This patch implments the structure handling for the semaphore IPC related structures used by semctl(). This was tested using LTP on an ARM target. Were there any objections to this patch? Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149Index: qemu/linux-user/i386/syscall.h === --- qemu.orig/linux-user/i386/syscall.h 2007-03-23 09:05:19.0 -0400 +++ qemu/linux-user/i386/syscall.h 2007-03-23 09:05:32.0 -0400 @@ -142,80 +142,4 @@ struct target_vm86plus_info_struct vm86plus; }; -/* ipcs */ - -#define TARGET_SEMOP 1 -#define TARGET_SEMGET 2 -#define TARGET_SEMCTL 3 -#define TARGET_MSGSND 11 -#define TARGET_MSGRCV 12 -#define TARGET_MSGGET 13 -#define TARGET_MSGCTL 14 -#define TARGET_SHMAT 21 -#define TARGET_SHMDT 22 -#define TARGET_SHMGET 23 -#define TARGET_SHMCTL 24 - -struct target_msgbuf { - int mtype; - char mtext[1]; -}; - -struct target_ipc_kludge { - unsigned int msgp; /* Really (struct msgbuf *) */ - int msgtyp; -}; - -struct target_ipc_perm { - int key; - unsigned short uid; - unsigned short gid; - unsigned short cuid; - unsigned short cgid; - unsigned short mode; - unsigned short seq; -}; - -struct target_msqid_ds { - struct target_ipc_perm msg_perm; - unsigned int msg_first; /* really struct target_msg* */ - unsigned int msg_last; /* really struct target_msg* */ - unsigned int msg_stime; /* really target_time_t */ - unsigned int msg_rtime; /* really target_time_t */ - unsigned int msg_ctime; /* really target_time_t */ - unsigned int wwait; /* really struct wait_queue* */ - unsigned int rwait; /* really struct wait_queue* */ - unsigned short msg_cbytes; - unsigned short msg_qnum; - unsigned short msg_qbytes; - unsigned short msg_lspid; - unsigned short msg_lrpid; -}; - -struct target_shmid_ds { - struct target_ipc_perm shm_perm; - int shm_segsz; - unsigned int shm_atime; /* really target_time_t */ - unsigned int shm_dtime; /* really target_time_t */ - unsigned int shm_ctime; /* really target_time_t */ - unsigned short shm_cpid; - unsigned short shm_lpid; - short shm_nattch; - unsigned short shm_npages; - unsigned long *shm_pages; - void *attaches; /* really struct shm_desc * */ -}; - -#define TARGET_IPC_RMID 0 -#define TARGET_IPC_SET 1 -#define TARGET_IPC_STAT 2 - -union target_semun { -int val; -unsigned int buf; /* really struct semid_ds * */ -unsigned int array; /* really unsigned short * */ -unsigned int __buf; /* really struct seminfo * */ -unsigned int __pad; /* really void* */ -}; - #define UNAME_MACHINE "i686" Index: qemu/linux-user/ppc/syscall.h === --- qemu.orig/linux-user/ppc/syscall.h 2007-03-23 09:05:19.0 -0400 +++ qemu/linux-user/ppc/syscall.h 2007-03-23 09:05:32.0 -0400 @@ -51,80 +51,4 @@ * flags masks */ -/* ipcs */ - -#define TARGET_SEMOP 1 -#define TARGET_SEMGET 2 -#define TARGET_SEMCTL 3 -#define TARGET_MSGSND 11 -#define TARGET_MSGRCV 12 -#define TARGET_MSGGET 13 -#define TARGET_MSGCTL 14 -#define TARGET_SHMAT 21 -#define TARGET_SHMDT 22 -#define TARGET_SHMGET 23 -#define TARGET_SHMCTL 24 - -struct target_msgbuf { - int mtype; - char mtext[1]; -}; - -struct target_ipc_kludge { - unsigned int msgp; /* Really (struct msgbuf *) */ - int msgtyp; -}; - -struct target_ipc_perm { - int key; - unsigned short uid; - unsigned short gid; - unsigned short cuid; - unsigned short cgid; - unsigned short mode; - unsigned short seq; -}; - -struct target_msqid_ds { - struct target_ipc_perm msg_perm; - unsigned int msg_first; /* really struct target_msg* */ - unsigned int msg_last; /* really struct target_msg* */ - unsigned int msg_stime; /* really target_time_t */ - unsigned int msg_rtime; /* really target_time_t */ - unsigned int msg_ctime; /* really target_time_t */ - unsigned int wwait; /* really struct wait_queue* */ - unsigned int rwait; /* really struct wait_queue* */ - unsigned short msg_cbytes; - unsigned short msg_qnum; - unsigned short msg_qbytes; - unsigned short msg_lspid; - unsigned short msg_lrpid; -}; - -struct target_shmid_ds { - struct target_ipc_perm shm_perm; - int shm_segsz; - unsigned int shm_atime; /* really target_time_t */ - unsigned int shm_dtime; /* really target_time_t */ - unsigned int shm_ctime; /* really target_time_t */ - unsigned short shm_cpid; - unsigned short shm_lpid; - short
[Qemu-devel] [mips-linux-user] patch for struct stat mapping
The code that maps struct stat is wrong for MIPS. It uses the wrong sized calls (16 vs 32) for swapping some of the structure members. A patch to fix this is attached. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149Index: qemu/linux-user/syscall.c === --- qemu.orig/linux-user/syscall.c 2007-05-29 22:17:15.0 -0400 +++ qemu/linux-user/syscall.c 2007-05-29 22:18:16.0 -0400 @@ -3698,7 +3698,11 @@ lock_user_struct(target_st, arg2, 0); if( ret=page_check_range(target_st,sizeof(*target_st),PAGE_WRITE) ) return -ret; +#if defined(TARGET_MIPS) +target_st->st_dev = tswapl(st.st_dev); +#else target_st->st_dev = tswap16(st.st_dev); +#endif target_st->st_ino = tswapl(st.st_ino); #if defined(TARGET_PPC) || defined(TARGET_MIPS) target_st->st_mode = tswapl(st.st_mode); /* XXX: check this */ @@ -3709,8 +3713,14 @@ target_st->st_uid = tswap16(st.st_uid); target_st->st_gid = tswap16(st.st_gid); #endif +#if defined(TARGET_MIPS) + /* If this is the same on PPC, then just merge w/ the above ifdef */ +target_st->st_nlink = tswapl(st.st_nlink); +target_st->st_rdev = tswapl(st.st_rdev); +#else target_st->st_nlink = tswap16(st.st_nlink); target_st->st_rdev = tswap16(st.st_rdev); +#endif target_st->st_size = tswapl(st.st_size); target_st->st_blksize = tswapl(st.st_blksize); target_st->st_blocks = tswapl(st.st_blocks);
Re: [Qemu-devel] linux-user target
On Thu, 19 Apr 2007, J. Mayer wrote: > And I checked the code generated on my machine. > I got the repz at the end of the op_goto_tb0 and op_goto_tb1 and it > seems to work well here with the bash version I got. IIrc from yesterday, they ended up in front of lea instuctions, which I think always resulted in the same value being used, so no harm could be done. More digging last night, and this morning, and I have disovered that a 32-bit build from the x86 system that works fine on the 32-bit system will crash when run inside a 32-bit chroot on the x86_64 system (with the save version of libraries in the chroot as are on the 32-bit system). This suggests that there may be something in the execution environment that is causing the problem. I traced both runs, and am comparing the results. The first difference is where things get placed in the address space. Stuff that is at 0x5xxx on one is at 0x7xxx on the other. Same for 0xa and 0xfxxx. This doesn't seem to cause much of a problem becasue if I use a simple text substitution on the log files, the differences almost completely go away. At least that is true for the first 50,000 lines of the logs. Then, for some reason I haven't figured out yet, the two instances start executing different instructions inside the guest. I'll need to dig more to figure out it going on when that happens. Another test which might be interesting is to trade executables with someone that has a working build on an x86_64 system. The crash will either follow my executable to someone elses system or their perfectly good executables will start crashing on my system. I suspect it will be the latter, but it would be nice to confirm it. Note that I've had this system running under stress for quite a while now, including a lot of runtime w/ qemu-arm, so I'm pretty certain it isn't something mundane like bad RAM. Sigh... it saddens me to think of the improvements to the rest of linux-user that I could have finished in the amount of time I've spent on thhis one problem 8-(. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149
Re: [Qemu-devel] linux-user target
On Thu, 19 Apr 2007, Igor Kovalenko wrote: as discussed before, to do this in dyngen you need to know the context better or you'll skip more than intended; that amounts to moving a large bit of decoder there as far as I understand that Yes, it was a quick hack along w/ visual inspection of the results. I have since tried the -mtune=nocona change, and it still crashes. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149
Re: [Qemu-devel] linux-user target
On Wed, 18 Apr 2007, Igor Kovalenko wrote: This should be solved for x86_64 host with "-mtune=nocona" patch posted a while ago. I'll go dig that up. The problem is with dyngen being confused by "repz retq" sequence. That's what caught my attention earlier today. It was only showing up in two places in the generated code. I fixed it by hand by tweaking dyngen to skip the repz as well as the retq, but I still got the crash. It is of course possible that I'm seeing multiple crashes and not recognizing when I have actually fixed something. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149
Re: [Qemu-devel] linux-user target
On Wed, 18 Apr 2007, J. Mayer wrote: You're right: I think all TLS specific code is located in the glibc. In my last tracing through qemu.log, I did check for r2 references, and there was one store near the beginning that looked like what glibc would do (r2 = ptr+0x700), and the rest of the access were reads of r2. It may be related to some of the library versions installed in your 64 bits environment that would not be the same as the one used in the 32 bits environment. Both are current Debian etch systems, a real x86_64, and a real x86. Both are running the same library versions. ii libc6 2.3.6.ds1-13 GNU C Library: Shared libraries One important precision that may make a big difference: I always use gcc 3.4 to compile because I know several gcc 4.x bugs (crash during ISO C compliant code and/or incorrect generated asm instructions), then I do not consider gcc 4.x as usable for a production environment today. I'm using gcc-3.4 as well. ii gcc-3.43.4.6-5 The GNU C compiler ii gcc-3.4-base 3.4.6-5 The GNU Compiler Collection (base package) Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149
Re: [Qemu-devel] [PATCH] PPC termios structure ordering
On Wed, 18 Apr 2007, J. Mayer wrote: With this change, both host and target 'stty -a' give the same output. Thanks. I'll take a better look to this patch then apply. There maybe the same issue in the ppc64 strucutre ? Yes, it looks like the same changes it needed in linux-user/ppc64/termbits.h as well. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149
Re: [Qemu-devel] linux-user target
On Tue, 17 Apr 2007, Stuart Anderson wrote: I've continued to work on this all week, and I still haven't managed to solve it. I've chased down a lot of paths, but none of them have lead to a solution. Here is a summary of the situation now. * programs other than bash will run * bash --version will run * bash --noediting will run * occasionally, bash has run if I'm stracing it, but I can't always reproduce it. * when it runs, I occasionally see some odd behavior, but not always. The termios patch I just sent cleared up a lot of the oddness. * when it runs, it hangs on exit. Killing it logs me all the way out of the system (ssh conection). * when it crashes, gdb looses the user level thread, so I can't do any debugging * I don't see any of the TLS related system calls being called. I also don't see any concrete proof one way or another that it is used in the executable (ie No R_PPC_*TLS relocations). I've been digging in the kernel & glibc source, and I don't see a lot of special code to support TLS on ppc. It mostly seems to be just taking care to not step on R2. Glibc seems to be the only place where it knows something specific about TLS, which leads me to think that TLS is mostly contain within the userspace on PPC. * I've tried turning on most of the DEBUG_ defines under linux-user, but none of them has yielded anything useful, or noteworthy. This morning, I went back and tried a 32-bit x86 host (instead of the x86_64 host), and discovered that everything works just fine. This makes me think it's a 64 bit issue, so I took a closer look at the build warnings that exist on x86_64 but not on x86. This pointed to PPC_OP(goto_tb0) & PPC_OP(goto_tb1) in target-ppc/op.c. It appears that x86_64 is using the generic portable code, but one of the fields that it is taking as a pointer (tb_next) is only an int. Changing it to a ulong didn't fix things though, but it did eliminate the warning. After more digging in the qemu.log, I noticed this difference that is related to those two functions (op_goto_tb0 & op_goto_tb1). On x86: 0ebf : ebf: e9 fc ff ff ff jmpec0 ec4: c3 ret 0ec5 : ec5: e9 fc ff ff ff jmpec6 eca: c3 ret On x86_64: 154e : 154e: 8b 05 00 00 00 00 mov0(%rip),%eax 1554: ff e0 jmpq *%rax 1556: f3 c3 repz retq 1558 : 1558: 8b 05 00 00 00 00 mov0(%rip),%eax 155e: ff e0 jmpq *%rax 1560: f3 c3 repz retq Note repz before retq which is not in x86 code or in any other x86_64 op. In use the micro ops are: 0x000d: goto_tb1 0x60233800 0x000e: set_T1 0x100a4df8 0x000f: b_T1 For which the generated code becomes 0x61a5998d: mov-25321811(%rip),%eax# 0x60233840 0x61a59993: jmpq *%eax 0x61a59995: repz lea -1369131941(%rip),%r12d# 0x100a4df8 0x61a5999d: mov%r12d,%eax 0x61a599a0: and$0xfffc,%eax 0x61a599a3: mov%eax,0xc7f4(%r14) 0x61a599aa: lea-25321904(%rip),%r15d# 0x60233801 0x61a599b1: retq The repz is still there from the goto_tb1 OP, but is now applied to the lea isn from the set_T1 op. Is this correct? Would it cause any kind of a problem? Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149
Re: [Qemu-devel] [PATCH] semaphore syscalls - refresh
Thiemo, Just wondering if you had a chance to take another look at this. On Sat, 31 Mar 2007, Stuart Anderson wrote: On Sat, 31 Mar 2007, Thiemo Seufer wrote: +switch( cmd ) { + case GETALL: + case SETALL: + case IPC_STAT: + case IPC_SET: + lock_user_struct(target_su, target_addr, 1); + target_to_host_semid_ds(ds,target_su->buf); + host_su->buf = ds; + unlock_user_struct(target_su, target_addr, 0); + break; I don't see how this can work with target_su being an uninitialized pointer. #define lock_user_struct(host_ptr, guest_addr, copy) \ host_ptr = lock_user(guest_addr, sizeof(*host_ptr), copy) target_su is the left hand side of the assignment. The macro just hides it. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149
Re: [Qemu-devel] linux-user target
On Tue, 10 Apr 2007, Jocelyn Mayer wrote: PPC: I am unable to get any executable to run. projects:~/upstream/qemu# ./ppc-linux-user/qemu-ppc -L /mirror0/chroots/ppc/ /mirror0/chroots/ppc/bin/bash init_ppc_proc: PVR 0008 mask => 0008 Segmentation fault projects:~/upstream/qemu# Just checked, on an amd64 host with a random powerpc bash version I got on my hard disk drive: ./ppc-linux-user/qemu-ppc -L /mnt/local/hdc/part3/PPC/linux/archives /mnt/local/hdc/part3/PPC/linux/archives/bin/bash --version init_ppc_proc: PVR 0008 mask => 0008 GNU bash, version 2.05a.0(1)-release (powerpc-unknown-linux-gnu) Copyright 2001 Free Software Foundation, Inc. I also tried to really launch the shell and use it and it worked. ... I have to admit there are some strange behaviors with some features... But I think recent builds using glibc with TLS/NPTL would not run. I've continued to work on this all week, and I still haven't managed to solve it. I've chased down a lot of paths, but none of them have lead to a solution. Here is a summary of the situation now. * programs other than bash will run * bash --version will run * bash --noediting will run * occasionally, bash has run if I'm stracing it, but I can't always reproduce it. * when it runs, I occasionally see some odd behavior, but not always. The termios patch I just sent cleared up a lot of the oddness. * when it runs, it hangs on exit. Killing it logs me all the way out of the system (ssh conection). * when it crashes, gdb looses the user level thread, so I can't do any debugging * I don't see any of the TLS related system calls being called. I also don't see any concrete proof one way or another that it is used in the executable (ie No R_PPC_*TLS relocations). I've been digging in the kernel & glibc source, and I don't see a lot of special code to support TLS on ppc. It mostly seems to be just taking care to not step on R2. Glibc seems to be the only place where it knows something specific about TLS, which leads me to think that TLS is mostly contain within the userspace on PPC. * I've tried turning on most of the DEBUG_ defines under linux-user, but none of them has yielded anything useful, or noteworthy. Whew.. I'm in need a of a fresh idea or three. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149
[Qemu-devel] [PATCH] PPC termios structure ordering
Just found a small problem w/ the termios structure as defined for PPC linux user. It doesn't match the one in include/asm-powerpc/termbits.h. Index: linux-user/ppc/termbits.h === --- linux-user/ppc/termbits.h (revision 44) +++ linux-user/ppc/termbits.h (working copy) @@ -7,8 +7,8 @@ unsigned int c_oflag; /* output mode flags */ unsigned int c_cflag; /* control mode flags */ unsigned int c_lflag; /* local mode flags */ +unsigned char c_cc[TARGET_NCCS];/* control characters */ unsigned char c_line;/* line discipline */ -unsigned char c_cc[TARGET_NCCS];/* control characters */ unsigned int c_ispeed; /* input speed */ unsigned int c_ospeed; /* output speed */ }; With this change, both host and target 'stty -a' give the same output. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149
Re: [Qemu-devel] linux-user target
On Tue, 10 Apr 2007, Jocelyn Mayer wrote: > Just checked, on an amd64 host with a random powerpc bash version I got > on my hard disk drive: > > I also tried to really launch the shell and use it and it worked. Interesting... > But I think recent builds using glibc with TLS/NPTL would not run. Ahh. that's probably it. The executables I'm using are build with libc-2.3.6. > If this can help. Indeed, it has probably narrowed the search space considerably. Thanks. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149
[Qemu-devel] (no subject)
I'm trying to test my fixes to the linux-user emulation on some additonal architectures now, but I'm running into problems. I can debug these some, but any suggestions or guidence, especially from people more familiar with the architecture core code, would be appreciated. The environment is a Debian x86_64 server running Etch, with target environments built using debootstrap. MIPS: Bash seems to start up ok, but when I run a command in it, it hangs until I hit return a second time, and then bash exits w/ an uncaught target signal. projects:~/upstream/qemu# mips-linux-user/qemu-mips -L /mirror0/chroots/mips/ /mirror0/chroots/mips/bin/bash projects:~/upstream/qemu# ps PID TTY TIME CMD 18786 pts/100:00:00 bash 20057 pts/100:00:00 ps 20058 pts/100:00:00 qemu-mips qemu: uncaught target signal 25 (Continued) - exiting projects:~/upstream/qemu# PPC: I am unable to get any executable to run. projects:~/upstream/qemu# ./ppc-linux-user/qemu-ppc -L /mirror0/chroots/ppc/ /mirror0/chroots/ppc/bin/bash init_ppc_proc: PVR 0008 mask => 0008 Segmentation fault projects:~/upstream/qemu# Thanks, Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149
Re: [Qemu-devel] [PATCH] clone syscall fix
On Sat, 31 Mar 2007, Thiemo Seufer wrote: Stuart Anderson wrote: Even though clone() and fork() are related, they don't seem to be close enough to allow a single routine to be used to implement both. With this patch, the LTP tests for clone now pass. But it still does the same, assuming VM_CLONE is set, except for passing additional arguments to the host call. I'm not so sure that the VM_CLONE flag should control wether the new stack is set up or not. There are tests for newsp == NULL inside that block anyway. The LTP certainly tests combination for which the do_fork() code doesn't work. Passing untranslated regs looks like a bug to me, I'm unsure about the tls_val. Hmm, could be, but that's the way it is in the current code. I think more testing on additional combination sof target &host will be needed. It may be possible to fold this back into do_fork(), but this just seemed to be a little bit more straightforward. Since Linux's fork() is just a specialcase of clone() this should be done eventually. I'll try just dropping do_fork completely, and see if this new do_clone() works for the fork case also. If so, then that effectively folds the changes back into do_fork(), and more closely resembles that non-emulated case of fork() being implemnted on top of clone( anyway. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149
Re: [Qemu-devel] [PATCH] semaphore syscalls - refresh
On Sat, 31 Mar 2007, Thiemo Seufer wrote: +switch( cmd ) { + case GETALL: + case SETALL: + case IPC_STAT: + case IPC_SET: + lock_user_struct(target_su, target_addr, 1); + target_to_host_semid_ds(ds,target_su->buf); + host_su->buf = ds; + unlock_user_struct(target_su, target_addr, 0); + break; I don't see how this can work with target_su being an uninitialized pointer. #define lock_user_struct(host_ptr, guest_addr, copy) \ host_ptr = lock_user(guest_addr, sizeof(*host_ptr), copy) target_su is the left hand side of the assignment. The macro just hides it. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149
[Qemu-devel] [PATCH] EFAULT refresh
Here is a refresh of the EFAULT patch. This fixes a lot of crashes in LTP, and presumably in regular applications too. This still needs to have the checking foldded into lock_user(), but there were a handful of small fixes since this patch was last sent out. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149Index: qemu/exec.c === --- qemu.orig/exec.c 2007-03-26 11:18:49.0 -0400 +++ qemu/exec.c 2007-03-26 11:20:06.0 -0400 @@ -1785,6 +1785,29 @@ spin_unlock(&tb_lock); } +int page_check_range(target_ulong start, target_ulong len, int flags) +{ +PageDesc *p; +target_ulong end; +target_ulong addr; + +end = TARGET_PAGE_ALIGN(start+len); /* must do before we loose bits in the next step */ +start = start & TARGET_PAGE_MASK; + +if( end < start ) return EFAULT; /* we've wrapped around */ +for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) { +p = page_find(addr >> TARGET_PAGE_BITS); + if( !p ) return EFAULT; + if( !(p->flags & PAGE_VALID) ) return EFAULT; + +if (!(p->flags & PAGE_READ) && +(flags & PAGE_READ) ) return EFAULT; +if (!(p->flags & PAGE_WRITE) && +(flags & PAGE_WRITE) ) return EFAULT; +} +return 0; +} + /* called from signal handler: invalidate the code and unprotect the page. Return TRUE if the fault was succesfully handled. */ int page_unprotect(target_ulong address, unsigned long pc, void *puc) Index: qemu/cpu-all.h === --- qemu.orig/cpu-all.h 2007-03-26 11:18:49.0 -0400 +++ qemu/cpu-all.h 2007-03-26 11:20:06.0 -0400 @@ -689,6 +689,7 @@ int page_get_flags(target_ulong address); void page_set_flags(target_ulong start, target_ulong end, int flags); void page_unprotect_range(target_ulong data, target_ulong data_size); +int page_check_range(target_ulong start, target_ulong len, int flags); #define SINGLE_CPU_DEFINES #ifdef SINGLE_CPU_DEFINES Index: qemu/linux-user/syscall.c === --- qemu.orig/linux-user/syscall.c 2007-03-26 11:20:05.0 -0400 +++ qemu/linux-user/syscall.c 2007-03-26 14:11:21.0 -0400 @@ -406,28 +406,36 @@ return ret; } -static inline void target_to_host_sockaddr(struct sockaddr *addr, +static inline long target_to_host_sockaddr(struct sockaddr *addr, target_ulong target_addr, - socklen_t len) + socklen_t len, + int pg_access) { +long ret = 0; struct target_sockaddr *target_saddr; target_saddr = lock_user(target_addr, len, 1); +if( ret=page_check_range(target_saddr,len,pg_access) ) return ret; memcpy(addr, target_saddr, len); addr->sa_family = tswap16(target_saddr->sa_family); unlock_user(target_saddr, target_addr, 0); +return ret; } -static inline void host_to_target_sockaddr(target_ulong target_addr, +static inline long host_to_target_sockaddr(target_ulong target_addr, struct sockaddr *addr, - socklen_t len) + socklen_t len, + int pg_access) { +long ret = 0; struct target_sockaddr *target_saddr; target_saddr = lock_user(target_addr, len, 0); +if( ret=page_check_range(target_saddr,len,pg_access) ) return ret; memcpy(target_saddr, addr, len); target_saddr->sa_family = tswap16(addr->sa_family); unlock_user(target_saddr, target_addr, len); +return ret; } /* ??? Should this also swap msgh->name? */ @@ -788,18 +796,20 @@ static long do_bind(int sockfd, target_ulong target_addr, socklen_t addrlen) { +long ret = 0; void *addr = alloca(addrlen); -target_to_host_sockaddr(addr, target_addr, addrlen); +if( ret=target_to_host_sockaddr(addr, target_addr, addrlen,PAGE_READ) ) return -ret; return get_errno(bind(sockfd, addr, addrlen)); } static long do_connect(int sockfd, target_ulong target_addr, socklen_t addrlen) { +long ret = 0; void *addr = alloca(addrlen); -target_to_host_sockaddr(addr, target_addr, addrlen); +if( ret=target_to_host_sockaddr(addr, target_addr, addrlen,PAGE_READ) ) return -ret; return get_errno(connect(sockfd, addr, addrlen)); } @@ -814,11 +824,19 @@ target_ulong target_vec; lock_user_struct(msgp, target_msg, 1); +if
[Qemu-devel] [PATCH] signal syscall fixes
This patch fixes a couple of problems with signals(). The first fix, in cpu-exec.c, is needed for the case where a process does a kill(SIGSEGV) on itself (as is done in a test suite). This fix for ARM is similar to what is done for some of the other architectures. I'm not 100% certain this is the best fix, but it does yield the right results when running the test suite. The second fix is simple. sigaction() is supposed to fail if SIGKILL or SIGSTOP is passed in. Those signals may not be blocked or ignored. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149Index: qemu/cpu-exec.c === --- qemu.orig/cpu-exec.c 2007-03-26 13:51:50.0 -0400 +++ qemu/cpu-exec.c 2007-03-26 13:52:21.0 -0400 @@ -952,10 +952,15 @@ a virtual CPU fault */ cpu_restore_state(tb, env, pc, puc); } +if( ret == 1 ) { +sigprocmask(SIG_SETMASK, old_set, NULL); +//raise_exception_err(env->exception_index, env->error_code); +} else { /* we restore the process signal mask as the sigreturn should do it (XXX: use sigsetjmp) */ sigprocmask(SIG_SETMASK, old_set, NULL); cpu_loop_exit(); +} } #elif defined(TARGET_SPARC) static inline int handle_cpu_signal(unsigned long pc, unsigned long address, Index: qemu/linux-user/signal.c === --- qemu.orig/linux-user/signal.c 2007-03-26 13:51:50.0 -0400 +++ qemu/linux-user/signal.c 2007-03-26 13:52:21.0 -0400 @@ -422,7 +422,7 @@ struct sigaction act1; int host_sig; -if (sig < 1 || sig > TARGET_NSIG) +if (sig < 1 || sig > TARGET_NSIG || sig == SIGKILL || sig == SIGSTOP) return -EINVAL; k = &sigact_table[sig - 1]; #if defined(DEBUG_SIGNAL)
[Qemu-devel] [PATCH] clone syscall fix
Even though clone() and fork() are related, they don't seem to be close enough to allow a single routine to be used to implement both. With this patch, the LTP tests for clone now pass. It may be possible to fold this back into do_fork(), but this just seemed to be a little bit more straightforward. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149Index: qemu/linux-user/syscall.c === --- qemu.orig/linux-user/syscall.c 2007-03-26 11:20:06.0 -0400 +++ qemu/linux-user/syscall.c 2007-03-26 11:28:01.0 -0400 @@ -2088,6 +2088,75 @@ return 0; } +int do_clone(CPUState *env, unsigned int flags, unsigned long newsp, + unsigned long parent_tidptr, unsigned long tls_val, + unsigned long child_tidptr, unsigned long regs) +{ +int ret; +TaskState *ts = NULL; +uint8_t *new_stack; +CPUState *new_env; + +ts = malloc(sizeof(TaskState) + NEW_STACK_SIZE); +memset(ts, 0, sizeof(TaskState)); +new_stack = ts->stack; +ts->used = 1; +/* add in task state list */ +ts->next = first_task_state; +first_task_state = ts; +/* we create a new CPU instance. */ +new_env = cpu_copy(env); +#if defined(TARGET_I386) +if (!newsp) +newsp = env->regs[R_ESP]; +new_env->regs[R_ESP] = newsp; +new_env->regs[R_EAX] = 0; +#elif defined(TARGET_ARM) +if (!newsp) +newsp = env->regs[13]; +new_env->regs[13] = newsp; +new_env->regs[0] = 0; +#elif defined(TARGET_SPARC) +if (!newsp) +newsp = env->regwptr[22]; +new_env->regwptr[22] = newsp; +new_env->regwptr[0] = 0; + /* X */ +printf ("HELPME: %s:%d\n", __FILE__, __LINE__); +#elif defined(TARGET_M68K) +if (!newsp) +newsp = env->aregs[7]; +new_env->aregs[7] = newsp; +new_env->dregs[0] = 0; +/* ??? is this sufficient? */ +#elif defined(TARGET_MIPS) +printf ("HELPME: %s:%d\n", __FILE__, __LINE__); +#elif defined(TARGET_PPC) +if (!newsp) +newsp = env->gpr[1]; +new_env->gpr[1] = newsp; +{ +int i; +for (i = 7; i < 32; i++) +new_env->gpr[i] = 0; +} +#elif defined(TARGET_SH4) + if (!newsp) + newsp = env->gregs[15]; + new_env->gregs[15] = newsp; + /* X */ +#else +#error unsupported target CPU +#endif +new_env->opaque = ts; +#ifdef __ia64__ +ret = __clone2(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env); +#else + ret = clone(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env); +#endif +return ret; +} + int do_fork(CPUState *env, unsigned int flags, unsigned long newsp) { int ret; @@ -3529,7 +3598,7 @@ ret = get_errno(fsync(arg1)); break; case TARGET_NR_clone: -ret = get_errno(do_fork(cpu_env, arg1, arg2)); +ret = get_errno(do_clone(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6)); break; #ifdef __NR_exit_group /* new thread calls */
[Qemu-devel] [PATCH] message queue fixes - refresh
Here is a refresh of the message queue syscall (msg*()) fixes. These are analgous to the just posted sempahore fixes. Tested with LTP on the target. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149Index: qemu/linux-user/syscall.c === --- qemu.orig/linux-user/syscall.c 2007-03-23 09:06:14.0 -0400 +++ qemu/linux-user/syscall.c 2007-03-23 09:06:16.0 -0400 @@ -1322,6 +1322,117 @@ return ret; } +struct target_msqid_ds +{ + struct target_ipc_perm msg_perm; + target_ulong msg_stime; + target_ulong __unused1; + target_ulong msg_rtime; + target_ulong __unused2; + target_ulong msg_ctime; + target_ulong __unused3; + target_ulong __msg_cbytes; + target_ulong msg_qnum; + target_ulong msg_qbytes; + target_ulong msg_lspid; + target_ulong msg_lrpid; + target_ulong __unused4; + target_ulong __unused5; +}; + +static inline void target_to_host_msqid_ds(struct msqid_ds *host_md, + target_ulong target_addr) +{ +struct target_msqid_ds *target_md; + +lock_user_struct(target_md, target_addr, 1); +target_to_host_ipc_perm(&(host_md->msg_perm),target_addr); +host_md->msg_stime = tswapl(target_md->msg_stime); +host_md->msg_rtime = tswapl(target_md->msg_rtime); +host_md->msg_ctime = tswapl(target_md->msg_ctime); +host_md->__msg_cbytes = tswapl(target_md->__msg_cbytes); +host_md->msg_qnum = tswapl(target_md->msg_qnum); +host_md->msg_qbytes = tswapl(target_md->msg_qbytes); +host_md->msg_lspid = tswapl(target_md->msg_lspid); +host_md->msg_lrpid = tswapl(target_md->msg_lrpid); +unlock_user_struct(target_md, target_addr, 0); +} + +static inline void host_to_target_msqid_ds(target_ulong target_addr, + struct msqid_ds *host_md) +{ +struct target_msqid_ds *target_md; + +lock_user_struct(target_md, target_addr, 0); +host_to_target_ipc_perm(target_addr,&(host_md->msg_perm)); +target_md->msg_stime = tswapl(host_md->msg_stime); +target_md->msg_rtime = tswapl(host_md->msg_rtime); +target_md->msg_ctime = tswapl(host_md->msg_ctime); +target_md->__msg_cbytes = tswapl(host_md->__msg_cbytes); +target_md->msg_qnum = tswapl(host_md->msg_qnum); +target_md->msg_qbytes = tswapl(host_md->msg_qbytes); +target_md->msg_lspid = tswapl(host_md->msg_lspid); +target_md->msg_lrpid = tswapl(host_md->msg_lrpid); +unlock_user_struct(target_md, target_addr, 1); +} + +static inline long do_msgctl(long first, long second, long ptr) +{ +struct msqid_ds dsarg; +int cmd = second&0xff; +long ret = 0; +switch( cmd ) { +case IPC_STAT: +case IPC_SET: +target_to_host_msqid_ds(&dsarg,ptr); +ret = get_errno(msgctl(first, cmd, &dsarg)); +host_to_target_msqid_ds(ptr,&dsarg); +default: +ret = get_errno(msgctl(first, cmd, &dsarg)); +} +return ret; +} + +struct target_msgbuf { + target_ulong mtype; + char mtext[1]; +}; + +static inline long do_msgsnd(long msqid, long msgp, long msgsz, long msgflg) +{ +struct target_msgbuf *target_mb; +struct msgbuf *host_mb; +long ret = 0; + +lock_user_struct(target_mb,msgp,0); +host_mb = malloc(msgsz+sizeof(long)); +host_mb->mtype = tswapl(target_mb->mtype); +memcpy(host_mb->mtext,target_mb->mtext,msgsz); +ret = get_errno(msgsnd(msqid, host_mb, msgsz, msgflg)); +free(host_mb); +unlock_user_struct(target_mb, msgp, 0); + +return ret; +} + +static inline long do_msgrcv(long msqid, long msgp, long msgsz, long msgtype, long msgflg) +{ +struct target_msgbuf *target_mb; +struct msgbuf *host_mb; +long ret = 0; + +lock_user_struct(target_mb,msgp,0); +host_mb = malloc(msgsz+sizeof(long)); +ret = get_errno(msgrcv(msqid, host_mb, msgsz, 1, msgflg)); +if( ret > 0 ) + memcpy(target_mb->mtext,host_mb->mtext,ret); +target_mb->mtype = tswapl(host_mb->mtype); +free(host_mb); +unlock_user_struct(target_mb, msgp, 0); + +return ret; +} + /* ??? This only works with linear mappings. */ static long do_ipc(long call, long first, long second, long third, long ptr, long fifth) @@ -1358,27 +1469,27 @@ break; case IPCOP_msgsnd: - ret = get_errno(msgsnd(first, (struct msgbuf *) ptr, second, third)); + ret = do_msgsnd(first, ptr, second, third); break; case IPCOP_msgctl: - ret = get_errno(msgctl(first, second, (struct msqid_ds *) ptr)); + ret = do_msgctl(first, second, ptr); break; case IPCOP_msgrcv: - { - struct ipc_kludge - { -void *__unbounded msgp; -long int msgtyp; - }; +{ +
[Qemu-devel] [PATCH] fcntl() remaining fix
There is still one bit left after the last fcntl() fix went in. For TARGET_F_GETLK and TARGET_F_GETLK64, the structure being passed *in* needs to be mapped from target to host. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149Index: qemu/linux-user/syscall.c === --- qemu.orig/linux-user/syscall.c 2007-03-23 09:06:00.0 -0400 +++ qemu/linux-user/syscall.c 2007-03-23 09:06:06.0 -0400 @@ -1985,6 +1985,13 @@ switch(cmd) { case TARGET_F_GETLK: +lock_user_struct(target_fl, arg, 1); +fl.l_type = tswap16(target_fl->l_type); +fl.l_whence = tswap16(target_fl->l_whence); +fl.l_start = tswapl(target_fl->l_start); +fl.l_len = tswapl(target_fl->l_len); +fl.l_pid = tswapl(target_fl->l_pid); +unlock_user_struct(target_fl, arg, 0); ret = fcntl(fd, cmd, &fl); if (ret == 0) { lock_user_struct(target_fl, arg, 0); @@ -2010,6 +2017,13 @@ break; case TARGET_F_GETLK64: +lock_user_struct(target_fl64, arg, 1); +fl64.l_type = tswap16(target_fl64->l_type) >> 1; +fl64.l_whence = tswap16(target_fl64->l_whence); +fl64.l_start = tswapl(target_fl64->l_start); +fl64.l_len = tswapl(target_fl64->l_len); +fl64.l_pid = tswap16(target_fl64->l_pid); +unlock_user_struct(target_fl64, arg, 0); ret = fcntl(fd, cmd >> 1, &fl64); if (ret == 0) { lock_user_struct(target_fl64, arg, 0); @@ -4088,6 +4102,26 @@ switch(arg2) { case TARGET_F_GETLK64: +#ifdef TARGET_ARM +if (((CPUARMState *)cpu_env)->eabi) { +lock_user_struct(target_efl, arg3, 1); +fl.l_type = tswap16(target_efl->l_type); +fl.l_whence = tswap16(target_efl->l_whence); +fl.l_start = tswap64(target_efl->l_start); +fl.l_len = tswap64(target_efl->l_len); +fl.l_pid = tswapl(target_efl->l_pid); +unlock_user_struct(target_efl, arg3, 0); +} else +#endif +{ +lock_user_struct(target_fl, arg3, 1); +fl.l_type = tswap16(target_fl->l_type); +fl.l_whence = tswap16(target_fl->l_whence); +fl.l_start = tswap64(target_fl->l_start); +fl.l_len = tswap64(target_fl->l_len); +fl.l_pid = tswapl(target_fl->l_pid); +unlock_user_struct(target_fl, arg3, 0); +} ret = get_errno(fcntl(arg1, cmd, &fl)); if (ret == 0) { #ifdef TARGET_ARM
[Qemu-devel] [PATCH] semaphore syscalls - refresh
This is a refresh of a prior patch to fix the semaphore system calls sem*() in user-linux mode. Some additional cases have been dealt with, and a small amount of code re-arrainging to prepare for the EFAULT patch. Tested using Linux Test Project in the target. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149Index: qemu/linux-user/i386/syscall.h === --- qemu.orig/linux-user/i386/syscall.h 2007-03-23 09:05:19.0 -0400 +++ qemu/linux-user/i386/syscall.h 2007-03-23 09:05:32.0 -0400 @@ -142,80 +142,4 @@ struct target_vm86plus_info_struct vm86plus; }; -/* ipcs */ - -#define TARGET_SEMOP 1 -#define TARGET_SEMGET 2 -#define TARGET_SEMCTL 3 -#define TARGET_MSGSND 11 -#define TARGET_MSGRCV 12 -#define TARGET_MSGGET 13 -#define TARGET_MSGCTL 14 -#define TARGET_SHMAT 21 -#define TARGET_SHMDT 22 -#define TARGET_SHMGET 23 -#define TARGET_SHMCTL 24 - -struct target_msgbuf { - int mtype; - char mtext[1]; -}; - -struct target_ipc_kludge { - unsigned int msgp; /* Really (struct msgbuf *) */ - int msgtyp; -}; - -struct target_ipc_perm { - int key; - unsigned short uid; - unsigned short gid; - unsigned short cuid; - unsigned short cgid; - unsigned short mode; - unsigned short seq; -}; - -struct target_msqid_ds { - struct target_ipc_perm msg_perm; - unsigned int msg_first; /* really struct target_msg* */ - unsigned int msg_last; /* really struct target_msg* */ - unsigned int msg_stime; /* really target_time_t */ - unsigned int msg_rtime; /* really target_time_t */ - unsigned int msg_ctime; /* really target_time_t */ - unsigned int wwait; /* really struct wait_queue* */ - unsigned int rwait; /* really struct wait_queue* */ - unsigned short msg_cbytes; - unsigned short msg_qnum; - unsigned short msg_qbytes; - unsigned short msg_lspid; - unsigned short msg_lrpid; -}; - -struct target_shmid_ds { - struct target_ipc_perm shm_perm; - int shm_segsz; - unsigned int shm_atime; /* really target_time_t */ - unsigned int shm_dtime; /* really target_time_t */ - unsigned int shm_ctime; /* really target_time_t */ - unsigned short shm_cpid; - unsigned short shm_lpid; - short shm_nattch; - unsigned short shm_npages; - unsigned long *shm_pages; - void *attaches; /* really struct shm_desc * */ -}; - -#define TARGET_IPC_RMID 0 -#define TARGET_IPC_SET 1 -#define TARGET_IPC_STAT 2 - -union target_semun { -int val; -unsigned int buf; /* really struct semid_ds * */ -unsigned int array; /* really unsigned short * */ -unsigned int __buf; /* really struct seminfo * */ -unsigned int __pad; /* really void* */ -}; - #define UNAME_MACHINE "i686" Index: qemu/linux-user/ppc/syscall.h === --- qemu.orig/linux-user/ppc/syscall.h 2007-03-23 09:05:19.0 -0400 +++ qemu/linux-user/ppc/syscall.h 2007-03-23 09:05:32.0 -0400 @@ -51,80 +51,4 @@ * flags masks */ -/* ipcs */ - -#define TARGET_SEMOP 1 -#define TARGET_SEMGET 2 -#define TARGET_SEMCTL 3 -#define TARGET_MSGSND 11 -#define TARGET_MSGRCV 12 -#define TARGET_MSGGET 13 -#define TARGET_MSGCTL 14 -#define TARGET_SHMAT 21 -#define TARGET_SHMDT 22 -#define TARGET_SHMGET 23 -#define TARGET_SHMCTL 24 - -struct target_msgbuf { - int mtype; - char mtext[1]; -}; - -struct target_ipc_kludge { - unsigned int msgp; /* Really (struct msgbuf *) */ - int msgtyp; -}; - -struct target_ipc_perm { - int key; - unsigned short uid; - unsigned short gid; - unsigned short cuid; - unsigned short cgid; - unsigned short mode; - unsigned short seq; -}; - -struct target_msqid_ds { - struct target_ipc_perm msg_perm; - unsigned int msg_first; /* really struct target_msg* */ - unsigned int msg_last; /* really struct target_msg* */ - unsigned int msg_stime; /* really target_time_t */ - unsigned int msg_rtime; /* really target_time_t */ - unsigned int msg_ctime; /* really target_time_t */ - unsigned int wwait; /* really struct wait_queue* */ - unsigned int rwait; /* really struct wait_queue* */ - unsigned short msg_cbytes; - unsigned short msg_qnum; - unsigned short msg_qbytes; - unsigned short msg_lspid; - unsigned short msg_lrpid; -}; - -struct target_shmid_ds { - struct target_ipc_perm shm_perm; - int shm_segsz; - unsigned int shm_atime; /* really target_time_t */ - unsigned int shm_dtime; /* really target_time_t */ - unsigned int shm_ctime; /* really target_time_t */ - unsigned short shm_cpid; - unsigned short shm_lpid; - s
Re: [Qemu-devel] generating EFAULT in linux-user
Here is an updated patch that show more of the changes that are needed to detect EFAULT situations in linux-user. The areas I focused on are the socket, semaphore, and message queue family of syscalls as they all make interesting use of pointers to structures. This patch does sit on top of the other patches I sent to this list this week for semaphores and message queues, so it can't be 'test driven' without them. With this patch, more of the Linux Test Project test suite is able to PASS, and qemu SEGVs less frequently. Still to be done is to actually fold this into lock_user(), and finish applying it in the other applicable syscalls. Comments would be appreciated. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149Index: qemu/exec.c === --- qemu.orig/exec.c 2007-03-23 09:05:45.0 -0400 +++ qemu/exec.c 2007-03-23 09:06:23.0 -0400 @@ -1785,6 +1785,29 @@ spin_unlock(&tb_lock); } +int page_check_range(target_ulong start, target_ulong len, int flags) +{ +PageDesc *p; +target_ulong end; +target_ulong addr; + +end = TARGET_PAGE_ALIGN(start+len); /* must do before we loose bits in the next step */ +start = start & TARGET_PAGE_MASK; + +if( end < start ) return EFAULT; /* we've wrapped around */ +for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) { +p = page_find(addr >> TARGET_PAGE_BITS); + if( !p ) return EFAULT; + if( !(p->flags & PAGE_VALID) ) return EFAULT; + +if (!(p->flags & PAGE_READ) && +(flags & PAGE_READ) ) return EFAULT; +if (!(p->flags & PAGE_WRITE) && +(flags & PAGE_WRITE) ) return EFAULT; +} +return 0; +} + /* called from signal handler: invalidate the code and unprotect the page. Return TRUE if the fault was succesfully handled. */ int page_unprotect(target_ulong address, unsigned long pc, void *puc) Index: qemu/cpu-all.h === --- qemu.orig/cpu-all.h 2007-03-23 09:05:45.0 -0400 +++ qemu/cpu-all.h 2007-03-23 10:52:16.0 -0400 @@ -689,6 +689,7 @@ int page_get_flags(target_ulong address); void page_set_flags(target_ulong start, target_ulong end, int flags); void page_unprotect_range(target_ulong data, target_ulong data_size); +int page_check_range(target_ulong start, target_ulong len, int flags); #define SINGLE_CPU_DEFINES #ifdef SINGLE_CPU_DEFINES Index: qemu/linux-user/syscall.c === --- qemu.orig/linux-user/syscall.c 2007-03-23 09:06:16.0 -0400 +++ qemu/linux-user/syscall.c 2007-03-23 10:55:01.0 -0400 @@ -406,28 +406,36 @@ return ret; } -static inline void target_to_host_sockaddr(struct sockaddr *addr, +static inline long target_to_host_sockaddr(struct sockaddr *addr, target_ulong target_addr, - socklen_t len) + socklen_t len, + int pg_access) { +long ret = 0; struct target_sockaddr *target_saddr; target_saddr = lock_user(target_addr, len, 1); +if( ret=page_check_range(target_saddr,len,pg_access) ) return ret; memcpy(addr, target_saddr, len); addr->sa_family = tswap16(target_saddr->sa_family); unlock_user(target_saddr, target_addr, 0); +return ret; } -static inline void host_to_target_sockaddr(target_ulong target_addr, +static inline long host_to_target_sockaddr(target_ulong target_addr, struct sockaddr *addr, - socklen_t len) + socklen_t len, + int pg_access) { +long ret = 0; struct target_sockaddr *target_saddr; target_saddr = lock_user(target_addr, len, 0); +if( ret=page_check_range(target_saddr,len,pg_access) ) return ret; memcpy(target_saddr, addr, len); target_saddr->sa_family = tswap16(addr->sa_family); unlock_user(target_saddr, target_addr, len); +return ret; } /* ??? Should this also swap msgh->name? */ @@ -788,18 +796,20 @@ static long do_bind(int sockfd, target_ulong target_addr, socklen_t addrlen) { +long ret = 0; void *addr = alloca(addrlen); -target_to_host_sockaddr(addr, target_addr, addrlen); +if( ret=target_to_host_sockaddr(addr, target_addr, addrlen,PAGE_READ) ) return -ret; return get_errno(bind(sockfd, addr, addrlen)); } static long do_connect(int sockfd, target_ulong target_addr,
[Qemu-devel] [PATCH] Refresh of sem* implementation
Attached is a refreshed patch w/ a couple of additional fixes. This patch provides an implementation of semaphore interfaces (semget(), semctl(), semop()) that consists mostly of the structure mapping needed for 32 bit guest on 64 host such as arm on x86_64. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149Index: qemu/linux-user/i386/syscall.h === --- qemu.orig/linux-user/i386/syscall.h 2007-03-22 18:20:20.0 -0400 +++ qemu/linux-user/i386/syscall.h 2007-03-22 18:20:23.0 -0400 @@ -142,80 +142,4 @@ struct target_vm86plus_info_struct vm86plus; }; -/* ipcs */ - -#define TARGET_SEMOP 1 -#define TARGET_SEMGET 2 -#define TARGET_SEMCTL 3 -#define TARGET_MSGSND 11 -#define TARGET_MSGRCV 12 -#define TARGET_MSGGET 13 -#define TARGET_MSGCTL 14 -#define TARGET_SHMAT 21 -#define TARGET_SHMDT 22 -#define TARGET_SHMGET 23 -#define TARGET_SHMCTL 24 - -struct target_msgbuf { - int mtype; - char mtext[1]; -}; - -struct target_ipc_kludge { - unsigned int msgp; /* Really (struct msgbuf *) */ - int msgtyp; -}; - -struct target_ipc_perm { - int key; - unsigned short uid; - unsigned short gid; - unsigned short cuid; - unsigned short cgid; - unsigned short mode; - unsigned short seq; -}; - -struct target_msqid_ds { - struct target_ipc_perm msg_perm; - unsigned int msg_first; /* really struct target_msg* */ - unsigned int msg_last; /* really struct target_msg* */ - unsigned int msg_stime; /* really target_time_t */ - unsigned int msg_rtime; /* really target_time_t */ - unsigned int msg_ctime; /* really target_time_t */ - unsigned int wwait; /* really struct wait_queue* */ - unsigned int rwait; /* really struct wait_queue* */ - unsigned short msg_cbytes; - unsigned short msg_qnum; - unsigned short msg_qbytes; - unsigned short msg_lspid; - unsigned short msg_lrpid; -}; - -struct target_shmid_ds { - struct target_ipc_perm shm_perm; - int shm_segsz; - unsigned int shm_atime; /* really target_time_t */ - unsigned int shm_dtime; /* really target_time_t */ - unsigned int shm_ctime; /* really target_time_t */ - unsigned short shm_cpid; - unsigned short shm_lpid; - short shm_nattch; - unsigned short shm_npages; - unsigned long *shm_pages; - void *attaches; /* really struct shm_desc * */ -}; - -#define TARGET_IPC_RMID 0 -#define TARGET_IPC_SET 1 -#define TARGET_IPC_STAT 2 - -union target_semun { -int val; -unsigned int buf; /* really struct semid_ds * */ -unsigned int array; /* really unsigned short * */ -unsigned int __buf; /* really struct seminfo * */ -unsigned int __pad; /* really void* */ -}; - #define UNAME_MACHINE "i686" Index: qemu/linux-user/ppc/syscall.h === --- qemu.orig/linux-user/ppc/syscall.h 2007-03-22 18:20:20.0 -0400 +++ qemu/linux-user/ppc/syscall.h 2007-03-22 18:20:23.0 -0400 @@ -51,80 +51,4 @@ * flags masks */ -/* ipcs */ - -#define TARGET_SEMOP 1 -#define TARGET_SEMGET 2 -#define TARGET_SEMCTL 3 -#define TARGET_MSGSND 11 -#define TARGET_MSGRCV 12 -#define TARGET_MSGGET 13 -#define TARGET_MSGCTL 14 -#define TARGET_SHMAT 21 -#define TARGET_SHMDT 22 -#define TARGET_SHMGET 23 -#define TARGET_SHMCTL 24 - -struct target_msgbuf { - int mtype; - char mtext[1]; -}; - -struct target_ipc_kludge { - unsigned int msgp; /* Really (struct msgbuf *) */ - int msgtyp; -}; - -struct target_ipc_perm { - int key; - unsigned short uid; - unsigned short gid; - unsigned short cuid; - unsigned short cgid; - unsigned short mode; - unsigned short seq; -}; - -struct target_msqid_ds { - struct target_ipc_perm msg_perm; - unsigned int msg_first; /* really struct target_msg* */ - unsigned int msg_last; /* really struct target_msg* */ - unsigned int msg_stime; /* really target_time_t */ - unsigned int msg_rtime; /* really target_time_t */ - unsigned int msg_ctime; /* really target_time_t */ - unsigned int wwait; /* really struct wait_queue* */ - unsigned int rwait; /* really struct wait_queue* */ - unsigned short msg_cbytes; - unsigned short msg_qnum; - unsigned short msg_qbytes; - unsigned short msg_lspid; - unsigned short msg_lrpid; -}; - -struct target_shmid_ds { - struct target_ipc_perm shm_perm; - int shm_segsz; - unsigned int shm_atime; /* really target_time_t */ - unsigned int shm_dtime; /* really target_time_t */ - unsigned int shm_ctime; /* really target_time_t */ - unsigned short shm_cpid; - unsigned short shm_lpid; -
[Qemu-devel] generating EFAULT in linux-user
With a little help from Paul yesterday, I was able to come up with a scheme for detecting bad pointers passed to system calls in linux-user mode. This is used to return EFAULT as would be done on a real kernel. The attached patch is very preliminary, but shows how it can be done. I'm sending it now to solicit comments. The patch currently just add a seperate call to validate the address. Per yesterdays discussion, the checking should be folded into lock_user(), but it's not a trivial drop in as lock_user() and lock_user_struct() are used in different ways in different places, and none of them are actually checking a return value. I'm still thinking on how best to accomplish this part. The end result, is that the tests in LTPs msg* tests that try to generate EFAULT can now do so (and thus PASS). Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149Index: qemu/exec.c === --- qemu.orig/exec.c 2007-03-22 17:18:32.0 -0400 +++ qemu/exec.c 2007-03-22 17:42:30.0 -0400 @@ -1785,6 +1785,29 @@ spin_unlock(&tb_lock); } +int page_check_range(target_ulong start, target_ulong len, int flags) +{ +PageDesc *p; +target_ulong end; +target_ulong addr; + +end = TARGET_PAGE_ALIGN(start+len); /* must do before we loose bits in the next step */ +start = start & TARGET_PAGE_MASK; + +if( end < start ) return EFAULT; /* we've wrapped around */ +for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) { +p = page_find(addr >> TARGET_PAGE_BITS); + if( !p ) return EFAULT; + if( !(p->flags & PAGE_VALID) ) return EFAULT; + +if (!(p->flags & PAGE_READ) && +(flags & PAGE_READ) ) return EFAULT; +if (!(p->flags & PAGE_WRITE) && +(flags & PAGE_WRITE) ) return EFAULT; +} +return 0; +} + /* called from signal handler: invalidate the code and unprotect the page. Return TRUE if the fault was succesfully handled. */ int page_unprotect(target_ulong address, unsigned long pc, void *puc) Index: qemu/cpu-all.h === --- qemu.orig/cpu-all.h 2007-03-22 17:18:32.0 -0400 +++ qemu/cpu-all.h 2007-03-22 17:19:10.0 -0400 @@ -689,6 +689,7 @@ int page_get_flags(target_ulong address); void page_set_flags(target_ulong start, target_ulong end, int flags); void page_unprotect_range(target_ulong data, target_ulong data_size); +int page_check_range(target_ulong start, target_ulong len, int flags); #define SINGLE_CPU_DEFINES #ifdef SINGLE_CPU_DEFINES Index: qemu/linux-user/syscall.c === --- qemu.orig/linux-user/syscall.c 2007-03-22 17:19:00.0 -0400 +++ qemu/linux-user/syscall.c 2007-03-22 17:26:17.0 -0400 @@ -1287,12 +1287,15 @@ target_ulong __unused5; }; -static inline void target_to_host_msqid_ds(struct msqid_ds *host_md, - target_ulong target_addr) +/* static inline */ long target_to_host_msqid_ds(struct msqid_ds *host_md, + target_ulong target_addr, + int pg_access) { +long ret = 0; struct target_msqid_ds *target_md; lock_user_struct(target_md, target_addr, 1); +if( ret=page_check_range(target_md,sizeof(*target_md),pg_access) ) return -ret; target_to_host_ipc_perm(&(host_md->msg_perm),target_addr); host_md->msg_stime = tswapl(target_md->msg_stime); host_md->msg_rtime = tswapl(target_md->msg_rtime); @@ -1303,9 +1306,10 @@ host_md->msg_lspid = tswapl(target_md->msg_lspid); host_md->msg_lrpid = tswapl(target_md->msg_lrpid); unlock_user_struct(target_md, target_addr, 0); +return ret; } -static inline void host_to_target_msqid_ds(target_ulong target_addr, +/* static inline */ void host_to_target_msqid_ds(target_ulong target_addr, struct msqid_ds *host_md) { struct target_msqid_ds *target_md; @@ -1323,17 +1327,22 @@ unlock_user_struct(target_md, target_addr, 1); } -static inline long do_msgctl(long first, long second, long ptr) +/* static inline */ long do_msgctl(long first, long second, long ptr) { struct msqid_ds dsarg; int cmd = second&0xff; long ret = 0; switch( cmd ) { case IPC_STAT: +if( ret=target_to_host_msqid_ds(&dsarg,ptr,PAGE_WRITE) ) return -ret; +ret = get_errno(msgctl(first, cmd, &dsarg)); +host_to_target_msqid_ds(ptr,&dsarg); + break; case IPC_SET: -target_to_host_msqid_ds(&dsarg,ptr); +if( ret=target_to_host_msqid_ds(&dsarg,ptr,PAG
[Qemu-devel] [PATCH] message queue completion
Like the semaphore patch a couple of days ago, this patch completes the implementation of the message queue syscalls. With this patch, most of the message queue tests in LTP now pass in the guest. The remaining ones will require fixes in other syscall to fix, or at least eliminate the noise to identify any lingering issues. This was testing using ARM guest on a x86_64 host. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149Index: qemu/linux-user/syscall.c === --- qemu.orig/linux-user/syscall.c 2007-03-21 20:32:30.0 -0400 +++ qemu/linux-user/syscall.c 2007-03-21 21:07:50.0 -0400 @@ -1381,6 +1381,115 @@ return ret; } +struct target_msqid_ds +{ + struct target_ipc_perm msg_perm; + target_ulong msg_stime; + target_ulong __unused1; + target_ulong msg_rtime; + target_ulong __unused2; + target_ulong msg_ctime; + target_ulong __unused3; + target_ulong __msg_cbytes; + target_ulong msg_qnum; + target_ulong msg_qbytes; + target_ulong msg_lspid; + target_ulong msg_lrpid; + target_ulong __unused4; + target_ulong __unused5; +}; + +static inline void target_to_host_msqid_ds(struct msqid_ds *host_md, + target_ulong target_addr) +{ +struct target_msqid_ds *target_md; + +lock_user_struct(target_md, target_addr, 1); +target_to_host_ipc_perm(&(host_md->msg_perm),target_addr); +host_md->msg_stime = tswapl(target_md->msg_stime); +host_md->msg_rtime = tswapl(target_md->msg_rtime); +host_md->msg_ctime = tswapl(target_md->msg_ctime); +host_md->__msg_cbytes = tswapl(target_md->__msg_cbytes); +host_md->msg_qnum = tswapl(target_md->msg_qnum); +host_md->msg_lspid = tswapl(target_md->msg_lspid); +host_md->msg_lrpid = tswapl(target_md->msg_lrpid); +unlock_user_struct(target_md, target_addr, 0); +} + +static inline void host_to_target_msqid_ds(target_ulong target_addr, + struct msqid_ds *host_md) +{ +struct target_msqid_ds *target_md; + +lock_user_struct(target_md, target_addr, 0); +host_to_target_ipc_perm(target_addr,&(host_md->msg_perm)); +target_md->msg_stime = tswapl(host_md->msg_stime); +target_md->msg_rtime = tswapl(host_md->msg_rtime); +target_md->msg_ctime = tswapl(host_md->msg_ctime); +target_md->__msg_cbytes = tswapl(host_md->__msg_cbytes); +target_md->msg_qnum = tswapl(host_md->msg_qnum); +target_md->msg_lspid = tswapl(host_md->msg_lspid); +target_md->msg_lrpid = tswapl(host_md->msg_lrpid); +unlock_user_struct(target_md, target_addr, 1); +} + +static inline long do_msgctl(long first, long second, long ptr) +{ +struct msqid_ds dsarg; +int cmd = second&0xff; +long ret = 0; +switch( cmd ) { +case IPC_STAT: +case IPC_SET: +target_to_host_msqid_ds(&dsarg,ptr); +ret = get_errno(msgctl(first, cmd, &dsarg)); +host_to_target_msqid_ds(ptr,&dsarg); +default: +ret = get_errno(msgctl(first, cmd, &dsarg)); +} +return ret; +} + +struct target_msgbuf { + target_ulong mtype; + char mtext[1]; +}; + +static inline long do_msgsnd(long msqid, long msgp, long msgsz, long msgflg) +{ +struct target_msgbuf *target_mb; +struct msgbuf *host_mb; +long ret = 0; + +lock_user_struct(target_mb,msgp,0); +host_mb = malloc(msgsz+sizeof(long)); +host_mb->mtype = tswapl(target_mb->mtype); +memcpy(host_mb->mtext,target_mb->mtext,msgsz); +ret = get_errno(msgsnd(msqid, host_mb, msgsz, msgflg)); +free(host_mb); +unlock_user_struct(target_mb, msgp, 0); + +return ret; +} + +static inline long do_msgrcv(long msqid, long msgp, long msgsz, long msgtype, long msgflg) +{ +struct target_msgbuf *target_mb; +struct msgbuf *host_mb; +long ret = 0; + +lock_user_struct(target_mb,msgp,0); +host_mb = malloc(msgsz+sizeof(long)); +ret = get_errno(msgrcv(msqid, host_mb, msgsz, 1, msgflg)); +if( ret > 0 ) + memcpy(target_mb->mtext,host_mb->mtext,ret); +target_mb->mtype = tswapl(host_mb->mtype); +free(host_mb); +unlock_user_struct(target_mb, msgp, 0); + +return ret; +} + /* ??? This only works with linear mappings. */ static long do_ipc(long call, long first, long second, long third, long ptr, long fifth) @@ -1417,27 +1526,15 @@ break; case IPCOP_msgsnd: - ret = get_errno(msgsnd(first, (struct msgbuf *) ptr, second, third)); + ret = do_msgsnd(first, ptr, second, third); break; case IPCOP_msgctl: - ret = get_errno(msgctl(first, second, (struct msqid_ds *) ptr)); + ret = do_msgctl(first, second, ptr); break; case IPCOP_msgrcv: - { - struct ipc
Re: [Qemu-devel] [PATCH] fcntl64 fix
On Tue, 20 Mar 2007, Paul Brook wrote: Now that the dust has settled, I see where the change is probably a no-op anyway. A quick little test program indicates that on x86_64, l_start will have an offset of 8 wether the structure is packed or not, and wether the __pad member is present or not. The unsigned long long is always going to be aligned to a 8 byte boundary. The __pad member is essential. Your logic is wrong is two ways: a) The struct is packed. This overrides normal alignment and ensures the structure contains no padding. And in this case, it does remove some tail padding at the end of the structure. b) long long has whatever alignment the host feels like giving it. There's no guarantee it's going to be 8 byte aligned. No there isn't. This was just an observation of what occurs when building a simple test case on x86_64. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149 ___ Qemu-devel mailing list Qemu-devel@nongnu.org http://lists.nongnu.org/mailman/listinfo/qemu-devel
Re: [Qemu-devel] [PATCH] fcntl64 fix
On Wed, 21 Mar 2007, Kirill A. Shutemov wrote: Primarily, I also thought that problem is in padding, because, without the patch F_GETLK, on 32-bit target recognises as F_GETLK64 on 64-bit host. It's happen because on 64-bit host and 32-bit target F_GETLK == F_GETLK64 == TARGET_F_GETLK. So if you're using qemu-arm on 64-bit host and a target eabi program calls fcntl(fd,F_GETLK,...), target_eabi_flock64 will be used by mistake. Disabling padding can helps in some trivial cases to pass pseudo-correct args to fcntl. I guess this part of patch wrong. Stuart, am I right? Yes, this is a good summary of the trap I initially fell into. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149 ___ Qemu-devel mailing list Qemu-devel@nongnu.org http://lists.nongnu.org/mailman/listinfo/qemu-devel
Re: [Qemu-devel] [PATCH] fcntl64 fix
On Tue, 20 Mar 2007, Thiemo Seufer wrote: Still, this part makes no sense to me since it is in a packed struct. Can you explain why this works better for you? It worked better, in that it fixed a problem that let me continue on to fix other issues. After revisiting fcntl() and coming up with the more comprehensive patch, this change now seems to have no effect, so I must conceed that it is not needed, please drop that part of the patch. Now that the dust has settled, I see where the change is probably a no-op anyway. A quick little test program indicates that on x86_64, l_start will have an offset of 8 wether the structure is packed or not, and wether the __pad member is present or not. The unsigned long long is always going to be aligned to a 8 byte boundary. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149 ___ Qemu-devel mailing list Qemu-devel@nongnu.org http://lists.nongnu.org/mailman/listinfo/qemu-devel
Re: [Qemu-devel] [PATCH] fcntl64 fix
OK, I think I finally have it all sorted out. Sorry if I sounded dense along the way.. there were multiple variable, which increases the number of possible combinations quickly. The patch from Kirill is needed, and makes things better. One thing I notice with it is that we now handle TARGET_F_GETLK64 in two places, first in the case for TARGET_NR_fcntl64 (around line 4300), and then again in do_fcntl(), which is called in the default case of the first location. Once difference between the two locations is wether or not the case for EABI is handled. In addition to Kirill's patch, my original patch for target_eabi_flock64 is still needed as well as an expanded version of the revised patch I sent later that does target->host strcture mapping for the F_GETLK* cases. I have used the fcntl test sets out of the Linux Test Projects to measure with an without the different parts of these patches. With the entire set (Which is attached), 16 of the 18 test sets pass completely, and a significant portion of test14 (one of the two that don't pass completely) passes as well. The tests in test14 that fail may be do to a problem with a syscall other than fcntl(), but I haven't completely resulved it yet. Without my portion of the patch, the results are much worse (maybe half-ish are passing). There is something interesting about test18 (the other one that doesn't pass). It intentionally passes in a bad value (-1) as the 3rd argument to fcntl(). It is testing wether it will get EFAULT. With these fixes, qemu will SEGV as it tries to convert the struct flock (or struct flock64) from target->host, and encounters the bad address that was passed in. The initial SEGV is caught, but the handler for it then SEGVs again. Ideally, we could detect that we are inside an emulated system call, and be able to just return the EFAULT. I ran the LTP tests for both old ABI and EABI, and got the same results. Attached is the combined patch for fcntl(). Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149--- linux-user/syscall_defs.h.orig 2007-02-23 15:44:47.0 -0500 +++ linux-user/syscall_defs.h 2007-02-23 15:44:26.0 -0500 @@ -1414,7 +1414,9 @@ struct target_eabi_flock64 { short l_type; short l_whence; +#if HOST_LONG_BITS == 32 int __pad; +#endif unsigned long long l_start; unsigned long long l_len; int l_pid; Index: linux-user/syscall.c === --- linux-user/syscall.c.orig 2007-03-20 16:19:11.0 -0400 +++ linux-user/syscall.c2007-03-20 17:04:40.0 -0400 @@ -2107,6 +2107,13 @@ switch(cmd) { case TARGET_F_GETLK: +lock_user_struct(target_fl, arg, 1); +fl.l_type = tswap16(target_fl->l_type); +fl.l_whence = tswap16(target_fl->l_whence); +fl.l_start = tswapl(target_fl->l_start); +fl.l_len = tswapl(target_fl->l_len); +fl.l_pid = tswapl(target_fl->l_pid); +unlock_user_struct(target_fl, arg, 0); ret = fcntl(fd, cmd, &fl); if (ret == 0) { lock_user_struct(target_fl, arg, 0); @@ -2132,6 +2139,13 @@ break; case TARGET_F_GETLK64: +lock_user_struct(target_fl64, arg, 1); +fl64.l_type = tswap16(target_fl64->l_type) >> 1; +fl64.l_whence = tswap16(target_fl64->l_whence); +fl64.l_start = tswapl(target_fl64->l_start); +fl64.l_len = tswapl(target_fl64->l_len); +fl64.l_pid = tswap16(target_fl64->l_pid); +unlock_user_struct(target_fl64, arg, 0); ret = fcntl(fd, cmd >> 1, &fl64); if (ret == 0) { lock_user_struct(target_fl64, arg, 0); @@ -4201,15 +4215,47 @@ #if TARGET_LONG_BITS == 32 case TARGET_NR_fcntl64: { + int cmd; struct flock64 fl; struct target_flock64 *target_fl; #ifdef TARGET_ARM struct target_eabi_flock64 *target_efl; #endif + switch(arg2){ + case TARGET_F_GETLK64: + cmd = F_GETLK64; + case TARGET_F_SETLK64: + cmd = F_SETLK64; + case TARGET_F_SETLKW64: + cmd = F_SETLKW64; + default: + cmd = arg2; + } + switch(arg2) { -case F_GETLK64: -ret = get_errno(fcntl(arg1, arg2, &fl)); +case TARGET_F_GETLK64: +#ifdef TARGET_ARM +if (((CPUARMState *)cpu_env)->eabi) { +lock_user_struct(target_efl, arg3, 1); +fl.l_type = tswap16(target_efl->l_type); +fl.l_whence = tswap16(target_efl->l_whence); +fl.l_start = tswap64(target_efl->l_start); +fl.l_len = tswap64(target_efl->l_len)
Re: [Qemu-devel] [PATCH] fcntl64 fix
On Tue, 20 Mar 2007, Kirill A. Shutemov wrote: No. Remap is needed: $ uname -m; echo -e '#include \nF_GETLK64' | cpp | tail -1 x86_64 5 $ uname -m; echo -e '#include \nF_GETLK64' | cpp | tail -1 armv5l 12 Same for F_SETLK64 and F_SETLKW64. You are right. I had previously printed out the non-64 versions, and they are the same, but we not using those. TARGET_F_GETLK 5 F_GETLK 5 TARGET_F_GETLK64 12 F_GETLK64 5 My confusion... Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149 ___ Qemu-devel mailing list Qemu-devel@nongnu.org http://lists.nongnu.org/mailman/listinfo/qemu-devel
Re: [Qemu-devel] [PATCH] fcntl64 fix
On Tue, 20 Mar 2007, Kirill A. Shutemov wrote: What are you using as a test app? I got error when runing Debian's apt-get and tried to fix it. OK, that's what got me started on this one, but I switched to using the ltp-kernel-test package for a more comprehensive set of tests once I got past that first eabi structure change. I think that remapping the constants is needed, but I'm just curious how we seem to be coming up with different parts of the fix when we have the same target/host combination. I'm not sure that I understand you... On the arm/x86_64 combination, I think the host & target cmd values are the same, so the remapping is a noop. It may be needed for other combinations though. Some architectures have very different values for constants like this in their ABI. I was trying to understand how your fix made apt-get/dpkg happy, or if you were just using a different app that was hitting a different case for fcntl(). Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149 ___ Qemu-devel mailing list Qemu-devel@nongnu.org http://lists.nongnu.org/mailman/listinfo/qemu-devel
Re: [Qemu-devel] [PATCH] fcntl64 fix
On Tue, 20 Mar 2007, Kirill A. Shutemov wrote: Kiril, What 32 bit host and 64 bit host are you using? I'm working on arm on x86_64, and I'm starting to think that perhaps all of the different parts of the fix are needed to ensure it works correctly on all target/host combinations. I'm using arm(little-endian) on x86_64. That blows that theory 8-). What are you using as a test app? I think that remapping the constants is needed, but I'm just curious how we seem to be coming up with different parts of the fix when we have the same target/host combination. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149 ___ Qemu-devel mailing list Qemu-devel@nongnu.org http://lists.nongnu.org/mailman/listinfo/qemu-devel
Re: [Qemu-devel] [PATCH] fcntl64 fix
On Mon, 19 Mar 2007, Stuart Anderson wrote: My initial fix was before I started using LTP, and just took care of a single case that was holding me up. Now I have run the fcntl tests in LTP on ARM (both oABI and EABI) and there are a lot of failures indicating that there is a lot more work to be done yet on fcntl(). I'll take a look into it, and probably resubmit a bigger patch later. One more small fix to repack a structure from taget -> host before using it clears up most of the fcntl() errors that showed up in LTP. This is one of those that probably doesn't happen when runngin 32 on 32, but I'm running 32 on 64. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149--- linux-user/syscall.c.orig 2007-03-20 01:25:39.0 -0400 +++ linux-user/syscall.c2007-03-20 02:32:39.0 -0400 @@ -2107,6 +2107,13 @@ switch(cmd) { case TARGET_F_GETLK: +lock_user_struct(target_fl, arg, 1); +fl.l_type = tswap16(target_fl->l_type); +fl.l_whence = tswap16(target_fl->l_whence); +fl.l_start = tswapl(target_fl->l_start); +fl.l_len = tswapl(target_fl->l_len); +fl.l_pid = tswapl(target_fl->l_pid); +unlock_user_struct(target_fl, arg, 0); ret = fcntl(fd, cmd, &fl); if (ret == 0) { lock_user_struct(target_fl, arg, 0); ___ Qemu-devel mailing list Qemu-devel@nongnu.org http://lists.nongnu.org/mailman/listinfo/qemu-devel
Re: [Qemu-devel] [PATCH] fcntl64 fix
My initial fix was before I started using LTP, and just took care of a single case that was holding me up. Now I have run the fcntl tests in LTP on ARM (both oABI and EABI) and there are a lot of failures indicating that there is a lot more work to be done yet on fcntl(). I'll take a look into it, and probably resubmit a bigger patch later. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149 ___ Qemu-devel mailing list Qemu-devel@nongnu.org http://lists.nongnu.org/mailman/listinfo/qemu-devel
Re: [Qemu-devel] [PATCH] EABI fcntl on x86_64
On Mon, 19 Mar 2007, Stuart Anderson wrote: I have a debian arm chroot setup. Just to clarify, this is from the applieddata.net repository, not the normal debian one (which is not eabi). Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149 ___ Qemu-devel mailing list Qemu-devel@nongnu.org http://lists.nongnu.org/mailman/listinfo/qemu-devel
[Qemu-devel] [PATCH] semctl support is incomplete
The attached patch finishes adding support for semctl(). This was verified on ARM using the semctl test from LTP in the target. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149Index: linux-user/syscall.c === RCS file: /sources/qemu/qemu/linux-user/syscall.c,v retrieving revision 1.93 diff -u -r1.93 syscall.c --- linux-user/syscall.c19 Mar 2007 13:32:45 - 1.93 +++ linux-user/syscall.c19 Mar 2007 15:40:57 - @@ -1123,12 +1123,152 @@ uint32_t size; } shm_regions[N_SHM_REGIONS]; +struct target_ipc_perm +{ +target_long __key; +target_ulong uid; +target_ulong gid; +target_ulong cuid; +target_ulong cgid; +unsigned short int mode; +unsigned short int __pad1; +unsigned short int __seq; +unsigned short int __pad2; +target_ulong __unused1; +target_ulong __unused2; +}; + +struct target_semid_ds +{ + struct target_ipc_perm sem_perm; + target_ulong sem_otime; + target_ulong __unused1; + target_ulong sem_ctime; + target_ulong __unused2; + target_ulong sem_nsems; + target_ulong __unused3; + target_ulong __unused4; +}; + +static inline void target_to_host_ipc_perm(struct ipc_perm *ip, + target_ulong target_addr) +{ +struct target_ipc_perm *target_ip; +struct target_semid_ds *target_sd; + +lock_user_struct(target_sd, target_addr, 1); +target_ip=&(target_sd->sem_perm); +ip->__key = tswapl(target_ip->__key); +ip->uid = tswapl(target_ip->uid); +ip->gid = tswapl(target_ip->gid); +ip->cuid = tswapl(target_ip->cuid); +ip->cgid = tswapl(target_ip->cgid); +ip->mode = tswapl(target_ip->mode); +unlock_user_struct(target_sd, target_addr, 0); +} + +static inline void host_to_target_ipc_perm(target_ulong target_addr, + struct ipc_perm *host_ip) +{ +struct target_ipc_perm *target_ip; +struct target_semid_ds *target_sd; + +lock_user_struct(target_sd, target_addr, 0); +target_ip = &(target_sd->sem_perm); +target_ip->__key = tswapl(host_ip->__key); +target_ip->uid = tswapl(host_ip->uid); +target_ip->gid = tswapl(host_ip->gid); +target_ip->cuid = tswapl(host_ip->cuid); +target_ip->cgid = tswapl(host_ip->cgid); +target_ip->mode = tswapl(host_ip->mode); +unlock_user_struct(target_sd, target_addr, 1); +} + +static inline void target_to_host_semid_ds(struct semid_ds *host_sd, + target_ulong target_addr) +{ +struct target_semid_ds *target_sd; + +lock_user_struct(target_sd, target_addr, 1); +target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr); +host_sd->sem_nsems = tswapl(target_sd->sem_nsems); +host_sd->sem_otime = tswapl(target_sd->sem_otime); +host_sd->sem_ctime = tswapl(target_sd->sem_ctime); +unlock_user_struct(target_sd, target_addr, 0); +} + +static inline void host_to_target_semid_ds(target_ulong target_addr, + struct semid_ds *host_sd) +{ +struct target_semid_ds *target_sd; + +lock_user_struct(target_sd, target_addr, 0); +host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm)); +target_sd->sem_nsems = tswapl(host_sd->sem_nsems); +target_sd->sem_otime = tswapl(host_sd->sem_otime); +target_sd->sem_ctime = tswapl(host_sd->sem_ctime); +unlock_user_struct(target_sd, target_addr, 1); +} + union semun { int val; - struct senid_ds *buf; + struct semid_ds *buf; unsigned short *array; }; +union target_semun { + int val; + target_long buf; + target_long array; +}; + +static inline void target_to_host_semun(unsigned long cmd, union semun *host_su, + target_ulong target_addr, struct semid_ds *ds) +{ +union target_semun *target_su; + +lock_user_struct(target_su, target_addr, 1); +switch( cmd ) { + case IPC_STAT: + case IPC_SET: + target_to_host_semid_ds(ds,target_su->buf); + host_su->buf = ds; + break; + default: + host_su->array = tswapl(target_su->array); +} +unlock_user_struct(target_su, target_addr, 0); +} + +static inline void host_to_target_semun(unsigned long cmd, target_ulong target_addr, + union semun *host_su, struct semid_ds *ds) +{ +union target_semun *target_su; + +lock_user_struct(target_su, target_addr, 0); +switch( cmd ) { + case IPC_STAT: + case IPC_SET: + host_to_target_semid_ds(target_su->buf,ds); + break; +default: + target_su->arra
Re: [Qemu-devel] [PATCH] EABI fcntl on x86_64
On Mon, 19 Mar 2007, Paul Brook wrote: On Monday 19 March 2007 15:30, Stuart Anderson wrote: When running ARM EABI binaries on x86_64, the target_eabi_flock64 structure is already padded correct so the padding is not needed. This patch adds an #ifdef to only include the _pad member on 32-but hosts. This is wrong. The struct is packed, so its layout should be independent of the host. How did you test your change? I have a debian arm chroot setup. dpkg was unhappy, and I used gdb to observe that there seemed to an extra 4 bytes of data in the middle of the structure being passed into the host function. I missed Kirill's patch as it came across before I got back on the list, (and I missedit when I browsed the archive as well). Since I should be able to reproduce this, I'll test w/ his fix as well. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149 ___ Qemu-devel mailing list Qemu-devel@nongnu.org http://lists.nongnu.org/mailman/listinfo/qemu-devel
[Qemu-devel] [PATCH] EABI fcntl on x86_64
When running ARM EABI binaries on x86_64, the target_eabi_flock64 structure is already padded correct so the padding is not needed. This patch adds an #ifdef to only include the _pad member on 32-but hosts. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149Index: linux-user/syscall_defs.h === RCS file: /sources/qemu/qemu/linux-user/syscall_defs.h,v retrieving revision 1.30 diff -u -r1.30 syscall_defs.h --- linux-user/syscall_defs.h 22 Oct 2006 00:18:54 - 1.30 +++ linux-user/syscall_defs.h 19 Mar 2007 15:25:58 - @@ -1409,7 +1409,9 @@ struct target_eabi_flock64 { short l_type; short l_whence; +#if HOST_LONG_BITS == 32 int __pad; +#endif unsigned long long l_start; unsigned long long l_len; int l_pid; ___ Qemu-devel mailing list Qemu-devel@nongnu.org http://lists.nongnu.org/mailman/listinfo/qemu-devel
[Qemu-devel] [PATCH] Correct setuid behavious in linux-user
The attached patch is needed to correctly emulate setuid executables. With this change, and by making qemu be setuid root (and assumming all of the risks and responsibilites of doing so), executables such as /bin/su will be able to create the correct environment. Stuart Stuart R. Anderson [EMAIL PROTECTED] Network & Software Engineering http://www.netsweng.com/ 1024D/37A79149: 0791 D3B8 9A4C 2CDC A31F BD03 0A62 E534 37A7 9149Index: linux-user/linuxload.c === RCS file: /sources/qemu/qemu/linux-user/linuxload.c,v retrieving revision 1.2 diff -u -r1.2 linuxload.c --- linux-user/linuxload.c 19 Nov 2006 20:29:35 - 1.2 +++ linux-user/linuxload.c 19 Mar 2007 15:09:50 - @@ -78,6 +78,8 @@ if(bprm->e_uid != geteuid()) { id_change = 1; } +} else { + seteuid(getuid()); } /* Set-gid? */ @@ -91,6 +93,8 @@ if (!in_group_p(bprm->e_gid)) { id_change = 1; } +} else { + setegid(getgid()); } memset(bprm->buf, 0, sizeof(bprm->buf)); ___ Qemu-devel mailing list Qemu-devel@nongnu.org http://lists.nongnu.org/mailman/listinfo/qemu-devel