diff options
Diffstat (limited to 'linux-user')
| -rw-r--r-- | linux-user/flat.h | 5 | ||||
| -rw-r--r-- | linux-user/flatload.c | 293 | ||||
| -rw-r--r-- | linux-user/ioctls.h | 3 | ||||
| -rw-r--r-- | linux-user/qemu.h | 4 | ||||
| -rw-r--r-- | linux-user/syscall.c | 73 | ||||
| -rw-r--r-- | linux-user/syscall_defs.h | 1 | ||||
| -rw-r--r-- | linux-user/syscall_types.h | 5 | ||||
| -rw-r--r-- | linux-user/uaccess.c | 4 |
8 files changed, 56 insertions, 332 deletions
diff --git a/linux-user/flat.h b/linux-user/flat.h index ed518e2013..e374b73e26 100644 --- a/linux-user/flat.h +++ b/linux-user/flat.h @@ -12,11 +12,8 @@ #define FLAT_VERSION 0x00000004L -#ifdef CONFIG_BINFMT_SHARED_FLAT -#define MAX_SHARED_LIBS (4) -#else +/* QEMU doesn't support bflt shared libraries */ #define MAX_SHARED_LIBS (1) -#endif /* * To make everything easier to port and manage cross platform diff --git a/linux-user/flatload.c b/linux-user/flatload.c index 5b62aa0a2b..04d8138d12 100644 --- a/linux-user/flatload.c +++ b/linux-user/flatload.c @@ -29,8 +29,6 @@ * JAN/99 -- coded full program relocation (gerg@snapgear.com) */ -/* ??? ZFLAT and shared library support is currently disabled. */ - /****************************************************************************/ #include "qemu/osdep.h" @@ -64,10 +62,6 @@ struct lib_info { short loaded; /* Has this library been loaded? */ }; -#ifdef CONFIG_BINFMT_SHARED_FLAT -static int load_flat_shared_library(int id, struct lib_info *p); -#endif - struct linux_binprm; /****************************************************************************/ @@ -108,153 +102,6 @@ static int target_pread(int fd, abi_ulong ptr, abi_ulong len, unlock_user(buf, ptr, len); return ret; } -/****************************************************************************/ - -#ifdef CONFIG_BINFMT_ZFLAT - -#include <linux/zlib.h> - -#define LBUFSIZE 4000 - -/* gzip flag byte */ -#define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */ -#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ -#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ -#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ -#define COMMENT 0x10 /* bit 4 set: file comment present */ -#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ -#define RESERVED 0xC0 /* bit 6,7: reserved */ - -static int decompress_exec( - struct linux_binprm *bprm, - unsigned long offset, - char *dst, - long len, - int fd) -{ - unsigned char *buf; - z_stream strm; - loff_t fpos; - int ret, retval; - - DBG_FLT("decompress_exec(offset=%x,buf=%x,len=%x)\n",(int)offset, (int)dst, (int)len); - - memset(&strm, 0, sizeof(strm)); - strm.workspace = kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL); - if (strm.workspace == NULL) { - DBG_FLT("binfmt_flat: no memory for decompress workspace\n"); - return -ENOMEM; - } - buf = kmalloc(LBUFSIZE, GFP_KERNEL); - if (buf == NULL) { - DBG_FLT("binfmt_flat: no memory for read buffer\n"); - retval = -ENOMEM; - goto out_free; - } - - /* Read in first chunk of data and parse gzip header. */ - fpos = offset; - ret = bprm->file->f_op->read(bprm->file, buf, LBUFSIZE, &fpos); - - strm.next_in = buf; - strm.avail_in = ret; - strm.total_in = 0; - - retval = -ENOEXEC; - - /* Check minimum size -- gzip header */ - if (ret < 10) { - DBG_FLT("binfmt_flat: file too small?\n"); - goto out_free_buf; - } - - /* Check gzip magic number */ - if ((buf[0] != 037) || ((buf[1] != 0213) && (buf[1] != 0236))) { - DBG_FLT("binfmt_flat: unknown compression magic?\n"); - goto out_free_buf; - } - - /* Check gzip method */ - if (buf[2] != 8) { - DBG_FLT("binfmt_flat: unknown compression method?\n"); - goto out_free_buf; - } - /* Check gzip flags */ - if ((buf[3] & ENCRYPTED) || (buf[3] & CONTINUATION) || - (buf[3] & RESERVED)) { - DBG_FLT("binfmt_flat: unknown flags?\n"); - goto out_free_buf; - } - - ret = 10; - if (buf[3] & EXTRA_FIELD) { - ret += 2 + buf[10] + (buf[11] << 8); - if (unlikely(LBUFSIZE == ret)) { - DBG_FLT("binfmt_flat: buffer overflow (EXTRA)?\n"); - goto out_free_buf; - } - } - if (buf[3] & ORIG_NAME) { - for (; ret < LBUFSIZE && (buf[ret] != 0); ret++) - ; - if (unlikely(LBUFSIZE == ret)) { - DBG_FLT("binfmt_flat: buffer overflow (ORIG_NAME)?\n"); - goto out_free_buf; - } - } - if (buf[3] & COMMENT) { - for (; ret < LBUFSIZE && (buf[ret] != 0); ret++) - ; - if (unlikely(LBUFSIZE == ret)) { - DBG_FLT("binfmt_flat: buffer overflow (COMMENT)?\n"); - goto out_free_buf; - } - } - - strm.next_in += ret; - strm.avail_in -= ret; - - strm.next_out = dst; - strm.avail_out = len; - strm.total_out = 0; - - if (zlib_inflateInit2(&strm, -MAX_WBITS) != Z_OK) { - DBG_FLT("binfmt_flat: zlib init failed?\n"); - goto out_free_buf; - } - - while ((ret = zlib_inflate(&strm, Z_NO_FLUSH)) == Z_OK) { - ret = bprm->file->f_op->read(bprm->file, buf, LBUFSIZE, &fpos); - if (ret <= 0) - break; - if (is_error(ret)) { - break; - } - len -= ret; - - strm.next_in = buf; - strm.avail_in = ret; - strm.total_in = 0; - } - - if (ret < 0) { - DBG_FLT("binfmt_flat: decompression failed (%d), %s\n", - ret, strm.msg); - goto out_zlib; - } - - retval = 0; -out_zlib: - zlib_inflateEnd(&strm); -out_free_buf: - kfree(buf); -out_free: - kfree(strm.workspace); -out: - return retval; -} - -#endif /* CONFIG_BINFMT_ZFLAT */ /****************************************************************************/ @@ -268,40 +115,7 @@ calc_reloc(abi_ulong r, struct lib_info *p, int curid, int internalp) abi_ulong text_len; abi_ulong start_code; -#ifdef CONFIG_BINFMT_SHARED_FLAT -#error needs checking - if (r == 0) - id = curid; /* Relocs of 0 are always self referring */ - else { - id = (r >> 24) & 0xff; /* Find ID for this reloc */ - r &= 0x00ffffff; /* Trim ID off here */ - } - if (id >= MAX_SHARED_LIBS) { - fprintf(stderr, "BINFMT_FLAT: reference 0x%x to shared library %d\n", - (unsigned) r, id); - goto failed; - } - if (curid != id) { - if (internalp) { - fprintf(stderr, "BINFMT_FLAT: reloc address 0x%x not " - "in same module (%d != %d)\n", - (unsigned) r, curid, id); - goto failed; - } else if (!p[id].loaded && is_error(load_flat_shared_library(id, p))) { - fprintf(stderr, "BINFMT_FLAT: failed to load library %d\n", id); - goto failed; - } - /* Check versioning information (i.e. time stamps) */ - if (p[id].build_date && p[curid].build_date - && p[curid].build_date < p[id].build_date) { - fprintf(stderr, "BINFMT_FLAT: library %d is younger than %d\n", - id, curid); - goto failed; - } - } -#else id = 0; -#endif start_brk = p[id].start_brk; start_data = p[id].start_data; @@ -425,12 +239,10 @@ static int load_flat_file(struct linux_binprm * bprm, if (rev == OLD_FLAT_VERSION && flat_old_ram_flag(flags)) flags = FLAT_FLAG_RAM; -#ifndef CONFIG_BINFMT_ZFLAT if (flags & (FLAT_FLAG_GZIP|FLAT_FLAG_GZDATA)) { - fprintf(stderr, "Support for ZFLAT executables is not enabled\n"); + fprintf(stderr, "ZFLAT executables are not supported\n"); return -ENOEXEC; } -#endif /* * calculate the extra space we need to map in @@ -483,17 +295,9 @@ static int load_flat_file(struct linux_binprm * bprm, (int)(data_len + bss_len + stack_len), (int)datapos); fpos = ntohl(hdr->data_start); -#ifdef CONFIG_BINFMT_ZFLAT - if (flags & FLAT_FLAG_GZDATA) { - result = decompress_exec(bprm, fpos, (char *) datapos, - data_len + (relocs * sizeof(abi_ulong))) - } else -#endif - { - result = target_pread(bprm->src.fd, datapos, - data_len + (relocs * sizeof(abi_ulong)), - fpos); - } + result = target_pread(bprm->src.fd, datapos, + data_len + (relocs * sizeof(abi_ulong)), + fpos); if (result < 0) { fprintf(stderr, "Unable to read data+bss\n"); return result; @@ -515,38 +319,12 @@ static int load_flat_file(struct linux_binprm * bprm, datapos = realdatastart + indx_len; reloc = (textpos + ntohl(hdr->reloc_start) + indx_len); -#ifdef CONFIG_BINFMT_ZFLAT -#error code needs checking - /* - * load it all in and treat it like a RAM load from now on - */ - if (flags & FLAT_FLAG_GZIP) { - result = decompress_exec(bprm, sizeof (struct flat_hdr), - (((char *) textpos) + sizeof (struct flat_hdr)), - (text_len + data_len + (relocs * sizeof(unsigned long)) - - sizeof (struct flat_hdr)), - 0); - memmove((void *) datapos, (void *) realdatastart, - data_len + (relocs * sizeof(unsigned long))); - } else if (flags & FLAT_FLAG_GZDATA) { - fpos = 0; - result = bprm->file->f_op->read(bprm->file, - (char *) textpos, text_len, &fpos); - if (!is_error(result)) { - result = decompress_exec(bprm, text_len, (char *) datapos, - data_len + (relocs * sizeof(unsigned long)), 0); - } - } - else -#endif - { - result = target_pread(bprm->src.fd, textpos, - text_len, 0); - if (result >= 0) { - result = target_pread(bprm->src.fd, datapos, - data_len + (relocs * sizeof(abi_ulong)), - ntohl(hdr->data_start)); - } + result = target_pread(bprm->src.fd, textpos, + text_len, 0); + if (result >= 0) { + result = target_pread(bprm->src.fd, datapos, + data_len + (relocs * sizeof(abi_ulong)), + ntohl(hdr->data_start)); } if (result < 0) { fprintf(stderr, "Unable to read code+data+bss\n"); @@ -678,44 +456,6 @@ static int load_flat_file(struct linux_binprm * bprm, /****************************************************************************/ -#ifdef CONFIG_BINFMT_SHARED_FLAT - -/* - * Load a shared library into memory. The library gets its own data - * segment (including bss) but not argv/argc/environ. - */ - -static int load_flat_shared_library(int id, struct lib_info *libs) -{ - struct linux_binprm bprm; - int res; - char buf[16]; - - /* Create the file name */ - sprintf(buf, "/lib/lib%d.so", id); - - /* Open the file up */ - bprm.filename = buf; - bprm.file = open_exec(bprm.filename); - res = PTR_ERR(bprm.file); - if (IS_ERR(bprm.file)) - return res; - - res = prepare_binprm(&bprm); - - if (!is_error(res)) { - res = load_flat_file(&bprm, libs, id, NULL); - } - if (bprm.file) { - allow_write_access(bprm.file); - fput(bprm.file); - bprm.file = NULL; - } - return(res); -} - -#endif /* CONFIG_BINFMT_SHARED_FLAT */ - int load_flt_binary(struct linux_binprm *bprm, struct image_info *info) { struct lib_info libinfo[MAX_SHARED_LIBS]; @@ -793,19 +533,6 @@ int load_flt_binary(struct linux_binprm *bprm, struct image_info *info) */ start_addr = libinfo[0].entry; -#ifdef CONFIG_BINFMT_SHARED_FLAT -#error here - for (i = MAX_SHARED_LIBS-1; i>0; i--) { - if (libinfo[i].loaded) { - /* Push previous first to call address */ - --sp; - if (put_user_ual(start_addr, sp)) - return -EFAULT; - start_addr = libinfo[i].entry; - } - } -#endif - /* Stash our initial stack pointer into the mm structure */ info->start_code = libinfo[0].start_code; info->end_code = libinfo[0].start_code + libinfo[0].text_len; diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h index 1aec9d5836..d508d0c04a 100644 --- a/linux-user/ioctls.h +++ b/linux-user/ioctls.h @@ -140,6 +140,9 @@ #ifdef FITHAW IOCTL(FITHAW, IOC_W | IOC_R, TYPE_INT) #endif +#ifdef FITRIM + IOCTL(FITRIM, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_fstrim_range))) +#endif IOCTL(FIGETBSZ, IOC_R, MK_PTR(TYPE_LONG)) #ifdef CONFIG_FIEMAP diff --git a/linux-user/qemu.h b/linux-user/qemu.h index 32cd43d9ef..4777856b52 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -4,8 +4,6 @@ #include "cpu.h" #include "exec/cpu_ldst.h" -#undef DEBUG_REMAP - #include "exec/user/abitypes.h" #include "syscall_defs.h" @@ -332,7 +330,7 @@ void *lock_user(int type, abi_ulong guest_addr, ssize_t len, bool copy); /* Unlock an area of guest memory. The first LEN bytes must be flushed back to guest memory. host_ptr = NULL is explicitly allowed and does nothing. */ -#ifndef DEBUG_REMAP +#ifndef CONFIG_DEBUG_REMAP static inline void unlock_user(void *host_ptr, abi_ulong guest_addr, ssize_t len) { diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 3df2b94d9a..41659b63f5 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -1615,24 +1615,6 @@ static abi_long do_pipe(CPUArchState *cpu_env, abi_ulong pipedes, return get_errno(ret); } -static inline abi_long target_to_host_ip_mreq(struct ip_mreqn *mreqn, - abi_ulong target_addr, - socklen_t len) -{ - struct target_ip_mreqn *target_smreqn; - - target_smreqn = lock_user(VERIFY_READ, target_addr, len, 1); - if (!target_smreqn) - return -TARGET_EFAULT; - mreqn->imr_multiaddr.s_addr = target_smreqn->imr_multiaddr.s_addr; - mreqn->imr_address.s_addr = target_smreqn->imr_address.s_addr; - if (len == sizeof(struct target_ip_mreqn)) - mreqn->imr_ifindex = tswapal(target_smreqn->imr_ifindex); - unlock_user(target_smreqn, target_addr, 0); - - return 0; -} - static inline abi_long target_to_host_sockaddr(int fd, struct sockaddr *addr, abi_ulong target_addr, socklen_t len) @@ -2067,8 +2049,6 @@ static abi_long do_setsockopt(int sockfd, int level, int optname, { abi_long ret; int val; - struct ip_mreqn *ip_mreq; - struct ip_mreq_source *ip_mreq_source; switch(level) { case SOL_TCP: @@ -2111,19 +2091,40 @@ static abi_long do_setsockopt(int sockfd, int level, int optname, break; case IP_ADD_MEMBERSHIP: case IP_DROP_MEMBERSHIP: + { + struct ip_mreqn ip_mreq; + struct target_ip_mreqn *target_smreqn; + + QEMU_BUILD_BUG_ON(sizeof(struct ip_mreq) != + sizeof(struct target_ip_mreq)); + if (optlen < sizeof (struct target_ip_mreq) || - optlen > sizeof (struct target_ip_mreqn)) + optlen > sizeof (struct target_ip_mreqn)) { return -TARGET_EINVAL; + } - ip_mreq = (struct ip_mreqn *) alloca(optlen); - target_to_host_ip_mreq(ip_mreq, optval_addr, optlen); - ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq, optlen)); - break; + target_smreqn = lock_user(VERIFY_READ, optval_addr, optlen, 1); + if (!target_smreqn) { + return -TARGET_EFAULT; + } + ip_mreq.imr_multiaddr.s_addr = target_smreqn->imr_multiaddr.s_addr; + ip_mreq.imr_address.s_addr = target_smreqn->imr_address.s_addr; + if (optlen == sizeof(struct target_ip_mreqn)) { + ip_mreq.imr_ifindex = tswapal(target_smreqn->imr_ifindex); + optlen = sizeof(struct ip_mreqn); + } + unlock_user(target_smreqn, optval_addr, 0); + ret = get_errno(setsockopt(sockfd, level, optname, &ip_mreq, optlen)); + break; + } case IP_BLOCK_SOURCE: case IP_UNBLOCK_SOURCE: case IP_ADD_SOURCE_MEMBERSHIP: case IP_DROP_SOURCE_MEMBERSHIP: + { + struct ip_mreq_source *ip_mreq_source; + if (optlen != sizeof (struct target_ip_mreq_source)) return -TARGET_EINVAL; @@ -2134,7 +2135,7 @@ static abi_long do_setsockopt(int sockfd, int level, int optname, ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq_source, optlen)); unlock_user (ip_mreq_source, optval_addr, 0); break; - + } default: goto unimplemented; } @@ -2277,18 +2278,13 @@ static abi_long do_setsockopt(int sockfd, int level, int optname, switch (optname) { case ALG_SET_KEY: { - char *alg_key = g_malloc(optlen); - + char *alg_key = lock_user(VERIFY_READ, optval_addr, optlen, 1); if (!alg_key) { - return -TARGET_ENOMEM; - } - if (copy_from_user(alg_key, optval_addr, optlen)) { - g_free(alg_key); return -TARGET_EFAULT; } ret = get_errno(setsockopt(sockfd, level, optname, alg_key, optlen)); - g_free(alg_key); + unlock_user(alg_key, optval_addr, optlen); break; } case ALG_SET_AEAD_AUTHSIZE: @@ -2305,12 +2301,10 @@ static abi_long do_setsockopt(int sockfd, int level, int optname, case TARGET_SOL_SOCKET: switch (optname) { case TARGET_SO_RCVTIMEO: + case TARGET_SO_SNDTIMEO: { struct timeval tv; - optname = SO_RCVTIMEO; - -set_timeout: if (optlen != sizeof(struct target_timeval)) { return -TARGET_EINVAL; } @@ -2319,13 +2313,12 @@ set_timeout: return -TARGET_EFAULT; } - ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, + ret = get_errno(setsockopt(sockfd, SOL_SOCKET, + optname == TARGET_SO_RCVTIMEO ? + SO_RCVTIMEO : SO_SNDTIMEO, &tv, sizeof(tv))); return ret; } - case TARGET_SO_SNDTIMEO: - optname = SO_SNDTIMEO; - goto set_timeout; case TARGET_SO_ATTACH_FILTER: { struct target_sock_fprog *tfprog; diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 3995487630..a00b617cae 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -945,6 +945,7 @@ struct target_rtc_pll_info { #define TARGET_FIFREEZE TARGET_IOWR('X', 119, abi_int) #define TARGET_FITHAW TARGET_IOWR('X', 120, abi_int) +#define TARGET_FITRIM TARGET_IOWR('X', 121, struct fstrim_range) /* * Note that the ioctl numbers for FS_IOC_<GET|SET><FLAGS|VERSION> diff --git a/linux-user/syscall_types.h b/linux-user/syscall_types.h index c3b43f8022..6dd7a80ce5 100644 --- a/linux-user/syscall_types.h +++ b/linux-user/syscall_types.h @@ -341,6 +341,11 @@ STRUCT(file_clone_range, TYPE_ULONGLONG, /* src_length */ TYPE_ULONGLONG) /* dest_offset */ +STRUCT(fstrim_range, + TYPE_ULONGLONG, /* start */ + TYPE_ULONGLONG, /* len */ + TYPE_ULONGLONG) /* minlen */ + STRUCT(fiemap_extent, TYPE_ULONGLONG, /* fe_logical */ TYPE_ULONGLONG, /* fe_physical */ diff --git a/linux-user/uaccess.c b/linux-user/uaccess.c index 425cbf677f..27e841e651 100644 --- a/linux-user/uaccess.c +++ b/linux-user/uaccess.c @@ -14,7 +14,7 @@ void *lock_user(int type, abi_ulong guest_addr, ssize_t len, bool copy) return NULL; } host_addr = g2h_untagged(guest_addr); -#ifdef DEBUG_REMAP +#ifdef CONFIG_DEBUG_REMAP if (copy) { host_addr = g_memdup(host_addr, len); } else { @@ -24,7 +24,7 @@ void *lock_user(int type, abi_ulong guest_addr, ssize_t len, bool copy) return host_addr; } -#ifdef DEBUG_REMAP +#ifdef CONFIG_DEBUG_REMAP void unlock_user(void *host_ptr, abi_ulong guest_addr, ssize_t len) { void *host_ptr_conv; |