diff options
author | Marcelo Tosatti <mtosatti@redhat.com> | 2012-08-23 09:33:26 -0300 |
---|---|---|
committer | Marcelo Tosatti <mtosatti@redhat.com> | 2012-08-23 09:33:26 -0300 |
commit | f59dd237e3bf57d2c00d627c65f57e145e7eec9d (patch) | |
tree | ca88b4ce7f4623d1818087f1064ca4f19897fcf3 | |
parent | 47d70a2bcd70994d398cfb696c19ee1851e9f0ca (diff) | |
parent | ea776abca628d855e03c4929da3864985afd8aae (diff) |
Merge commit 'ea776abca628d855e03c4929da3864985afd8aae' into upstream-merge
* commit 'ea776abca628d855e03c4929da3864985afd8aae': (30 commits)
virtio-blk: hide VIRTIO_BLK_F_CONFIG_WCE from old machine types
softmmu-semi: fix lock_user* functions not to deref NULL upon OOM
arm-semi: don't leak 1KB user string lock buffer upon TARGET_SYS_OPEN
sheepdog: don't leak socket file descriptor upon connection failure
linux-user: do_msgrcv: don't leak host_mb upon TARGET_EFAULT failure
qemu-ga: don't leak a file descriptor upon failed lockf
i82378: Remove bogus MMIO coalescing
eventfd: making it thread safe
Update OpenBIOS images
pc: Fix RTC CMOS info on RAM for ram_size < 1MiB
vl: Round argument of -m up to multiple of 8KiB
scsi: fix warning
Avoid asprintf() which is not available on mingw
Update version to 1.2.0-rc0
qemu-char: (Re-)connect for tcp_chr_write() unconnected writing
Allow QEMUMachine to override reset sequencing
pseries: Instantiate USB interface when required
osdep: Fix compilation failure on BSD systems
Command line support for seccomp with -sandbox (v8)
Adding seccomp calls to vl.c (v8)
...
Conflicts:
hw/pc_piix.c
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
-rw-r--r-- | Makefile.objs | 6 | ||||
-rw-r--r-- | VERSION | 2 | ||||
-rw-r--r-- | block/sheepdog.c | 1 | ||||
-rwxr-xr-x | configure | 101 | ||||
-rw-r--r-- | dma-helpers.c | 4 | ||||
-rw-r--r-- | exec.c | 21 | ||||
-rw-r--r-- | hw/boards.h | 3 | ||||
-rw-r--r-- | hw/i82378.c | 1 | ||||
-rw-r--r-- | hw/msix.c | 8 | ||||
-rw-r--r-- | hw/pc.c | 31 | ||||
-rw-r--r-- | hw/pc_piix.c | 4 | ||||
-rw-r--r-- | hw/scsi-bus.c | 2 | ||||
-rw-r--r-- | hw/spapr.c | 10 | ||||
-rw-r--r-- | hw/virtio-blk.c | 1 | ||||
-rw-r--r-- | hw/virtio-blk.h | 3 | ||||
-rw-r--r-- | iohandler.c | 1 | ||||
-rw-r--r-- | json-parser.c | 230 | ||||
-rw-r--r-- | linux-user/syscall.c | 4 | ||||
-rw-r--r-- | osdep.c | 8 | ||||
-rw-r--r-- | osdep.h | 7 | ||||
-rw-r--r-- | pc-bios/README | 2 | ||||
-rw-r--r-- | pc-bios/openbios-ppc | bin | 729876 -> 729876 bytes | |||
-rw-r--r-- | pc-bios/openbios-sparc32 | bin | 381764 -> 381764 bytes | |||
-rw-r--r-- | pc-bios/openbios-sparc64 | bin | 1598648 -> 1598648 bytes | |||
-rw-r--r-- | qemu-char.c | 7 | ||||
-rw-r--r-- | qemu-config.c | 18 | ||||
-rw-r--r-- | qemu-config.h | 1 | ||||
-rw-r--r-- | qemu-ga.c | 3 | ||||
-rw-r--r-- | qemu-options.hx | 15 | ||||
-rw-r--r-- | qemu-seccomp.c | 141 | ||||
-rw-r--r-- | qemu-seccomp.h | 22 | ||||
-rw-r--r-- | qlist.c | 13 | ||||
-rw-r--r-- | qlist.h | 1 | ||||
-rw-r--r-- | rules.mak | 2 | ||||
-rw-r--r-- | softmmu-semi.h | 5 | ||||
-rw-r--r-- | sysemu.h | 1 | ||||
-rw-r--r-- | target-arm/arm-semi.c | 13 | ||||
-rw-r--r-- | tests/check-qjson.c | 53 | ||||
-rw-r--r-- | vl.c | 53 |
39 files changed, 641 insertions, 157 deletions
diff --git a/Makefile.objs b/Makefile.objs index 309d06628..441275730 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -97,6 +97,12 @@ common-obj-y += qemu-timer.o qemu-timer-common.o common-obj-$(CONFIG_SLIRP) += slirp/ ###################################################################### +# libseccomp +ifeq ($(CONFIG_SECCOMP),y) +common-obj-y += qemu-seccomp.o +endif + +###################################################################### # libuser user-obj-y = @@ -1 +1 @@ -1.1.50 +1.1.90 diff --git a/block/sheepdog.c b/block/sheepdog.c index a04ad99ea..df4f44107 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -485,6 +485,7 @@ static int connect_to_sdog(const char *addr, const char *port) if (errno == EINTR) { goto reconnect; } + close(fd); break; } @@ -229,6 +229,7 @@ zlib="yes" guest_agent="yes" libiscsi="" coroutine="" +seccomp="" # parse CC options first for opt do @@ -309,6 +310,41 @@ EOF compile_object } +if check_define __linux__ ; then + targetos="Linux" +elif check_define _WIN32 ; then + targetos='MINGW32' +elif check_define __OpenBSD__ ; then + targetos='OpenBSD' +elif check_define __sun__ ; then + targetos='SunOS' +elif check_define __HAIKU__ ; then + targetos='Haiku' +else + targetos=`uname -s` +fi + +# Some host OSes need non-standard checks for which CPU to use. +# Note that these checks are broken for cross-compilation: if you're +# cross-compiling to one of these OSes then you'll need to specify +# the correct CPU with the --cpu option. +case $targetos in +Darwin) + # on Leopard most of the system is 32-bit, so we have to ask the kernel if we can + # run 64-bit userspace code. + # If the user didn't specify a CPU explicitly and the kernel says this is + # 64 bit hw, then assume x86_64. Otherwise fall through to the usual detection code. + if test -z "$cpu" && test "$(sysctl -n hw.optional.x86_64)" = "1"; then + cpu="x86_64" + fi + ;; +SunOS) + # `uname -m` returns i86pc even on an x86_64 box, so default based on isainfo + if test -z "$cpu" && test "$(isainfo -k)" = "amd64"; then + cpu="x86_64" + fi +esac + if test ! -z "$cpu" ; then # command line argument : @@ -383,19 +419,6 @@ if test -z "$ARCH"; then fi # OS specific -if check_define __linux__ ; then - targetos="Linux" -elif check_define _WIN32 ; then - targetos='MINGW32' -elif check_define __OpenBSD__ ; then - targetos='OpenBSD' -elif check_define __sun__ ; then - targetos='SunOS' -elif check_define __HAIKU__ ; then - targetos='Haiku' -else - targetos=`uname -s` -fi case $targetos in CYGWIN*) @@ -445,12 +468,6 @@ OpenBSD) Darwin) bsd="yes" darwin="yes" - # on Leopard most of the system is 32-bit, so we have to ask the kernel it if we can - # run 64-bit userspace code - if [ "$cpu" = "i386" ] ; then - is_x86_64=`sysctl -n hw.optional.x86_64` - [ "$is_x86_64" = "1" ] && cpu=x86_64 - fi if [ "$cpu" = "x86_64" ] ; then QEMU_CFLAGS="-arch x86_64 $QEMU_CFLAGS" LDFLAGS="-arch x86_64 $LDFLAGS" @@ -462,6 +479,9 @@ Darwin) audio_possible_drivers="coreaudio sdl fmod" LDFLAGS="-framework CoreFoundation -framework IOKit $LDFLAGS" libs_softmmu="-F/System/Library/Frameworks -framework Cocoa -framework IOKit $libs_softmmu" + # Disable attempts to use ObjectiveC features in os/object.h since they + # won't work when we're compiling with gcc as a C compiler. + QEMU_CFLAGS="-DOS_OBJECT_USE_OBJC=0 $QEMU_CFLAGS" ;; SunOS) solaris="yes" @@ -471,12 +491,6 @@ SunOS) smbd="${SMBD-/usr/sfw/sbin/smbd}" needs_libsunmath="no" solarisrev=`uname -r | cut -f2 -d.` - # have to select again, because `uname -m` returns i86pc - # even on an x86_64 box. - solariscpu=`isainfo -k` - if test "${solariscpu}" = "amd64" ; then - cpu="x86_64" - fi if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then if test "$solarisrev" -le 9 ; then if test -f /opt/SUNWspro/prod/lib/libsunmath.so.1; then @@ -541,6 +555,13 @@ fi : ${python=${PYTHON-python}} : ${smbd=${SMBD-/usr/sbin/smbd}} +# Default objcc to clang if available, otherwise use CC +if has clang; then + objcc=clang +else + objcc="$cc" +fi + if test "$mingw32" = "yes" ; then EXESUF=".exe" QEMU_CFLAGS="-DWIN32_LEAN_AND_MEAN -DWINVER=0x501 $QEMU_CFLAGS" @@ -584,6 +605,8 @@ for opt do ;; --host-cc=*) host_cc="$optarg" ;; + --objcc=*) objcc="$optarg" + ;; --make=*) make="$optarg" ;; --install=*) install="$optarg" @@ -857,6 +880,10 @@ for opt do ;; --disable-guest-agent) guest_agent="no" ;; + --enable-seccomp) seccomp="yes" + ;; + --disable-seccomp) seccomp="no" + ;; *) echo "ERROR: unknown option $opt"; show_help="yes" ;; esac @@ -1030,6 +1057,7 @@ echo " --cross-prefix=PREFIX use PREFIX for compile tools [$cross_prefix]" echo " --cc=CC use C compiler CC [$cc]" echo " --host-cc=CC use C compiler CC [$host_cc] for code run at" echo " build time" +echo " --objcc=OBJCC use Objective-C compiler OBJCC [$objcc]" echo " --extra-cflags=CFLAGS append extra C compiler flags QEMU_CFLAGS" echo " --extra-ldflags=LDFLAGS append extra linker flags LDFLAGS" echo " --make=MAKE use specified make [$make]" @@ -1146,6 +1174,8 @@ echo " --disable-usb-redir disable usb network redirection support" echo " --enable-usb-redir enable usb network redirection support" echo " --disable-guest-agent disable building of the QEMU Guest Agent" echo " --enable-guest-agent enable building of the QEMU Guest Agent" +echo " --disable-seccomp disable seccomp support" +echo " --enable-seccomp enables seccomp support" echo " --with-coroutine=BACKEND coroutine backend. Supported options:" echo " gthread, ucontext, sigaltstack, windows" echo "" @@ -1408,6 +1438,20 @@ EOF fi ########################################## +# libseccomp check + +if test "$seccomp" != "no" ; then + if $pkg_config libseccomp --modversion >/dev/null 2>&1; then + LIBS=`$pkg_config --libs libseccomp` + seccomp="yes" + else + seccomp="no" + if test "$seccomp" = "yes"; then + feature_not_found "libseccomp" + fi + fi +fi +########################################## # xen probe if test "$xen" != "no" ; then @@ -3062,6 +3106,7 @@ fi echo "Source path $source_path" echo "C compiler $cc" echo "Host C compiler $host_cc" +echo "Objective-C compiler $objcc" echo "CFLAGS $CFLAGS" echo "QEMU_CFLAGS $QEMU_CFLAGS" echo "LDFLAGS $LDFLAGS" @@ -3137,6 +3182,7 @@ echo "usb net redir $usb_redir" echo "OpenGL support $opengl" echo "libiscsi support $libiscsi" echo "build guest agent $guest_agent" +echo "seccomp support $seccomp" echo "coroutine backend $coroutine_backend" if test "$sdl_too_old" = "yes"; then @@ -3432,6 +3478,10 @@ if test "$libiscsi" = "yes" ; then echo "CONFIG_LIBISCSI=y" >> $config_host_mak fi +if test "$seccomp" = "yes"; then + echo "CONFIG_SECCOMP=y" >> $config_host_mak +fi + # XXX: suppress that if [ "$bsd" = "yes" ] ; then echo "CONFIG_BSD=y" >> $config_host_mak @@ -3526,6 +3576,7 @@ echo "PYTHON=$python" >> $config_host_mak echo "CC=$cc" >> $config_host_mak echo "CC_I386=$cc_i386" >> $config_host_mak echo "HOST_CC=$host_cc" >> $config_host_mak +echo "OBJCC=$objcc" >> $config_host_mak echo "AR=$ar" >> $config_host_mak echo "OBJCOPY=$objcopy" >> $config_host_mak echo "LD=$ld" >> $config_host_mak diff --git a/dma-helpers.c b/dma-helpers.c index 13593d1b4..433d8b21b 100644 --- a/dma-helpers.c +++ b/dma-helpers.c @@ -24,8 +24,8 @@ static void do_dma_memory_set(dma_addr_t addr, uint8_t c, dma_addr_t len) while (len > 0) { l = len < FILLBUF_SIZE ? len : FILLBUF_SIZE; cpu_physical_memory_rw(addr, fillbuf, l, true); - len -= len; - addr += len; + len -= l; + addr += l; } } @@ -2475,6 +2475,24 @@ static ram_addr_t last_ram_offset(void) return last; } +static void qemu_ram_setup_dump(void *addr, ram_addr_t size) +{ + int ret; + QemuOpts *machine_opts; + + /* Use MADV_DONTDUMP, if user doesn't want the guest memory in the core */ + machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0); + if (machine_opts && + !qemu_opt_get_bool(machine_opts, "dump-guest-core", true)) { + ret = qemu_madvise(addr, size, QEMU_MADV_DONTDUMP); + if (ret) { + perror("qemu_madvise"); + fprintf(stderr, "madvise doesn't support MADV_DONTDUMP, " + "but dump_guest_core=off specified\n"); + } + } +} + void qemu_ram_set_idstr(ram_addr_t addr, const char *name, DeviceState *dev) { RAMBlock *new_block, *block; @@ -2554,6 +2572,8 @@ ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, 0, size >> TARGET_PAGE_BITS); cpu_physical_memory_set_dirty_range(new_block->offset, size, 0xff); + qemu_ram_setup_dump(new_block->host, size); + if (kvm_enabled()) kvm_setup_guest_memory(new_block->host, size); @@ -2670,6 +2690,7 @@ void qemu_ram_remap(ram_addr_t addr, ram_addr_t length) exit(1); } qemu_madvise(vaddr, length, QEMU_MADV_MERGEABLE); + qemu_ram_setup_dump(vaddr, length); } return; } diff --git a/hw/boards.h b/hw/boards.h index 59c01d036..a2e0a5449 100644 --- a/hw/boards.h +++ b/hw/boards.h @@ -12,11 +12,14 @@ typedef void QEMUMachineInitFunc(ram_addr_t ram_size, const char *initrd_filename, const char *cpu_model); +typedef void QEMUMachineResetFunc(void); + typedef struct QEMUMachine { const char *name; const char *alias; const char *desc; QEMUMachineInitFunc *init; + QEMUMachineResetFunc *reset; int use_scsi; int max_cpus; unsigned int no_serial:1, diff --git a/hw/i82378.c b/hw/i82378.c index 9b11d907e..2123c142a 100644 --- a/hw/i82378.c +++ b/hw/i82378.c @@ -225,7 +225,6 @@ static int pci_i82378_init(PCIDevice *dev) pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->io); memory_region_init_io(&s->mem, &i82378_mem_ops, s, "i82378-mem", 0x01000000); - memory_region_set_coalescing(&s->mem); pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mem); /* Make I/O address read only */ @@ -307,13 +307,9 @@ int msix_init_exclusive_bar(PCIDevice *dev, unsigned short nentries, return -EINVAL; } - if (asprintf(&name, "%s-msix", dev->name) == -1) { - return -ENOMEM; - } - + name = g_strdup_printf("%s-msix", dev->name); memory_region_init(&dev->msix_exclusive_bar, name, MSIX_EXCLUSIVE_BAR_SIZE); - - free(name); + g_free(name); ret = msix_init(dev, nentries, &dev->msix_exclusive_bar, bar_nr, MSIX_EXCLUSIVE_BAR_TABLE_OFFSET, &dev->msix_exclusive_bar, @@ -338,32 +338,37 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size, /* various important CMOS locations needed by PC/Bochs bios */ /* memory size */ - val = 640; /* base memory in K */ + /* base memory (first MiB) */ + val = MIN(ram_size / 1024, 640); rtc_set_memory(s, 0x15, val); rtc_set_memory(s, 0x16, val >> 8); - - val = (ram_size / 1024) - 1024; + /* extended memory (next 64MiB) */ + if (ram_size > 1024 * 1024) { + val = (ram_size - 1024 * 1024) / 1024; + } else { + val = 0; + } if (val > 65535) val = 65535; rtc_set_memory(s, 0x17, val); rtc_set_memory(s, 0x18, val >> 8); rtc_set_memory(s, 0x30, val); rtc_set_memory(s, 0x31, val >> 8); - - if (above_4g_mem_size) { - rtc_set_memory(s, 0x5b, (unsigned int)above_4g_mem_size >> 16); - rtc_set_memory(s, 0x5c, (unsigned int)above_4g_mem_size >> 24); - rtc_set_memory(s, 0x5d, (uint64_t)above_4g_mem_size >> 32); - } - - if (ram_size > (16 * 1024 * 1024)) - val = (ram_size / 65536) - ((16 * 1024 * 1024) / 65536); - else + /* memory between 16MiB and 4GiB */ + if (ram_size > 16 * 1024 * 1024) { + val = (ram_size - 16 * 1024 * 1024) / 65536; + } else { val = 0; + } if (val > 65535) val = 65535; rtc_set_memory(s, 0x34, val); rtc_set_memory(s, 0x35, val >> 8); + /* memory above 4GiB */ + val = above_4g_mem_size / 65536; + rtc_set_memory(s, 0x5b, val); + rtc_set_memory(s, 0x5c, val >> 8); + rtc_set_memory(s, 0x5d, val >> 16); /* set the number of CPU */ rtc_set_memory(s, 0x5f, smp_cpus - 1); diff --git a/hw/pc_piix.c b/hw/pc_piix.c index 5860d5263..bc18fdccf 100644 --- a/hw/pc_piix.c +++ b/hw/pc_piix.c @@ -386,6 +386,10 @@ static QEMUMachine pc_machine_v1_2 = { .driver = "qxl",\ .property = "vgamem_mb",\ .value = stringify(16),\ + },{\ + .driver = "virtio-blk-pci",\ + .property = "config-wce",\ + .value = "off",\ } static QEMUMachine pc_machine_v1_1 = { diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c index b8a857d14..4981a0243 100644 --- a/hw/scsi-bus.c +++ b/hw/scsi-bus.c @@ -761,6 +761,7 @@ static int ata_passthrough_12_xfer_size(SCSIDevice *dev, uint8_t *buf) switch (length) { case 0: case 3: /* USB-specific. */ + default: xfer = 0; break; case 1: @@ -784,6 +785,7 @@ static int ata_passthrough_16_xfer_size(SCSIDevice *dev, uint8_t *buf) switch (length) { case 0: case 3: /* USB-specific. */ + default: xfer = 0; break; case 1: diff --git a/hw/spapr.c b/hw/spapr.c index 5178721d4..be533ee93 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -49,6 +49,7 @@ #include "vga-pci.h" #include "exec-memory.h" +#include "hw/usb.h" #include <libfdt.h> @@ -765,6 +766,15 @@ static void ppc_spapr_init(ram_addr_t ram_size, spapr->has_graphics = true; } + if (usb_enabled) { + pci_create_simple(QLIST_FIRST(&spapr->phbs)->host_state.bus, + -1, "pci-ohci"); + if (spapr->has_graphics) { + usbdevice_create("keyboard"); + usbdevice_create("mouse"); + } + } + if (rma_size < (MIN_RMA_SLOF << 20)) { fprintf(stderr, "qemu: pSeries SLOF firmware requires >= " "%ldM guest RMA (Real Mode Area memory)\n", MIN_RMA_SLOF); diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c index fd8fa9079..6f6d172fd 100644 --- a/hw/virtio-blk.c +++ b/hw/virtio-blk.c @@ -533,7 +533,6 @@ static uint32_t virtio_blk_get_features(VirtIODevice *vdev, uint32_t features) features |= (1 << VIRTIO_BLK_F_BLK_SIZE); features |= (1 << VIRTIO_BLK_F_SCSI); - features |= (1 << VIRTIO_BLK_F_CONFIG_WCE); if (bdrv_enable_write_cache(s->bs)) features |= (1 << VIRTIO_BLK_F_WCE); diff --git a/hw/virtio-blk.h b/hw/virtio-blk.h index 35834cf49..651a000b9 100644 --- a/hw/virtio-blk.h +++ b/hw/virtio-blk.h @@ -107,6 +107,7 @@ struct VirtIOBlkConf }; #define DEFINE_VIRTIO_BLK_FEATURES(_state, _field) \ - DEFINE_VIRTIO_COMMON_FEATURES(_state, _field) + DEFINE_VIRTIO_COMMON_FEATURES(_state, _field), \ + DEFINE_PROP_BIT("config-wce", _state, _field, VIRTIO_BLK_F_CONFIG_WCE, true) #endif diff --git a/iohandler.c b/iohandler.c index 3c74de612..dea43552d 100644 --- a/iohandler.c +++ b/iohandler.c @@ -77,6 +77,7 @@ int qemu_set_fd_handler2(int fd, ioh->fd_write = fd_write; ioh->opaque = opaque; ioh->deleted = 0; + qemu_notify_event(); } return 0; } diff --git a/json-parser.c b/json-parser.c index 849e2156d..457291b16 100644 --- a/json-parser.c +++ b/json-parser.c @@ -27,6 +27,11 @@ typedef struct JSONParserContext { Error *err; + struct { + QObject **buf; + size_t pos; + size_t count; + } tokens; } JSONParserContext; #define BUG_ON(cond) assert(!(cond)) @@ -40,7 +45,7 @@ typedef struct JSONParserContext * 4) deal with premature EOI */ -static QObject *parse_value(JSONParserContext *ctxt, QList **tokens, va_list *ap); +static QObject *parse_value(JSONParserContext *ctxt, va_list *ap); /** * Token manipulators @@ -270,27 +275,111 @@ out: return NULL; } +static QObject *parser_context_pop_token(JSONParserContext *ctxt) +{ + QObject *token; + g_assert(ctxt->tokens.pos < ctxt->tokens.count); + token = ctxt->tokens.buf[ctxt->tokens.pos]; + ctxt->tokens.pos++; + return token; +} + +/* Note: parser_context_{peek|pop}_token do not increment the + * token object's refcount. In both cases the references will continue + * to be tracked and cleaned up in parser_context_free(), so do not + * attempt to free the token object. + */ +static QObject *parser_context_peek_token(JSONParserContext *ctxt) +{ + QObject *token; + g_assert(ctxt->tokens.pos < ctxt->tokens.count); + token = ctxt->tokens.buf[ctxt->tokens.pos]; + return token; +} + +static JSONParserContext parser_context_save(JSONParserContext *ctxt) +{ + JSONParserContext saved_ctxt = {0}; + saved_ctxt.tokens.pos = ctxt->tokens.pos; + saved_ctxt.tokens.count = ctxt->tokens.count; + saved_ctxt.tokens.buf = ctxt->tokens.buf; + return saved_ctxt; +} + +static void parser_context_restore(JSONParserContext *ctxt, + JSONParserContext saved_ctxt) +{ + ctxt->tokens.pos = saved_ctxt.tokens.pos; + ctxt->tokens.count = saved_ctxt.tokens.count; + ctxt->tokens.buf = saved_ctxt.tokens.buf; +} + +static void tokens_append_from_iter(QObject *obj, void *opaque) +{ + JSONParserContext *ctxt = opaque; + g_assert(ctxt->tokens.pos < ctxt->tokens.count); + ctxt->tokens.buf[ctxt->tokens.pos++] = obj; + qobject_incref(obj); +} + +static JSONParserContext *parser_context_new(QList *tokens) +{ + JSONParserContext *ctxt; + size_t count; + + if (!tokens) { + return NULL; + } + + count = qlist_size(tokens); + if (count == 0) { + return NULL; + } + + ctxt = g_malloc0(sizeof(JSONParserContext)); + ctxt->tokens.pos = 0; + ctxt->tokens.count = count; + ctxt->tokens.buf = g_malloc(count * sizeof(QObject *)); + qlist_iter(tokens, tokens_append_from_iter, ctxt); + ctxt->tokens.pos = 0; + + return ctxt; +} + +/* to support error propagation, ctxt->err must be freed separately */ +static void parser_context_free(JSONParserContext *ctxt) +{ + int i; + if (ctxt) { + for (i = 0; i < ctxt->tokens.count; i++) { + qobject_decref(ctxt->tokens.buf[i]); + } + g_free(ctxt->tokens.buf); + g_free(ctxt); + } +} + /** * Parsing rules */ -static int parse_pair(JSONParserContext *ctxt, QDict *dict, QList **tokens, va_list *ap) +static int parse_pair(JSONParserContext *ctxt, QDict *dict, va_list *ap) { QObject *key = NULL, *token = NULL, *value, *peek; - QList *working = qlist_copy(*tokens); + JSONParserContext saved_ctxt = parser_context_save(ctxt); - peek = qlist_peek(working); + peek = parser_context_peek_token(ctxt); if (peek == NULL) { parse_error(ctxt, NULL, "premature EOI"); goto out; } - key = parse_value(ctxt, &working, ap); + key = parse_value(ctxt, ap); if (!key || qobject_type(key) != QTYPE_QSTRING) { parse_error(ctxt, peek, "key is not a string in object"); goto out; } - token = qlist_pop(working); + token = parser_context_pop_token(ctxt); if (token == NULL) { parse_error(ctxt, NULL, "premature EOI"); goto out; @@ -301,7 +390,7 @@ static int parse_pair(JSONParserContext *ctxt, QDict *dict, QList **tokens, va_l goto out; } - value = parse_value(ctxt, &working, ap); + value = parse_value(ctxt, ap); if (value == NULL) { parse_error(ctxt, token, "Missing value in dict"); goto out; @@ -309,28 +398,24 @@ static int parse_pair(JSONParserContext *ctxt, QDict *dict, QList **tokens, va_l qdict_put_obj(dict, qstring_get_str(qobject_to_qstring(key)), value); - qobject_decref(token); qobject_decref(key); - QDECREF(*tokens); - *tokens = working; return 0; out: - qobject_decref(token); + parser_context_restore(ctxt, saved_ctxt); qobject_decref(key); - QDECREF(working); return -1; } -static QObject *parse_object(JSONParserContext *ctxt, QList **tokens, va_list *ap) +static QObject *parse_object(JSONParserContext *ctxt, va_list *ap) { QDict *dict = NULL; QObject *token, *peek; - QList *working = qlist_copy(*tokens); + JSONParserContext saved_ctxt = parser_context_save(ctxt); - token = qlist_pop(working); + token = parser_context_pop_token(ctxt); if (token == NULL) { goto out; } @@ -338,23 +423,22 @@ static QObject *parse_object(JSONParserContext *ctxt, QList **tokens, va_list *a if (!token_is_operator(token, '{')) { goto out; } - qobject_decref(token); token = NULL; dict = qdict_new(); - peek = qlist_peek(working); + peek = parser_context_peek_token(ctxt); if (peek == NULL) { parse_error(ctxt, NULL, "premature EOI"); goto out; } if (!token_is_operator(peek, '}')) { - if (parse_pair(ctxt, dict, &working, ap) == -1) { + if (parse_pair(ctxt, dict, ap) == -1) { goto out; } - token = qlist_pop(working); + token = parser_context_pop_token(ctxt); if (token == NULL) { parse_error(ctxt, NULL, "premature EOI"); goto out; @@ -365,59 +449,52 @@ static QObject *parse_object(JSONParserContext *ctxt, QList **tokens, va_list *a parse_error(ctxt, token, "expected separator in dict"); goto out; } - qobject_decref(token); token = NULL; - if (parse_pair(ctxt, dict, &working, ap) == -1) { + if (parse_pair(ctxt, dict, ap) == -1) { goto out; } - token = qlist_pop(working); + token = parser_context_pop_token(ctxt); if (token == NULL) { parse_error(ctxt, NULL, "premature EOI"); goto out; } } - qobject_decref(token); token = NULL; } else { - token = qlist_pop(working); - qobject_decref(token); + token = parser_context_pop_token(ctxt); token = NULL; } - QDECREF(*tokens); - *tokens = working; - return QOBJECT(dict); out: - qobject_decref(token); - QDECREF(working); + parser_context_restore(ctxt, saved_ctxt); QDECREF(dict); return NULL; } -static QObject *parse_array(JSONParserContext *ctxt, QList **tokens, va_list *ap) +static QObject *parse_array(JSONParserContext *ctxt, va_list *ap) { QList *list = NULL; QObject *token, *peek; - QList *working = qlist_copy(*tokens); + JSONParserContext saved_ctxt = parser_context_save(ctxt); - token = qlist_pop(working); + token = parser_context_pop_token(ctxt); if (token == NULL) { goto out; } if (!token_is_operator(token, '[')) { + token = NULL; goto out; } - qobject_decref(token); token = NULL; list = qlist_new(); - peek = qlist_peek(working); + peek = parser_context_peek_token(ctxt); if (peek == NULL) { parse_error(ctxt, NULL, "premature EOI"); goto out; @@ -426,7 +503,7 @@ static QObject *parse_array(JSONParserContext *ctxt, QList **tokens, va_list *ap if (!token_is_operator(peek, ']')) { QObject *obj; - obj = parse_value(ctxt, &working, ap); + obj = parse_value(ctxt, ap); if (obj == NULL) { parse_error(ctxt, token, "expecting value"); goto out; @@ -434,7 +511,7 @@ static QObject *parse_array(JSONParserContext *ctxt, QList **tokens, va_list *ap qlist_append_obj(list, obj); - token = qlist_pop(working); + token = parser_context_pop_token(ctxt); if (token == NULL) { parse_error(ctxt, NULL, "premature EOI"); goto out; @@ -446,10 +523,9 @@ static QObject *parse_array(JSONParserContext *ctxt, QList **tokens, va_list *ap goto out; } - qobject_decref(token); token = NULL; - obj = parse_value(ctxt, &working, ap); + obj = parse_value(ctxt, ap); if (obj == NULL) { parse_error(ctxt, token, "expecting value"); goto out; @@ -457,39 +533,33 @@ static QObject *parse_array(JSONParserContext *ctxt, QList **tokens, va_list *ap qlist_append_obj(list, obj); - token = qlist_pop(working); + token = parser_context_pop_token(ctxt); if (token == NULL) { parse_error(ctxt, NULL, "premature EOI"); goto out; } } - qobject_decref(token); token = NULL; } else { - token = qlist_pop(working); - qobject_decref(token); + token = parser_context_pop_token(ctxt); token = NULL; } - QDECREF(*tokens); - *tokens = working; - return QOBJECT(list); out: - qobject_decref(token); - QDECREF(working); + parser_context_restore(ctxt, saved_ctxt); QDECREF(list); return NULL; } -static QObject *parse_keyword(JSONParserContext *ctxt, QList **tokens) +static QObject *parse_keyword(JSONParserContext *ctxt) { QObject *token, *ret; - QList *working = qlist_copy(*tokens); + JSONParserContext saved_ctxt = parser_context_save(ctxt); - token = qlist_pop(working); + token = parser_context_pop_token(ctxt); if (token == NULL) { goto out; } @@ -507,29 +577,24 @@ static QObject *parse_keyword(JSONParserContext *ctxt, QList **tokens) goto out; } - qobject_decref(token); - QDECREF(*tokens); - *tokens = working; - return ret; out: - qobject_decref(token); - QDECREF(working); + parser_context_restore(ctxt, saved_ctxt); return NULL; } -static QObject *parse_escape(JSONParserContext *ctxt, QList **tokens, va_list *ap) +static QObject *parse_escape(JSONParserContext *ctxt, va_list *ap) { QObject *token = NULL, *obj; - QList *working = qlist_copy(*tokens); + JSONParserContext saved_ctxt = parser_context_save(ctxt); if (ap == NULL) { goto out; } - token = qlist_pop(working); + token = parser_context_pop_token(ctxt); if (token == NULL) { goto out; } @@ -553,25 +618,20 @@ static QObject *parse_escape(JSONParserContext *ctxt, QList **tokens, va_list *a goto out; } - qobject_decref(token); - QDECREF(*tokens); - *tokens = working; - return obj; out: - qobject_decref(token); - QDECREF(working); + parser_context_restore(ctxt, saved_ctxt); return NULL; } -static QObject *parse_literal(JSONParserContext *ctxt, QList **tokens) +static QObject *parse_literal(JSONParserContext *ctxt) { QObject *token, *obj; - QList *working = qlist_copy(*tokens); + JSONParserContext saved_ctxt = parser_context_save(ctxt); - token = qlist_pop(working); + token = parser_context_pop_token(ctxt); if (token == NULL) { goto out; } @@ -591,35 +651,30 @@ static QObject *parse_literal(JSONParserContext *ctxt, QList **tokens) goto out; } - qobject_decref(token); - QDECREF(*tokens); - *tokens = working; - return obj; out: - qobject_decref(token); - QDECREF(working); + parser_context_restore(ctxt, saved_ctxt); return NULL; } -static QObject *parse_value(JSONParserContext *ctxt, QList **tokens, va_list *ap) +static QObject *parse_value(JSONParserContext *ctxt, va_list *ap) { QObject *obj; - obj = parse_object(ctxt, tokens, ap); + obj = parse_object(ctxt, ap); if (obj == NULL) { - obj = parse_array(ctxt, tokens, ap); + obj = parse_array(ctxt, ap); } if (obj == NULL) { - obj = parse_escape(ctxt, tokens, ap); + obj = parse_escape(ctxt, ap); } if (obj == NULL) { - obj = parse_keyword(ctxt, tokens); + obj = parse_keyword(ctxt); } if (obj == NULL) { - obj = parse_literal(ctxt, tokens); + obj = parse_literal(ctxt); } return obj; @@ -632,19 +687,18 @@ QObject *json_parser_parse(QList *tokens, va_list *ap) QObject *json_parser_parse_err(QList *tokens, va_list *ap, Error **errp) { - JSONParserContext ctxt = {}; - QList *working; + JSONParserContext *ctxt = parser_context_new(tokens); QObject *result; - if (!tokens) { + if (!ctxt) { return NULL; } - working = qlist_copy(tokens); - result = parse_value(&ctxt, &working, ap); - QDECREF(working); + result = parse_value(ctxt, ap); + + error_propagate(errp, ctxt->err); - error_propagate(errp, ctxt.err); + parser_context_free(ctxt); return result; } diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 41c869bfe..11743065e 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -2848,7 +2848,7 @@ static inline abi_long do_msgrcv(int msqid, abi_long msgp, if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0)) return -TARGET_EFAULT; - host_mb = malloc(msgsz+sizeof(long)); + host_mb = g_malloc(msgsz+sizeof(long)); ret = get_errno(msgrcv(msqid, host_mb, msgsz, tswapal(msgtyp), msgflg)); if (ret > 0) { @@ -2863,11 +2863,11 @@ static inline abi_long do_msgrcv(int msqid, abi_long msgp, } target_mb->mtype = tswapal(host_mb->mtype); - free(host_mb); end: if (target_mb) unlock_user_struct(target_mb, msgp, 1); + g_free(host_mb); return ret; } @@ -113,7 +113,13 @@ static int qemu_dup_flags(int fd, int flags) } /* Set/unset flags that we can with fcntl */ - setfl_flags = O_APPEND | O_ASYNC | O_DIRECT | O_NOATIME | O_NONBLOCK; + setfl_flags = O_APPEND | O_ASYNC | O_NONBLOCK; +#ifdef O_NOATIME + setfl_flags |= O_NOATIME; +#endif +#ifdef O_DIRECT + setfl_flags |= O_DIRECT; +#endif dup_flags &= ~setfl_flags; dup_flags |= (flags & setfl_flags); if (fcntl(ret, F_SETFL, dup_flags) == -1) { @@ -103,6 +103,11 @@ void qemu_vfree(void *ptr); #else #define QEMU_MADV_MERGEABLE QEMU_MADV_INVALID #endif +#ifdef MADV_DONTDUMP +#define QEMU_MADV_DONTDUMP MADV_DONTDUMP +#else +#define QEMU_MADV_DONTDUMP QEMU_MADV_INVALID +#endif #elif defined(CONFIG_POSIX_MADVISE) @@ -110,6 +115,7 @@ void qemu_vfree(void *ptr); #define QEMU_MADV_DONTNEED POSIX_MADV_DONTNEED #define QEMU_MADV_DONTFORK QEMU_MADV_INVALID #define QEMU_MADV_MERGEABLE QEMU_MADV_INVALID +#define QEMU_MADV_DONTDUMP QEMU_MADV_INVALID #else /* no-op */ @@ -117,6 +123,7 @@ void qemu_vfree(void *ptr); #define QEMU_MADV_DONTNEED QEMU_MADV_INVALID #define QEMU_MADV_DONTFORK QEMU_MADV_INVALID #define QEMU_MADV_MERGEABLE QEMU_MADV_INVALID +#define QEMU_MADV_DONTDUMP QEMU_MADV_INVALID #endif diff --git a/pc-bios/README b/pc-bios/README index f4b37d66d..fc07ebc21 100644 --- a/pc-bios/README +++ b/pc-bios/README @@ -12,7 +12,7 @@ 1275-1994 (referred to as Open Firmware) compliant firmware. The included images for PowerPC (for 32 and 64 bit PPC CPUs), Sparc32 and Sparc64 are built from OpenBIOS SVN revision - 1060. + 1062. - SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware implementation for certain IBM POWER hardware. The sources are at diff --git a/pc-bios/openbios-ppc b/pc-bios/openbios-ppc Binary files differindex aeae26588..1c3753d3e 100644 --- a/pc-bios/openbios-ppc +++ b/pc-bios/openbios-ppc diff --git a/pc-bios/openbios-sparc32 b/pc-bios/openbios-sparc32 Binary files differindex d90c4e59a..6bd8e45d8 100644 --- a/pc-bios/openbios-sparc32 +++ b/pc-bios/openbios-sparc32 diff --git a/pc-bios/openbios-sparc64 b/pc-bios/openbios-sparc64 Binary files differindex 457d26422..7c06fcc5a 100644 --- a/pc-bios/openbios-sparc64 +++ b/pc-bios/openbios-sparc64 diff --git a/qemu-char.c b/qemu-char.c index 10d150494..398baf1e0 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -2141,14 +2141,17 @@ typedef struct { static void tcp_chr_accept(void *opaque); +static void tcp_chr_connect(void *opaque); + static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len) { TCPCharDriver *s = chr->opaque; if (s->connected) { return send_all(s->fd, buf, len); } else { - /* XXX: indicate an error ? */ - return len; + /* (Re-)connect for unconnected writing */ + tcp_chr_connect(chr); + return 0; } } diff --git a/qemu-config.c b/qemu-config.c index 54694cce2..238390e81 100644 --- a/qemu-config.c +++ b/qemu-config.c @@ -366,6 +366,19 @@ static QemuOptsList qemu_global_opts = { }, }; +QemuOptsList qemu_sandbox_opts = { + .name = "sandbox", + .implied_opt_name = "enable", + .head = QTAILQ_HEAD_INITIALIZER(qemu_sandbox_opts.head), + .desc = { + { + .name = "enable", + .type = QEMU_OPT_BOOL, + }, + { /* end of list */ } + }, +}; + static QemuOptsList qemu_mon_opts = { .name = "mon", .implied_opt_name = "chardev", @@ -599,6 +612,10 @@ static QemuOptsList qemu_machine_opts = { .name = "dt_compatible", .type = QEMU_OPT_STRING, .help = "Overrides the \"compatible\" property of the dt root node", + }, { + .name = "dump-guest-core", + .type = QEMU_OPT_BOOL, + .help = "Include guest memory in a core dump", }, { /* End of list */ } }, @@ -645,6 +662,7 @@ static QemuOptsList *vm_config_groups[32] = { &qemu_machine_opts, &qemu_boot_opts, &qemu_iscsi_opts, + &qemu_sandbox_opts, NULL, }; diff --git a/qemu-config.h b/qemu-config.h index 12ddf3ed9..5557562c3 100644 --- a/qemu-config.h +++ b/qemu-config.h @@ -6,6 +6,7 @@ extern QemuOptsList qemu_fsdev_opts; extern QemuOptsList qemu_virtfs_opts; extern QemuOptsList qemu_spice_opts; +extern QemuOptsList qemu_sandbox_opts; QemuOptsList *qemu_find_opts(const char *group); QemuOptsList *qemu_find_opts_err(const char *group, Error **errp); @@ -247,6 +247,9 @@ static bool ga_open_pidfile(const char *pidfile) pidfd = open(pidfile, O_CREAT|O_WRONLY, S_IRUSR|S_IWUSR); if (pidfd == -1 || lockf(pidfd, F_TLOCK, 0)) { g_critical("Cannot lock pid file, %s", strerror(errno)); + if (pidfd != -1) { + close(pidfd); + } return false; } diff --git a/qemu-options.hx b/qemu-options.hx index 2da170d08..ea06324e5 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -37,7 +37,8 @@ DEF("machine", HAS_ARG, QEMU_OPTION_machine, \ " property accel=accel1[:accel2[:...]] selects accelerator\n" " supported accelerators are kvm, xen, tcg (default: tcg)\n" " kernel_irqchip=on|off controls accelerated irqchip support\n" - " kvm_shadow_mem=size of KVM shadow MMU\n", + " kvm_shadow_mem=size of KVM shadow MMU\n" + " dump-guest-core=on|off include guest memory in a core dump (default=on)\n", QEMU_ARCH_ALL) STEXI @item -machine [type=]@var{name}[,prop=@var{value}[,...]] @@ -54,6 +55,8 @@ to initialize. Enables in-kernel irqchip support for the chosen accelerator when available. @item kvm_shadow_mem=size Defines the size of the KVM shadow MMU. +@item dump-guest-core=on|off +Include guest memory in a core dump. The default is on. @end table ETEXI @@ -2720,6 +2723,16 @@ STEXI Old param mode (ARM only). ETEXI +DEF("sandbox", HAS_ARG, QEMU_OPTION_sandbox, \ + "-sandbox <arg> Enable seccomp mode 2 system call filter (default 'off').\n", + QEMU_ARCH_ALL) +STEXI +@item -sandbox +@findex -sandbox +Enable Seccomp mode 2 system call filter. 'on' will enable syscall filtering and 'off' will +disable it. The default is 'off'. +ETEXI + DEF("readconfig", HAS_ARG, QEMU_OPTION_readconfig, "-readconfig <file>\n", QEMU_ARCH_ALL) STEXI diff --git a/qemu-seccomp.c b/qemu-seccomp.c new file mode 100644 index 000000000..64329a3c0 --- /dev/null +++ b/qemu-seccomp.c @@ -0,0 +1,141 @@ +/* + * QEMU seccomp mode 2 support with libseccomp + * + * Copyright IBM, Corp. 2012 + * + * Authors: + * Eduardo Otubo <eotubo@br.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + * Contributions after 2012-01-13 are licensed under the terms of the + * GNU GPL, version 2 or (at your option) any later version. + */ +#include <stdio.h> +#include <seccomp.h> +#include "qemu-seccomp.h" + +struct QemuSeccompSyscall { + int32_t num; + uint8_t priority; +}; + +static const struct QemuSeccompSyscall seccomp_whitelist[] = { + { SCMP_SYS(timer_settime), 255 }, + { SCMP_SYS(timer_gettime), 254 }, + { SCMP_SYS(futex), 253 }, + { SCMP_SYS(select), 252 }, + { SCMP_SYS(recvfrom), 251 }, + { SCMP_SYS(sendto), 250 }, + { SCMP_SYS(read), 249 }, + { SCMP_SYS(brk), 248 }, + { SCMP_SYS(clone), 247 }, + { SCMP_SYS(mmap), 247 }, + { SCMP_SYS(mprotect), 246 }, + { SCMP_SYS(execve), 245 }, + { SCMP_SYS(open), 245 }, + { SCMP_SYS(ioctl), 245 }, + { SCMP_SYS(recvmsg), 245 }, + { SCMP_SYS(sendmsg), 245 }, + { SCMP_SYS(accept), 245 }, + { SCMP_SYS(connect), 245 }, + { SCMP_SYS(gettimeofday), 245 }, + { SCMP_SYS(readlink), 245 }, + { SCMP_SYS(access), 245 }, + { SCMP_SYS(prctl), 245 }, + { SCMP_SYS(signalfd), 245 }, +#if defined(__i386__) + { SCMP_SYS(fcntl64), 245 }, + { SCMP_SYS(fstat64), 245 }, + { SCMP_SYS(stat64), 245 }, + { SCMP_SYS(getgid32), 245 }, + { SCMP_SYS(getegid32), 245 }, + { SCMP_SYS(getuid32), 245 }, + { SCMP_SYS(geteuid32), 245 }, + { SCMP_SYS(sigreturn), 245 }, + { SCMP_SYS(_newselect), 245 }, + { SCMP_SYS(_llseek), 245 }, + { SCMP_SYS(mmap2), 245}, + { SCMP_SYS(sigprocmask), 245 }, +#elif defined(__x86_64__) + { SCMP_SYS(sched_getparam), 245}, + { SCMP_SYS(sched_getscheduler), 245}, + { SCMP_SYS(fstat), 245}, + { SCMP_SYS(clock_getres), 245}, + { SCMP_SYS(sched_get_priority_min), 245}, + { SCMP_SYS(sched_get_priority_max), 245}, + { SCMP_SYS(stat), 245}, + { SCMP_SYS(socket), 245}, + { SCMP_SYS(setsockopt), 245}, + { SCMP_SYS(uname), 245}, + { SCMP_SYS(semget), 245}, +#endif + { SCMP_SYS(eventfd2), 245 }, + { SCMP_SYS(dup), 245 }, + { SCMP_SYS(gettid), 245 }, + { SCMP_SYS(timer_create), 245 }, + { SCMP_SYS(exit), 245 }, + { SCMP_SYS(clock_gettime), 245 }, + { SCMP_SYS(time), 245 }, + { SCMP_SYS(restart_syscall), 245 }, + { SCMP_SYS(pwrite64), 245 }, + { SCMP_SYS(chown), 245 }, + { SCMP_SYS(openat), 245 }, + { SCMP_SYS(getdents), 245 }, + { SCMP_SYS(timer_delete), 245 }, + { SCMP_SYS(exit_group), 245 }, + { SCMP_SYS(rt_sigreturn), 245 }, + { SCMP_SYS(sync), 245 }, + { SCMP_SYS(pread64), 245 }, + { SCMP_SYS(madvise), 245 }, + { SCMP_SYS(set_robust_list), 245 }, + { SCMP_SYS(lseek), 245 }, + { SCMP_SYS(pselect6), 245 }, + { SCMP_SYS(fork), 245 }, + { SCMP_SYS(bind), 245 }, + { SCMP_SYS(listen), 245 }, + { SCMP_SYS(eventfd), 245 }, + { SCMP_SYS(rt_sigprocmask), 245 }, + { SCMP_SYS(write), 244 }, + { SCMP_SYS(fcntl), 243 }, + { SCMP_SYS(tgkill), 242 }, + { SCMP_SYS(rt_sigaction), 242 }, + { SCMP_SYS(pipe2), 242 }, + { SCMP_SYS(munmap), 242 }, + { SCMP_SYS(mremap), 242 }, + { SCMP_SYS(getsockname), 242 }, + { SCMP_SYS(getpeername), 242 }, + { SCMP_SYS(fdatasync), 242 }, + { SCMP_SYS(close), 242 } +}; + +int seccomp_start(void) +{ + int rc = 0; + unsigned int i = 0; + scmp_filter_ctx ctx; + + ctx = seccomp_init(SCMP_ACT_KILL); + if (ctx == NULL) { + goto seccomp_return; + } + + for (i = 0; i < ARRAY_SIZE(seccomp_whitelist); i++) { + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, seccomp_whitelist[i].num, 0); + if (rc < 0) { + goto seccomp_return; + } + rc = seccomp_syscall_priority(ctx, seccomp_whitelist[i].num, + seccomp_whitelist[i].priority); + if (rc < 0) { + goto seccomp_return; + } + } + + rc = seccomp_load(ctx); + + seccomp_return: + seccomp_release(ctx); + return rc; +} diff --git a/qemu-seccomp.h b/qemu-seccomp.h new file mode 100644 index 000000000..b2fc3f8c3 --- /dev/null +++ b/qemu-seccomp.h @@ -0,0 +1,22 @@ +/* + * QEMU seccomp mode 2 support with libseccomp + * + * Copyright IBM, Corp. 2012 + * + * Authors: + * Eduardo Otubo <eotubo@br.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + * Contributions after 2012-01-13 are licensed under the terms of the + * GNU GPL, version 2 or (at your option) any later version. + */ +#ifndef QEMU_SECCOMP_H +#define QEMU_SECCOMP_H + +#include <seccomp.h> +#include "osdep.h" + +int seccomp_start(void); +#endif @@ -124,6 +124,19 @@ int qlist_empty(const QList *qlist) return QTAILQ_EMPTY(&qlist->head); } +static void qlist_size_iter(QObject *obj, void *opaque) +{ + size_t *count = opaque; + (*count)++; +} + +size_t qlist_size(const QList *qlist) +{ + size_t count = 0; + qlist_iter(qlist, qlist_size_iter, &count); + return count; +} + /** * qobject_to_qlist(): Convert a QObject into a QList */ @@ -49,6 +49,7 @@ void qlist_iter(const QList *qlist, QObject *qlist_pop(QList *qlist); QObject *qlist_peek(QList *qlist); int qlist_empty(const QList *qlist); +size_t qlist_size(const QList *qlist); QList *qobject_to_qlist(const QObject *obj); static inline const QListEntry *qlist_first(const QList *qlist) @@ -29,7 +29,7 @@ endif $(call quiet-command,$(CC) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<," AS $(TARGET_DIR)$@") %.o: %.m - $(call quiet-command,$(CC) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<," OBJC $(TARGET_DIR)$@") + $(call quiet-command,$(OBJCC) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<," OBJC $(TARGET_DIR)$@") LINK = $(call quiet-command,$(CC) $(QEMU_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $(sort $(1)) $(LIBS)," LINK $(TARGET_DIR)$@") diff --git a/softmmu-semi.h b/softmmu-semi.h index 648cb959d..bcb979a5b 100644 --- a/softmmu-semi.h +++ b/softmmu-semi.h @@ -40,7 +40,7 @@ static void *softmmu_lock_user(CPUArchState *env, uint32_t addr, uint32_t len, uint8_t *p; /* TODO: Make this something that isn't fixed size. */ p = malloc(len); - if (copy) + if (p && copy) cpu_memory_rw_debug(env, addr, p, len, 0); return p; } @@ -52,6 +52,9 @@ static char *softmmu_lock_user_string(CPUArchState *env, uint32_t addr) uint8_t c; /* TODO: Make this something that isn't fixed size. */ s = p = malloc(1024); + if (!s) { + return NULL; + } do { cpu_memory_rw_debug(env, addr, &c, 1, 0); addr++; @@ -62,6 +62,7 @@ int qemu_powerdown_requested(void); void qemu_system_killed(int signal, pid_t pid); void qemu_kill_report(void); extern qemu_irq qemu_system_powerdown; +void qemu_devices_reset(void); void qemu_system_reset(bool report); void qemu_add_exit_notifier(Notifier *notify); diff --git a/target-arm/arm-semi.c b/target-arm/arm-semi.c index 24952061c..73bde584a 100644 --- a/target-arm/arm-semi.c +++ b/target-arm/arm-semi.c @@ -194,18 +194,19 @@ uint32_t do_arm_semihosting(CPUARMState *env) if (!(s = lock_user_string(ARG(0)))) /* FIXME - should this error code be -TARGET_EFAULT ? */ return (uint32_t)-1; - if (ARG(1) >= 12) + if (ARG(1) >= 12) { + unlock_user(s, ARG(0), 0); return (uint32_t)-1; + } if (strcmp(s, ":tt") == 0) { - if (ARG(1) < 4) - return STDIN_FILENO; - else - return STDOUT_FILENO; + int result_fileno = ARG(1) < 4 ? STDIN_FILENO : STDOUT_FILENO; + unlock_user(s, ARG(0), 0); + return result_fileno; } if (use_gdb_syscalls()) { gdb_do_syscall(arm_semi_cb, "open,%s,%x,1a4", ARG(0), (int)ARG(2)+1, gdb_open_modeflags[ARG(1)]); - return env->regs[0]; + ret = env->regs[0]; } else { ret = set_swi_errno(ts, open(s, open_modeflags[ARG(1)], 0644)); } diff --git a/tests/check-qjson.c b/tests/check-qjson.c index 526e25ef6..3b896f5f9 100644 --- a/tests/check-qjson.c +++ b/tests/check-qjson.c @@ -466,6 +466,58 @@ static void simple_dict(void) } } +/* + * this generates json of the form: + * a(0,m) = [0, 1, ..., m-1] + * a(n,m) = { + * 'key0': a(0,m), + * 'key1': a(1,m), + * ... + * 'key(n-1)': a(n-1,m) + * } + */ +static void gen_test_json(GString *gstr, int nest_level_max, + int elem_count) +{ + int i; + + g_assert(gstr); + if (nest_level_max == 0) { + g_string_append(gstr, "["); + for (i = 0; i < elem_count; i++) { + g_string_append_printf(gstr, "%d", i); + if (i < elem_count - 1) { + g_string_append_printf(gstr, ", "); + } + } + g_string_append(gstr, "]"); + return; + } + + g_string_append(gstr, "{"); + for (i = 0; i < nest_level_max; i++) { + g_string_append_printf(gstr, "'key%d': ", i); + gen_test_json(gstr, i, elem_count); + if (i < nest_level_max - 1) { + g_string_append(gstr, ","); + } + } + g_string_append(gstr, "}"); +} + +static void large_dict(void) +{ + GString *gstr = g_string_new(""); + QObject *obj; + + gen_test_json(gstr, 10, 100); + obj = qobject_from_json(gstr->str); + g_assert(obj != NULL); + + qobject_decref(obj); + g_string_free(gstr, true); +} + static void simple_list(void) { int i; @@ -706,6 +758,7 @@ int main(int argc, char **argv) g_test_add_func("/literals/keyword", keyword_literal); g_test_add_func("/dicts/simple_dict", simple_dict); + g_test_add_func("/dicts/large_dict", large_dict); g_test_add_func("/lists/simple_list", simple_list); g_test_add_func("/whitespace/simple_whitespace", simple_whitespace); @@ -63,6 +63,11 @@ #include <linux/ppdev.h> #include <linux/parport.h> #endif + +#ifdef CONFIG_SECCOMP +#include "qemu-seccomp.h" +#endif + #ifdef __sun__ #include <sys/stat.h> #include <sys/ethernet.h> @@ -765,6 +770,26 @@ static int bt_parse(const char *opt) return 1; } +static int parse_sandbox(QemuOpts *opts, void *opaque) +{ + /* FIXME: change this to true for 1.3 */ + if (qemu_opt_get_bool(opts, "enable", false)) { +#ifdef CONFIG_SECCOMP + if (seccomp_start() < 0) { + qerror_report(ERROR_CLASS_GENERIC_ERROR, + "failed to install seccomp syscall filter in the kernel"); + return -1; + } +#else + qerror_report(ERROR_CLASS_GENERIC_ERROR, + "sandboxing request but seccomp is not compiled into this build"); + return -1; +#endif + } + + return 0; +} + /***********************************************************/ /* QEMU Block devices */ @@ -1439,7 +1464,7 @@ void qemu_unregister_reset(QEMUResetHandler *func, void *opaque) } } -void qemu_system_reset(bool report) +void qemu_devices_reset(void) { QEMUResetEntry *re, *nre; @@ -1447,6 +1472,15 @@ void qemu_system_reset(bool report) QTAILQ_FOREACH_SAFE(re, &reset_handlers, entry, nre) { re->func(re->opaque); } +} + +void qemu_system_reset(bool report) +{ + if (current_machine && current_machine->reset) { + current_machine->reset(); + } else { + qemu_devices_reset(); + } if (report) { monitor_protocol_event(QEVENT_RESET, NULL); } @@ -2701,6 +2735,7 @@ int main(int argc, char **argv, char **envp) break; case QEMU_OPTION_m: { int64_t value; + uint64_t sz; char *end; value = strtosz(optarg, &end); @@ -2708,12 +2743,12 @@ int main(int argc, char **argv, char **envp) fprintf(stderr, "qemu: invalid ram size: %s\n", optarg); exit(1); } - - if (value != (uint64_t)(ram_addr_t)value) { + sz = QEMU_ALIGN_UP((uint64_t)value, 8192); + ram_size = sz; + if (ram_size != sz) { fprintf(stderr, "qemu: ram size too large\n"); exit(1); } - ram_size = value; break; } case QEMU_OPTION_mempath: @@ -3282,6 +3317,12 @@ int main(int argc, char **argv, char **envp) case QEMU_OPTION_qtest_log: qtest_log = optarg; break; + case QEMU_OPTION_sandbox: + opts = qemu_opts_parse(qemu_find_opts("sandbox"), optarg, 1); + if (!opts) { + exit(0); + } + break; default: os_parse_cmd_args(popt->index, optarg); } @@ -3289,6 +3330,10 @@ int main(int argc, char **argv, char **envp) } loc_set_none(); + if (qemu_opts_foreach(qemu_find_opts("sandbox"), parse_sandbox, NULL, 0)) { + exit(1); + } + if (machine == NULL) { fprintf(stderr, "No machine found.\n"); exit(1); |