[Qemu-devel] [PATCH] libqos: Convert malloc-pc allocator to a generic allocator
The allocator in malloc-pc has been extracted, so it can be used in every arch. This operation showed that both the alloc and free functions can be also generic. Because of this, the QGuestAllocator has been removed from is function to wrap the alloc and free function, and now just contains the allocator parameters. As a result, only the allocator initalizer and unitializer are arch dependent. Signed-off-by: Marc Marí --- tests/Makefile |2 +- tests/libqos/malloc-pc.c | 280 +- tests/libqos/malloc-pc.h | 11 +- tests/libqos/malloc.c| 268 tests/libqos/malloc.h| 45 +--- 5 files changed, 307 insertions(+), 299 deletions(-) create mode 100644 tests/libqos/malloc.c diff --git a/tests/Makefile b/tests/Makefile index 834279c..15bc670 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -296,7 +296,7 @@ tests/test-opts-visitor$(EXESUF): tests/test-opts-visitor.o $(test-qapi-obj-y) l tests/test-mul64$(EXESUF): tests/test-mul64.o libqemuutil.a tests/test-bitops$(EXESUF): tests/test-bitops.o libqemuutil.a -libqos-obj-y = tests/libqos/pci.o tests/libqos/fw_cfg.o +libqos-obj-y = tests/libqos/pci.o tests/libqos/fw_cfg.o tests/libqos/malloc.o libqos-obj-y += tests/libqos/i2c.o libqos-pc-obj-y = $(libqos-obj-y) tests/libqos/pci-pc.o libqos-pc-obj-y += tests/libqos/malloc-pc.o diff --git a/tests/libqos/malloc-pc.c b/tests/libqos/malloc-pc.c index f4218c6..c9c48fd 100644 --- a/tests/libqos/malloc-pc.c +++ b/tests/libqos/malloc-pc.c @@ -17,296 +17,28 @@ #include "hw/nvram/fw_cfg.h" #include "qemu-common.h" -#include "qemu/queue.h" #include #define PAGE_SIZE (4096) -#define MLIST_ENTNAME entries -typedef QTAILQ_HEAD(MemList, MemBlock) MemList; -typedef struct MemBlock { -QTAILQ_ENTRY(MemBlock) MLIST_ENTNAME; -uint64_t size; -uint64_t addr; -} MemBlock; - -typedef struct PCAlloc -{ -QGuestAllocator alloc; -PCAllocOpts opts; -uint64_t start; -uint64_t end; - -MemList used; -MemList free; -} PCAlloc; - -static MemBlock *mlist_new(uint64_t addr, uint64_t size) -{ -MemBlock *block; - -if (!size) { -return NULL; -} -block = g_malloc0(sizeof(MemBlock)); - -block->addr = addr; -block->size = size; - -return block; -} - -static void mlist_delete(MemList *list, MemBlock *node) -{ -g_assert(list && node); -QTAILQ_REMOVE(list, node, MLIST_ENTNAME); -g_free(node); -} - -static MemBlock *mlist_find_key(MemList *head, uint64_t addr) -{ -MemBlock *node; -QTAILQ_FOREACH(node, head, MLIST_ENTNAME) { -if (node->addr == addr) { -return node; -} -} -return NULL; -} - -static MemBlock *mlist_find_space(MemList *head, uint64_t size) -{ -MemBlock *node; - -QTAILQ_FOREACH(node, head, MLIST_ENTNAME) { -if (node->size >= size) { -return node; -} -} -return NULL; -} - -static MemBlock *mlist_sort_insert(MemList *head, MemBlock *insr) -{ -MemBlock *node; -g_assert(head && insr); - -QTAILQ_FOREACH(node, head, MLIST_ENTNAME) { -if (insr->addr < node->addr) { -QTAILQ_INSERT_BEFORE(node, insr, MLIST_ENTNAME); -return insr; -} -} - -QTAILQ_INSERT_TAIL(head, insr, MLIST_ENTNAME); -return insr; -} - -static inline uint64_t mlist_boundary(MemBlock *node) -{ -return node->size + node->addr; -} - -static MemBlock *mlist_join(MemList *head, MemBlock *left, MemBlock *right) -{ -g_assert(head && left && right); - -left->size += right->size; -mlist_delete(head, right); -return left; -} - -static void mlist_coalesce(MemList *head, MemBlock *node) -{ -g_assert(node); -MemBlock *left; -MemBlock *right; -char merge; - -do { -merge = 0; -left = QTAILQ_PREV(node, MemList, MLIST_ENTNAME); -right = QTAILQ_NEXT(node, MLIST_ENTNAME); - -/* clowns to the left of me */ -if (left && mlist_boundary(left) == node->addr) { -node = mlist_join(head, left, node); -merge = 1; -} - -/* jokers to the right */ -if (right && mlist_boundary(node) == right->addr) { -node = mlist_join(head, node, right); -merge = 1; -} - -} while (merge); -} - -static uint64_t pc_mlist_fulfill(PCAlloc *s, MemBlock *freenode, uint64_t size) -{ -uint64_t addr; -MemBlock *usednode; - -g_assert(freenode); -g_assert_cmpint(freenode->size, >=, size); - -addr = freenode->addr; -if (freenode->size == size) { -/* re-use this freenode as our used node */ -QTAILQ_REMOVE(&s->free, freenode, MLIST_ENTNAME); -usednode = freenode; -} else { -/* adjust the free node and create a new used node */ -freenode->addr += size; -freenode->size -= size; -usednode = mlist_new(addr, size); -} - -mlist_sort_inser
[Qemu-devel] Close the BlockDriverState when guest eject the media
Hi ALL: There are two ways to eject the cdrom tray. One is by the eject's qmp commmand(eject_device). The another one is by the guest(bdrv_eject). They have different results. eject_device: close the BlockDriverState(bdrv_close(bs)) bdrv_eject: don't close the BlockDriverState, This is ambiguous. So libvirt can't handle some situations. libvirt send eject qmp command ---> qemu send eject request to guest ---> guest respond to qemu ---> qemu emit tray_open event to libvirt ---> libvirt will not send change qmp command if media source is null. So the media is not be replace to the null. So close the BlockDriverState in bdrv_eject. Thanks. diff --git a/block.c b/block.c index d3aebeb..0be69de 100644 --- a/block.c +++ b/block.c @@ -5276,6 +5276,10 @@ void bdrv_eject(BlockDriverState *bs, bool eject_flag) qapi_event_send_device_tray_moved(bdrv_get_device_name(bs), eject_flag, &error_abort); } + +if (eject_flag) { +bdrv_close(bs); +} }
[Qemu-devel] ANNOUNCE: libguestfs 1.28 released
I'm pleased to announce libguestfs 1.28, a library and set of tools for accessing and modifying virtual machine disk images. This release took 7 months of work by a considerable number of people, and has many new features (see release notes below), including new 'virt-v2v' and 'virt-p2v' tools for importing guests from foreign hypervisors to KVM, and 'virt-log' which is a tool for extracting log files from guests (including Windows). You can get libguestfs 1.28 here: Main website: http://libguestfs.org/ Source: http://libguestfs.org/download/1.28-stable/ You will also need latest supermin from here: http://libguestfs.org/download/supermin/ Fedora 21: http://koji.fedoraproject.org/koji/packageinfo?packageID=8391 It will appear as an update for F21 in about a week. Debian/experimental coming soon, see: https://packages.debian.org/experimental/libguestfs0 [ From http://libguestfs.org/guestfs-release-notes.1.html ] RELEASE NOTES FOR LIBGUESTFS 1.28 New features Tools virt-v2v(1) and virt-p2v(1) are tools for converting from foreign hypervisors (such as VMware or Xen) or physical machines, to KVM. These tools were previously a separate project. The code for both tools has been integrated into the libguestfs tree. As part of the refactoring, virt-p2v has been rewritten (from Ruby, now C), and virt-v2v now uses several modern features of qemu which make it run many times faster than before. virt-v2v(1) can import from: VMware vCenter, VMware OVA files, local disk files, libvirt, RHEL 5 Xen. It can output to: oVirt or Red Hat Enterprise Virtualization (RHEV-M), OpenStack Glance, libvirt, qemu, local disk files. virt-log(1) is a new tool for listing log files from guests. It supports a variety of guests including Linux traditional, Linux using journal, and Windows event log. virt-builder(1) has a new --machine-readable option to make it simpler to consume virt-builder from other programs. New virt-builder(1) and virt-customize(1) --chmod option. virt-sysprep(1) will now remove: systemd journals, anaconda logs, lightdm logs, debian-installer files, apt logs, exim logs, ConsoleKit logs, firewalld logs, grubby logs, proftpd logs, libvirt/libxml logs, and several other log files. The virt-sysprep user-account operation is now able to remove or keep particular user accounts. (Pino Toscano). New guestmount(1) --fd option, allowing you to run guestmount captive under another process. virt-sparsify(1) has a new --tmp option allowing you to precisely control where temporary files are stored. virt-sparsify(1) can now write to a block device. virt-customize(1) and virt-sysprep(1) now support adding firstboot scripts to Windows guests. virt-cat(1), virt-edit(1), virt-ls(1) now support the -m option, allowing you to override automatic inspection of guests and instead specify where to mount partitions (Pino Toscano). The virt tools now have coloured output: green for OK, red for errors, blue for warnings. Language bindings You can build a Python distribution using make -C python sdist Ruby bindings have switched from Test::Unit to MiniTest. The Java bindings are now compatible with OpenJDK 8 (Pino Toscano). Inspection Oracle Linux is returned as oraclelinux (Nikos Skalkotos). Linux guests which do not have /etc/fstab can now be handled (Pino Toscano). Minix is returned as minix (Pino Toscano). Architectures Aarch64 (64 bit ARM) support has been added. Inspection and the guestfs_file_architecture call can now recognize arm (32 bit) and aarch64 guests. Security CVE-2014-0191 Network usage and entity resolution in XML parsing Libguestfs previously used unsafe libxml2 APIs for parsing libvirt XML. These APIs defaulted to allowing network connections to be made when certain XML documents were presented. Using a malformed XML document it was also possible to exhaust all CPU, memory or file descriptors on the machine. Since the libvirt XML comes from a trusted source (the libvirt daemon) it is not thought that this could have been exploitable. This was fixed in libguestfs ≥ 1.27.9 and the fix was backported to stable versions ≥ 1.26.2, ≥ 1.24.9, ≥ 1.22.10 and ≥ 1.20.13. (Thanks: Dan Berrange, Pino Toscano). Shellshock (bash CVE-2014-6271) This bash bug indirectly affects libguestfs. For more information see: https://www.redhat.com/archives/libguestfs/2014-September/msg00252.html API New APIs guestfs_clear_backend_setting guestfs_get_backend_setting guestfs_set_backend_setting Use these APIs to set individual backend settings. guestfs_cpio_out Convert a directory within the disk image to cpio format. guestfs_journal_get_realtime
[Qemu-devel] [PATCH v1 repost] block/curl: Improve type safety of s->timeout.
This patch is identical to the previous version, except that I have rebased it on top of current qemu HEAD. Previous discussion: https://lists.gnu.org/archive/html/qemu-devel/2014-10/threads.html#00518
[Qemu-devel] [PATCH v1 repost] block/curl: Improve type safety of s->timeout.
qemu_opt_get_number returns a uint64_t, and curl_easy_setopt expects a long (not an int). Store the timeout (which is a positive number of seconds) as a uint64_t. Check that the number given by the user is reasonable. Cast it to long before calling curl_easy_setopt. Example error message after this change has been applied: $ ./qemu-img create -f qcow2 /tmp/test.qcow2 \ -b 'json: { "file.driver":"https", "file.url":"https://foo/bar";, "file.timeout":-1 }' qemu-img: /tmp/test.qcow2: Could not open 'json: { "file.driver":"https", "file.url":"https://foo/bar";, "file.timeout":-1 }': timeout parameter is too large or negative: Invalid argument Signed-off-by: Richard W.M. Jones Reviewed-by: Laszlo Ersek --- block/curl.c | 8 ++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/block/curl.c b/block/curl.c index 225407c..5233ff6 100644 --- a/block/curl.c +++ b/block/curl.c @@ -112,7 +112,7 @@ typedef struct BDRVCURLState { char *url; size_t readahead_size; bool sslverify; -int timeout; +uint64_t timeout; char *cookie; bool accept_range; AioContext *aio_context; @@ -390,7 +390,7 @@ static CURLState *curl_init_state(BlockDriverState *bs, BDRVCURLState *s) if (s->cookie) { curl_easy_setopt(state->curl, CURLOPT_COOKIE, s->cookie); } -curl_easy_setopt(state->curl, CURLOPT_TIMEOUT, s->timeout); +curl_easy_setopt(state->curl, CURLOPT_TIMEOUT, (long)s->timeout); curl_easy_setopt(state->curl, CURLOPT_WRITEFUNCTION, (void *)curl_read_cb); curl_easy_setopt(state->curl, CURLOPT_WRITEDATA, (void *)state); @@ -546,6 +546,10 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags, s->timeout = qemu_opt_get_number(opts, CURL_BLOCK_OPT_TIMEOUT, CURL_TIMEOUT_DEFAULT); +if (s->timeout > 10) { +error_setg(errp, "timeout parameter is too large or negative"); +goto out_noclean; +} s->sslverify = qemu_opt_get_bool(opts, CURL_BLOCK_OPT_SSLVERIFY, true); -- 2.0.4
[Qemu-devel] qemu guest stalls with lots of PTY writes
qemu experts, please help. This is seen with the latest qemu 1.5 (commit 62c339c5272ce8fbe8ca52695cee8ff40da7872e), guest VM stalls intermittently. Setup:2) start a linux guest with a PTY device, for example 3) Bind pty device to a slow tty device socat -d /dev/pts/4 /dev/ttyS0,raw,b9600,echo=0 4) on serial console, writes lots of message, for example repeat 1 echo "`date`: this is a long long long long long long long test message" 5) on the host, 'strace -f -p' kvm device, noticed that trace stalls once a while. In addition, if you login via ssh to the guest, note that the login shell stalls intermittently.
Re: [Qemu-devel] qemu guest stalls with lots of PTY writes
Hello, please take a look on http://lists.nongnu.org/archive/html/qemu-devel/2014-09/msg00600.html, I had reported the simular issue for recent emulator versions. It would be good if this particular problem can achieve more votes, because I have not enough knowledge to fix it by myself.
[Qemu-devel] kvm segfault in iov_to_buf / virtio_scsi_parse_req
Hi, while migrating a bunch of VMs i saw multiple times segaults with qemu 2.1.2. Is this a known bug? Full backtrace: Program terminated with signal 11, Segmentation fault. #0 0x7ff9c73bca90 in ?? () from /lib/x86_64-linux-gnu/libc.so.6 (gdb) bt #0 0x7ff9c73bca90 in ?? () from /lib/x86_64-linux-gnu/libc.so.6 #1 0x7ff9cde46b8e in iov_to_buf (iov=0x7ff9b805c0b0, iov_cnt=1, offset=0, buf=0x7ff9b8060118, bytes=51) at util/iov.c:49 #2 0x7ff9cdacdc56 in virtio_scsi_parse_req (req=0x7ff9b8054090, req_size=51, resp_size=108) at qemu-kvm/hw/scsi/virtio-scsi.c:140 #3 0x7ff9cdace060 in virtio_scsi_load_request (f=0x7ff9b803b620, sreq=0x7ff9b8089550) at qemu-kvm/hw/scsi/virtio-scsi.c:215 #4 0x7ff9cdcf5737 in get_scsi_requests (f=0x7ff9b803b620, pv=0x7ff9cfe4a440, size=0) at hw/scsi/scsi-bus.c:1875 #5 0x7ff9cdb76e0c in vmstate_load_state (f=0x7ff9b803b620, vmsd=0x7ff9ce24cac0, opaque=0x7ff9cfe4a440, version_id=1) at vmstate.c:105 #6 0x7ff9cdb76de8 in vmstate_load_state (f=0x7ff9b803b620, vmsd=0x7ff9ce24c500, opaque=0x7ff9cfe4a440, version_id=1) at vmstate.c:102 #7 0x7ff9cda935b6 in vmstate_load (f=0x7ff9b803b620, se=0x7ff9cfe95570, version_id=1) at qemu-kvm/savevm.c:572 #8 0x7ff9cda94652 in qemu_loadvm_state (f=0x7ff9b803b620) at qemu-kvm/savevm.c:951 #9 0x7ff9cdb748bd in process_incoming_migration_co (opaque=0x7ff9b803b620) at migration.c:97 #10 0x7ff9cdddb433 in coroutine_trampoline (i0=-1207852976, i1=32761) at coroutine-ucontext.c:118 #11 0x7ff9c72dbd10 in ?? () from /lib/x86_64-linux-gnu/libc.so.6 #12 0x7fff5e55a830 in ?? () #13 0x in ?? () Stefan
[Qemu-devel] [PATCH 0/3] A few smartcard patches
From: Ray Strode The first two patches are resends from last year that have already been reviewed and just need to be pulled in. The third patch is something I ran into a few days ago when trying to set up kerberos (preauthentication with pkinit) in a guest. Ray Strode (3): libcacard: introduce new vcard_emul_logout libcacard: Lock NSS cert db when selecting an applet on an emulated card cac: don't free sign buffer while sign op is pending libcacard/cac.c| 10 +++--- libcacard/vcard.c | 5 + libcacard/vcard_emul.h | 1 + libcacard/vcard_emul_nss.c | 16 4 files changed, 25 insertions(+), 7 deletions(-) -- 2.1.0
[Qemu-devel] [PATCH 3/3] libcacard: don't free sign buffer while sign op is pending
From: Ray Strode commit 57f97834efe0c208ffadc9d2959f3d3d55580e52 cleaned up the cac_applet_pki_process_apdu function to have a single exit point. Unfortunately, that commit introduced a bug where the sign buffer can get free'd and nullified while it's still being used. This commit corrects the bug by introducing a boolean to track whether or not the sign buffer should be freed in the function exit path. Signed-off-by: Ray Strode --- libcacard/cac.c | 10 +++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/libcacard/cac.c b/libcacard/cac.c index ae8c378..f38fdce 100644 --- a/libcacard/cac.c +++ b/libcacard/cac.c @@ -88,60 +88,61 @@ cac_common_process_apdu(VCard *card, VCardAPDU *apdu, VCardResponse **response) } /* * reset the inter call state between applet selects */ static VCardStatus cac_applet_pki_reset(VCard *card, int channel) { VCardAppletPrivate *applet_private; CACPKIAppletData *pki_applet; applet_private = vcard_get_current_applet_private(card, channel); assert(applet_private); pki_applet = &(applet_private->u.pki_data); pki_applet->cert_buffer = NULL; g_free(pki_applet->sign_buffer); pki_applet->sign_buffer = NULL; pki_applet->cert_buffer_len = 0; pki_applet->sign_buffer_len = 0; return VCARD_DONE; } static VCardStatus cac_applet_pki_process_apdu(VCard *card, VCardAPDU *apdu, VCardResponse **response) { CACPKIAppletData *pki_applet; VCardAppletPrivate *applet_private; int size, next; unsigned char *sign_buffer; +bool retain_sign_buffer = FALSE; vcard_7816_status_t status; VCardStatus ret = VCARD_FAIL; applet_private = vcard_get_current_applet_private(card, apdu->a_channel); assert(applet_private); pki_applet = &(applet_private->u.pki_data); switch (apdu->a_ins) { case CAC_UPDATE_BUFFER: *response = vcard_make_response( VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED); ret = VCARD_DONE; break; case CAC_GET_CERTIFICATE: if ((apdu->a_p2 != 0) || (apdu->a_p1 != 0)) { *response = vcard_make_response( VCARD7816_STATUS_ERROR_P1_P2_INCORRECT); break; } assert(pki_applet->cert != NULL); size = apdu->a_Le; if (pki_applet->cert_buffer == NULL) { pki_applet->cert_buffer = pki_applet->cert; pki_applet->cert_buffer_len = pki_applet->cert_len; } size = MIN(size, pki_applet->cert_buffer_len); next = MIN(255, pki_applet->cert_buffer_len - size); *response = vcard_response_new_bytes( card, pki_applet->cert_buffer, size, apdu->a_Le, next ? @@ -151,85 +152,88 @@ cac_applet_pki_process_apdu(VCard *card, VCardAPDU *apdu, pki_applet->cert_buffer += size; pki_applet->cert_buffer_len -= size; if ((*response == NULL) || (next == 0)) { pki_applet->cert_buffer = NULL; } if (*response == NULL) { *response = vcard_make_response( VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE); } ret = VCARD_DONE; break; case CAC_SIGN_DECRYPT: if (apdu->a_p2 != 0) { *response = vcard_make_response( VCARD7816_STATUS_ERROR_P1_P2_INCORRECT); break; } size = apdu->a_Lc; sign_buffer = g_realloc(pki_applet->sign_buffer, pki_applet->sign_buffer_len + size); memcpy(sign_buffer+pki_applet->sign_buffer_len, apdu->a_body, size); size += pki_applet->sign_buffer_len; switch (apdu->a_p1) { case 0x80: /* p1 == 0x80 means we haven't yet sent the whole buffer, wait for * the rest */ pki_applet->sign_buffer = sign_buffer; pki_applet->sign_buffer_len = size; *response = vcard_make_response(VCARD7816_STATUS_SUCCESS); +retain_sign_buffer = TRUE; break; case 0x00: /* we now have the whole buffer, do the operation, result will be * in the sign_buffer */ status = vcard_emul_rsa_op(card, pki_applet->key, sign_buffer, size); if (status != VCARD7816_STATUS_SUCCESS) { *response = vcard_make_response(status); break; } *response = vcard_response_new(card, sign_buffer, size, apdu->a_Le, VCARD7816_STATUS_SUCCESS); if (*response == NULL) { *response = vcard_make_response( VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE); } break; default: *res
[Qemu-devel] [PATCH 1/3] libcacard: introduce new vcard_emul_logout
From: Ray Strode vcard_emul_reset currently only logs NSS out, but there is a TODO for potentially sending insertion/removal events when powering down or powering up. For clarity, this commit moves the current guts of vcard_emul_reset to a new vcard_emul_logout function which will never send insertion/removal events. The vcard_emul_reset function now just calls vcard_emul_logout, but also retains its TODO for watching power state transitions and sending insertion/removal events. Signed-off-by: Ray Strode Reviewed-By: Robert Relyea Reviewed-By: Alon Levy --- libcacard/vcard_emul.h | 1 + libcacard/vcard_emul_nss.c | 16 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/libcacard/vcard_emul.h b/libcacard/vcard_emul.h index 963563f..f09ee98 100644 --- a/libcacard/vcard_emul.h +++ b/libcacard/vcard_emul.h @@ -13,53 +13,54 @@ #ifndef VCARD_EMUL_H #define VCARD_EMUL_H 1 #include "card_7816t.h" #include "vcard.h" #include "vcard_emul_type.h" /* * types */ typedef enum { VCARD_EMUL_OK = 0, VCARD_EMUL_FAIL, /* return values by vcard_emul_init */ VCARD_EMUL_INIT_ALREADY_INITED, } VCardEmulError; /* options are emul specific. call card_emul_parse_args to change a string * To an options struct */ typedef struct VCardEmulOptionsStruct VCardEmulOptions; /* * Login functions */ /* return the number of login attempts still possible on the card. if unknown, * return -1 */ int vcard_emul_get_login_count(VCard *card); /* login into the card, return the 7816 status word (sw2 || sw1) */ vcard_7816_status_t vcard_emul_login(VCard *card, unsigned char *pin, int pin_len); +void vcard_emul_logout(VCard *card); /* * key functions */ /* delete a key */ void vcard_emul_delete_key(VCardKey *key); /* RSA sign/decrypt with the key, signature happens 'in place' */ vcard_7816_status_t vcard_emul_rsa_op(VCard *card, VCardKey *key, unsigned char *buffer, int buffer_size); void vcard_emul_reset(VCard *card, VCardPower power); void vcard_emul_get_atr(VCard *card, unsigned char *atr, int *atr_len); /* Re-insert of a card that has been removed by force removal */ VCardEmulError vcard_emul_force_card_insert(VReader *vreader); /* Force a card removal even if the card is not physically removed */ VCardEmulError vcard_emul_force_card_remove(VReader *vreader); VCardEmulOptions *vcard_emul_options(const char *args); VCardEmulError vcard_emul_init(const VCardEmulOptions *options); void vcard_emul_replay_insertion_events(void); void vcard_emul_usage(void); #endif diff --git a/libcacard/vcard_emul_nss.c b/libcacard/vcard_emul_nss.c index 07b4464..53252a8 100644 --- a/libcacard/vcard_emul_nss.c +++ b/libcacard/vcard_emul_nss.c @@ -374,78 +374,86 @@ vcard_emul_login(VCard *card, unsigned char *pin, int pin_len) if (!nss_emul_init) { return VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED; } slot = vcard_emul_card_get_slot(card); /* We depend on the PKCS #11 module internal login state here because we * create a separate process to handle each guest instance. If we needed * to handle multiple guests from one process, then we would need to keep * a lot of extra state in our card structure * */ pin_string = g_malloc(pin_len+1); memcpy(pin_string, pin, pin_len); pin_string[pin_len] = 0; /* handle CAC expanded pins correctly */ for (i = pin_len-1; i >= 0 && (pin_string[i] == 0xff); i--) { pin_string[i] = 0; } rv = PK11_Authenticate(slot, PR_FALSE, pin_string); memset(pin_string, 0, pin_len); /* don't let the pin hang around in memory to be snooped */ g_free(pin_string); if (rv == SECSuccess) { return VCARD7816_STATUS_SUCCESS; } /* map the error from port get error */ return VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED; } void -vcard_emul_reset(VCard *card, VCardPower power) +vcard_emul_logout(VCard *card) { PK11SlotInfo *slot; if (!nss_emul_init) { return; } +slot = vcard_emul_card_get_slot(card); +if (PK11_IsLoggedIn(slot,NULL)) { +PK11_Logout(slot); /* NOTE: ignoring SECStatus return value */ +} +} + +void +vcard_emul_reset(VCard *card, VCardPower power) +{ /* * if we reset the card (either power on or power off), we lose our login * state */ +vcard_emul_logout(card); + /* TODO: we may also need to send insertion/removal events? */ -slot = vcard_emul_card_get_slot(card); -PK11_Logout(slot); /* NOTE: ignoring SECStatus return value */ } - static VReader * vcard_emul_find_vreader_from_slot(PK11SlotInfo *slot) { VReaderList *reader_list = vreader_get_reader_list(); VReaderListEntry *current_entry; if (reader_list == NULL) { return NULL; } for (curr
[Qemu-devel] [PATCH 2/3] libcacard: Lock NSS cert db when selecting an applet on an emulated card
From: Ray Strode When a process in a guest uses an emulated smartcard, libcacard running on the host passes the PIN from the guest to the PK11_Authenticate NSS function. The first time PK11_Authenticate is called the passed in PIN is used to unlock the certificate database. Subsequent calls to PK11_Authenticate will transparently succeed, regardless of the passed in PIN. This is a convenience for applications provided by NSS. Of course, the guest may have many applications using the one emulated smart card all driven from the same host QEMU process. That means if a user enters the right PIN in one program in the guest, and then enters the wrong PIN in another program in the guest, the wrong PIN will still successfully unlock the virtual smartcard. This commit forces the NSS certificate database to be locked anytime an applet is selected on an emulated smartcard by calling vcard_emul_logout. Signed-off-by: Ray Strode Reviewed-By: Robert Relyea Reviewed-By: Alon Levy --- libcacard/vcard.c | 5 + 1 file changed, 5 insertions(+) diff --git a/libcacard/vcard.c b/libcacard/vcard.c index 87ad516..d140a8e 100644 --- a/libcacard/vcard.c +++ b/libcacard/vcard.c @@ -223,60 +223,65 @@ vcard_find_applet(VCard *card, unsigned char *aid, int aid_len) { VCardApplet *current_applet; for (current_applet = card->applet_list; current_applet; current_applet = current_applet->next) { if (current_applet->aid_len != aid_len) { continue; } if (memcmp(current_applet->aid, aid, aid_len) == 0) { break; } } return current_applet; } unsigned char * vcard_applet_get_aid(VCardApplet *applet, int *aid_len) { if (applet == NULL) { return NULL; } *aid_len = applet->aid_len; return applet->aid; } void vcard_select_applet(VCard *card, int channel, VCardApplet *applet) { assert(channel < MAX_CHANNEL); + +/* If using an emulated card, make sure to log out of any already logged in + * session. */ +vcard_emul_logout(card); + card->current_applet[channel] = applet; /* reset the applet */ if (applet && applet->reset_applet) { applet->reset_applet(card, channel); } } VCardAppletPrivate * vcard_get_current_applet_private(VCard *card, int channel) { VCardApplet *applet = card->current_applet[channel]; if (applet == NULL) { return NULL; } return applet->applet_private; } VCardStatus vcard_process_applet_apdu(VCard *card, VCardAPDU *apdu, VCardResponse **response) { if (card->current_applet[apdu->a_channel]) { return card->current_applet[apdu->a_channel]->process_apdu( card, apdu, response); } return VCARD_NEXT; } /* -- 2.1.0
Re: [Qemu-devel] [Bug 1362755] [NEW] QEmu +2 does not route VLAN tagged packets, that are originated within the Hypervisor itself.
Hey Vlad, Sorry about this delay... I tried the following commands within the guest (that router/firewall " guest-fw-1.domain.com"): root@guest-fw-1:~# ethtool -K eth1 tso off root@guest-fw-1:~# ethtool -K eth1 gso off root@guest-fw-1:~# ethtool -K eth1 tx off But it did not fixed the problem... Then, I tried (it was still enabled for that "vlan device", just to test): root@guest-fw-1:~# ethtool -K vlan100 gso off Didn't worked either... --- root@guest-fw-1:~# grep vlan100 /proc/net/vlan/config vlan100| 100 | eth1 --- Also, at the KVM host, its ovsbr1 (OpenvSwitch bridge), is attached to eth1, then, I tried to turn `tso/gso/tx off` there too but, no, same bad results. I tried to disable tso/gso/tx at another guest, of vlan100 net, didn't worked either. Regards, Thiago On 29 August 2014 11:20, Vlad Yasevich wrote: > [ realized that the bug and reporter were non cc'd, updated cc list] > > On 08/28/2014 02:40 PM, Thiago Martins wrote: > > Public bug reported: > > > > Guys, > > > > Trusty QEmu 2.0 Hypervisor fails to create a consistent virtual network. > > It does not route tagged VLAN packets. > > > > The have a been a bunch of rather recent changes to the kernel to support > guest VLANs correctly. The issues have been around TSO/GSO implementation > in the kernel. > > Could try disabling TSO/GSO and tx checksums on the vlan devices in the > guest > and see if it solves your problem? > > If it does, could you try the kernel from > git://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git > turn the offloads back on and see if the problem is solved? > > Thanks > -vlad > > > That's it, it is impossible to use Trusty acting as a QEmu 2.0 > > Hypervisor (metapakage `ubuntu-virt-server`), to make a basic virtual > > tagged network within itself. QEmu 2.X guest does not route traffic when > > with tagged VLANs! > > > > So, Trusty QEmu 2.0 Hypervisor cannot be used to host guests acting as > > "firewalls / routers", and it have an easy to reproduce, connectivity > > problem. > > > > This network problem affects Ubuntu 14.04.1 (Linux-3.13.0-35-generic) > > with QEmu 2.0 (it also affects 14.10, Linux 3.16 - QEmu 2.1). > > > > I have this very same setup up and running, on about ~100 physical > > servers (others Trusty QEmu 2.0 Hypervisors), and in only a few of them, > > the QEmu Hypervisors dedicated to host "guest acting as routers / > > firewalls", like a "borger gateway" for example, that it does not work > > as expected. > > > > One interesting thing to note is that, this BUG appear only, and only > > at, the QEmu Hypervisors dedicated to host guests that are used as > > `router / firewalls` (as I said above), others QEmu Hypervisors of my > > network does not suffer from this problem. > > > > Another interesting point is that it fails to route tagged VLAN packets > > only when these packets are originated from within the Hypervisor > > itself, I mean, packets from both host and other guests (not the > > router/firewall guest itself), suffer from this connectivity problem. > > > > As a workaroung / fix, Xen-4.4 can be used, instead of QEmu 2.0, as a > > "border hypervisor". So, this proves that there is something wrong with > > QEmu. > > > > I already tested it with both `openvswitch-switch` and with `bridge- > > utils`, same bad results. So, don't waste your time trying `bridge- > > utils` (optional steps while reproducing it), you can keep OVS bridges > > from original design. > > > > I think that I'm using the best pratices to build this environment, as > > follows... > > > > > > * Topology * > > > > > > QEmu 2.0 Hypervisor - (qemu-host-1.domain.com - the "border > hypervisor"): > > > > 1- Physical machine with 3 NICs; > > 2- Minimal Ubuntu 14.04.1 installed and upgraded; > > 3- Packages installed: "ubuntu-virt-server openvswitch-switch rdnssd > tcpdump". > > > > - eth0 connected to the Internet - VLAN tag 10; > > - eth1 connected to the LAN1 - VLAN tag 100; > > - eth2 connected to the LAN2 - VLAN tag 200; > > > > > > Guest (guest-fw-1.domain.com - the "border gateway" itself - regular > guest acting as a router with iptables/ip6tables): > > > > 1- Virtual Machine with 3 NICs (VirtIO); > > 2- Minimal Virtual Machine Ubuntu 14.04.1 installed and upgraded; > > 3- Packages installed: "aiccu iptables vlan pv-grub-menu". > > > > > > OBS: You'll need `virt-manager` to connect at `qemu-host-1` to install > > `guest-fw-1`. Then, use `guest-fw-1` as a default gateway for your > > (virt-)lab network, including the `qemu-host-1` itself. > > > > > > Steps to reproduce > > > > > > * Preparing the `qemu-host-1` host: > > > > - Configure the /etc/network/interfaces with: > > > > --- > > # The loopback network interface > > auto lo > > iface lo inet loopback > > > > auto eth0 > > iface eth0 inet manual > > up ip link set $IFACE up > > down ip link set $IFACE down > > > > auto eth1 > > iface eth1 inet manual > > up ip link set dev $IFACE up > > down ip link set dev $IFACE
[Qemu-devel] [PATCH] virtio-scsi-dataplane: Add op blocker
We need this to protect dataplane thread from race conditions with block jobs until the latter is made dataplane-safe. Signed-off-by: Fam Zheng --- hw/scsi/virtio-scsi-dataplane.c | 4 hw/scsi/virtio-scsi.c | 19 +-- include/hw/virtio/virtio-scsi.h | 1 + 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/hw/scsi/virtio-scsi-dataplane.c b/hw/scsi/virtio-scsi-dataplane.c index b778e05..97c2a4f 100644 --- a/hw/scsi/virtio-scsi-dataplane.c +++ b/hw/scsi/virtio-scsi-dataplane.c @@ -154,6 +154,8 @@ void virtio_scsi_dataplane_start(VirtIOSCSI *s) s->dataplane_starting = true; +assert(!s->blocker); +error_setg(&s->blocker, "block device is in use by data plane"); /* Set up guest notifier (irq) */ rc = k->set_guest_notifiers(qbus->parent, vs->conf.num_queues + 2, true); if (rc != 0) { @@ -194,6 +196,8 @@ void virtio_scsi_dataplane_stop(VirtIOSCSI *s) if (!s->dataplane_started || s->dataplane_stopping) { return; } +error_free(s->blocker); +s->blocker = NULL; s->dataplane_stopping = true; assert(s->ctx == iothread_get_aio_context(vs->conf.iothread)); diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c index 8547ea0..99fddee 100644 --- a/hw/scsi/virtio-scsi.c +++ b/hw/scsi/virtio-scsi.c @@ -741,9 +741,18 @@ static void virtio_scsi_hotplug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { VirtIODevice *vdev = VIRTIO_DEVICE(hotplug_dev); +VirtIOSCSI *s = VIRTIO_SCSI(vdev); +SCSIDevice *sd = SCSI_DEVICE(dev); + +if (s->ctx && !s->dataplane_disabled) { +if (bdrv_op_is_blocked(sd->conf.bs, BLOCK_OP_TYPE_DATAPLANE, errp)) { +return; +} +bdrv_op_block_all(sd->conf.bs, s->blocker); +} if ((vdev->guest_features >> VIRTIO_SCSI_F_HOTPLUG) & 1) { -virtio_scsi_push_event(VIRTIO_SCSI(hotplug_dev), SCSI_DEVICE(dev), +virtio_scsi_push_event(s, sd, VIRTIO_SCSI_T_TRANSPORT_RESET, VIRTIO_SCSI_EVT_RESET_RESCAN); } @@ -753,12 +762,18 @@ static void virtio_scsi_hotunplug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { VirtIODevice *vdev = VIRTIO_DEVICE(hotplug_dev); +VirtIOSCSI *s = VIRTIO_SCSI(vdev); +SCSIDevice *sd = SCSI_DEVICE(dev); if ((vdev->guest_features >> VIRTIO_SCSI_F_HOTPLUG) & 1) { -virtio_scsi_push_event(VIRTIO_SCSI(hotplug_dev), SCSI_DEVICE(dev), +virtio_scsi_push_event(s, sd, VIRTIO_SCSI_T_TRANSPORT_RESET, VIRTIO_SCSI_EVT_RESET_REMOVED); } + +if (s->ctx) { +bdrv_op_unblock_all(sd->conf.bs, s->blocker); +} qdev_simple_device_unplug_cb(hotplug_dev, dev, errp); } diff --git a/include/hw/virtio/virtio-scsi.h b/include/hw/virtio/virtio-scsi.h index d6e5e79..1ce0858 100644 --- a/include/hw/virtio/virtio-scsi.h +++ b/include/hw/virtio/virtio-scsi.h @@ -195,6 +195,7 @@ typedef struct VirtIOSCSI { bool dataplane_starting; bool dataplane_stopping; bool dataplane_disabled; +Error *blocker; Notifier migration_state_notifier; } VirtIOSCSI; -- 1.9.3
[Qemu-devel] [PATCH v2 0/2] target-xtensa: fix loading uImage kernels on MMUv2 cores
Hi, this series fixes loading uImage kernels on MMUv2 xtensa cores. U-boot for xtensa always treats uImage load address as virtual address. This is important when booting uImage on xtensa core with MMUv2, because MMUv2 has fixed non-identity virtual-to-physical mapping after reset. Changes v1->v2: - drop custom uImage loader interface and add generic translation function instead (suggested by Alexander Graf). Max Filippov (2): hw/core/loader: implement address translation in uimage loader hw/xtensa/xtfpga: treat uImage load address as virtual hw/arm/boot.c | 2 +- hw/core/loader.c | 17 + hw/m68k/an5206.c | 3 ++- hw/m68k/dummy_m68k.c | 3 ++- hw/m68k/mcf5208.c | 3 ++- hw/microblaze/boot.c | 3 ++- hw/openrisc/openrisc_sim.c | 2 +- hw/ppc/e500.c | 3 ++- hw/ppc/ppc440_bamboo.c | 3 ++- hw/xtensa/xtfpga.c | 3 ++- include/hw/loader.h| 4 +++- 11 files changed, 32 insertions(+), 14 deletions(-) -- 1.8.1.4
[Qemu-devel] [PATCH v2 2/2] hw/xtensa/xtfpga: treat uImage load address as virtual
U-boot for xtensa always treats uImage load address as virtual address. This is important when booting uImage on xtensa core with MMUv2, because MMUv2 has fixed non-identity virtual-to-physical mapping after reset. Always do virtual-to-physical translation of uImage load address and load uImage at the translated address. This fixes booting uImage kernels on dc232b and other MMUv2 cores. Cc: qemu-sta...@nongnu.org Reported-by: Waldemar Brodkorb Signed-off-by: Max Filippov --- Changes v1->v2: - use translate_phys_addr with the new load_uimage interface. hw/xtensa/xtfpga.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c index 3c2f409..02ab824 100644 --- a/hw/xtensa/xtfpga.c +++ b/hw/xtensa/xtfpga.c @@ -328,7 +328,7 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine) hwaddr ep; int is_linux; success = load_uimage(kernel_filename, &ep, NULL, &is_linux, - NULL, NULL); + translate_phys_addr, cpu); if (success > 0 && is_linux) { entry_point = ep; } else { -- 1.8.1.4
Re: [Qemu-devel] [Bug 1362755] [NEW] QEmu +2 does not route VLAN tagged packets, that are originated within the Hypervisor itself.
Oops! It seems to be working now! :-D This that I just said: I tried to disable tso/gso/tx at another guest, of vlan100 net, didn't > worked either. > Isn't true... I created a new guest, side-by-side with "guest-fw-1", on vlan100, and after disabling `tso/gso/tx`, its connectivity becomes stable! I'll try this: git://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git Nevertheless, I'm bit more confused now, the problem was fixed by disabling `tso/gso/tx` but, I did this *only within this new "guest-server-1"* that I created within vlan100... Only at it, I disabled "tso/gso/tx", so, the problem seems to not be within the "guest-fw-1" as I was thinking... Weird... Tks, Thiago > Regards, > Thiago > > On 29 August 2014 11:20, Vlad Yasevich wrote: > >> [ realized that the bug and reporter were non cc'd, updated cc list] >> >> On 08/28/2014 02:40 PM, Thiago Martins wrote: >> > Public bug reported: >> > >> > Guys, >> > >> > Trusty QEmu 2.0 Hypervisor fails to create a consistent virtual network. >> > It does not route tagged VLAN packets. >> > >> >> The have a been a bunch of rather recent changes to the kernel to support >> guest VLANs correctly. The issues have been around TSO/GSO implementation >> in the kernel. >> >> Could try disabling TSO/GSO and tx checksums on the vlan devices in the >> guest >> and see if it solves your problem? >> >> If it does, could you try the kernel from >> git://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git >> turn the offloads back on and see if the problem is solved? >> >> Thanks >> -vlad >> >> > That's it, it is impossible to use Trusty acting as a QEmu 2.0 >> > Hypervisor (metapakage `ubuntu-virt-server`), to make a basic virtual >> > tagged network within itself. QEmu 2.X guest does not route traffic when >> > with tagged VLANs! >> > >> > So, Trusty QEmu 2.0 Hypervisor cannot be used to host guests acting as >> > "firewalls / routers", and it have an easy to reproduce, connectivity >> > problem. >> > >> > This network problem affects Ubuntu 14.04.1 (Linux-3.13.0-35-generic) >> > with QEmu 2.0 (it also affects 14.10, Linux 3.16 - QEmu 2.1). >> > >> > I have this very same setup up and running, on about ~100 physical >> > servers (others Trusty QEmu 2.0 Hypervisors), and in only a few of them, >> > the QEmu Hypervisors dedicated to host "guest acting as routers / >> > firewalls", like a "borger gateway" for example, that it does not work >> > as expected. >> > >> > One interesting thing to note is that, this BUG appear only, and only >> > at, the QEmu Hypervisors dedicated to host guests that are used as >> > `router / firewalls` (as I said above), others QEmu Hypervisors of my >> > network does not suffer from this problem. >> > >> > Another interesting point is that it fails to route tagged VLAN packets >> > only when these packets are originated from within the Hypervisor >> > itself, I mean, packets from both host and other guests (not the >> > router/firewall guest itself), suffer from this connectivity problem. >> > >> > As a workaroung / fix, Xen-4.4 can be used, instead of QEmu 2.0, as a >> > "border hypervisor". So, this proves that there is something wrong with >> > QEmu. >> > >> > I already tested it with both `openvswitch-switch` and with `bridge- >> > utils`, same bad results. So, don't waste your time trying `bridge- >> > utils` (optional steps while reproducing it), you can keep OVS bridges >> > from original design. >> > >> > I think that I'm using the best pratices to build this environment, as >> > follows... >> > >> > >> > * Topology * >> > >> > >> > QEmu 2.0 Hypervisor - (qemu-host-1.domain.com - the "border >> hypervisor"): >> > >> > 1- Physical machine with 3 NICs; >> > 2- Minimal Ubuntu 14.04.1 installed and upgraded; >> > 3- Packages installed: "ubuntu-virt-server openvswitch-switch rdnssd >> tcpdump". >> > >> > - eth0 connected to the Internet - VLAN tag 10; >> > - eth1 connected to the LAN1 - VLAN tag 100; >> > - eth2 connected to the LAN2 - VLAN tag 200; >> > >> > >> > Guest (guest-fw-1.domain.com - the "border gateway" itself - regular >> guest acting as a router with iptables/ip6tables): >> > >> > 1- Virtual Machine with 3 NICs (VirtIO); >> > 2- Minimal Virtual Machine Ubuntu 14.04.1 installed and upgraded; >> > 3- Packages installed: "aiccu iptables vlan pv-grub-menu". >> > >> > >> > OBS: You'll need `virt-manager` to connect at `qemu-host-1` to install >> > `guest-fw-1`. Then, use `guest-fw-1` as a default gateway for your >> > (virt-)lab network, including the `qemu-host-1` itself. >> > >> > >> > Steps to reproduce >> > >> > >> > * Preparing the `qemu-host-1` host: >> > >> > - Configure the /etc/network/interfaces with: >> > >> > --- >> > # The loopback network interface >> > auto lo >> > iface lo inet loopback >> > >> > auto eth0 >> > iface eth0 inet manual >> > up ip link set $IFACE up >> > down ip link set $IFACE down >> > >> > auto eth1 >> > iface eth1 inet manual >> > up ip link set dev $IFACE u
Re: [Qemu-devel] [PATCH 3/3] libcacard: don't free sign buffer while sign op is pending
On 10/19/2014 05:12 AM, Ray Strode wrote: > From: Ray Strode > > commit 57f97834efe0c208ffadc9d2959f3d3d55580e52 cleaned up > the cac_applet_pki_process_apdu function to have a single > exit point. Unfortunately, that commit introduced a bug > where the sign buffer can get free'd and nullified while > it's still being used. > > This commit corrects the bug by introducing a boolean to > track whether or not the sign buffer should be freed in > the function exit path. My bad, thanks for catching this. Reviewed-by: Alon Levy > > Signed-off-by: Ray Strode > --- > libcacard/cac.c | 10 +++--- > 1 file changed, 7 insertions(+), 3 deletions(-) > > diff --git a/libcacard/cac.c b/libcacard/cac.c > index ae8c378..f38fdce 100644 > --- a/libcacard/cac.c > +++ b/libcacard/cac.c > @@ -88,60 +88,61 @@ cac_common_process_apdu(VCard *card, VCardAPDU *apdu, > VCardResponse **response) > } > > /* > * reset the inter call state between applet selects > */ > static VCardStatus > cac_applet_pki_reset(VCard *card, int channel) > { > VCardAppletPrivate *applet_private; > CACPKIAppletData *pki_applet; > applet_private = vcard_get_current_applet_private(card, channel); > assert(applet_private); > pki_applet = &(applet_private->u.pki_data); > > pki_applet->cert_buffer = NULL; > g_free(pki_applet->sign_buffer); > pki_applet->sign_buffer = NULL; > pki_applet->cert_buffer_len = 0; > pki_applet->sign_buffer_len = 0; > return VCARD_DONE; > } > > static VCardStatus > cac_applet_pki_process_apdu(VCard *card, VCardAPDU *apdu, > VCardResponse **response) > { > CACPKIAppletData *pki_applet; > VCardAppletPrivate *applet_private; > int size, next; > unsigned char *sign_buffer; > +bool retain_sign_buffer = FALSE; > vcard_7816_status_t status; > VCardStatus ret = VCARD_FAIL; > > applet_private = vcard_get_current_applet_private(card, apdu->a_channel); > assert(applet_private); > pki_applet = &(applet_private->u.pki_data); > > switch (apdu->a_ins) { > case CAC_UPDATE_BUFFER: > *response = vcard_make_response( > VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED); > ret = VCARD_DONE; > break; > case CAC_GET_CERTIFICATE: > if ((apdu->a_p2 != 0) || (apdu->a_p1 != 0)) { > *response = vcard_make_response( > VCARD7816_STATUS_ERROR_P1_P2_INCORRECT); > break; > } > assert(pki_applet->cert != NULL); > size = apdu->a_Le; > if (pki_applet->cert_buffer == NULL) { > pki_applet->cert_buffer = pki_applet->cert; > pki_applet->cert_buffer_len = pki_applet->cert_len; > } > size = MIN(size, pki_applet->cert_buffer_len); > next = MIN(255, pki_applet->cert_buffer_len - size); > *response = vcard_response_new_bytes( > card, pki_applet->cert_buffer, size, > apdu->a_Le, next ? > @@ -151,85 +152,88 @@ cac_applet_pki_process_apdu(VCard *card, VCardAPDU > *apdu, > pki_applet->cert_buffer += size; > pki_applet->cert_buffer_len -= size; > if ((*response == NULL) || (next == 0)) { > pki_applet->cert_buffer = NULL; > } > if (*response == NULL) { > *response = vcard_make_response( > VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE); > } > ret = VCARD_DONE; > break; > case CAC_SIGN_DECRYPT: > if (apdu->a_p2 != 0) { > *response = vcard_make_response( > VCARD7816_STATUS_ERROR_P1_P2_INCORRECT); > break; > } > size = apdu->a_Lc; > > sign_buffer = g_realloc(pki_applet->sign_buffer, > pki_applet->sign_buffer_len + size); > memcpy(sign_buffer+pki_applet->sign_buffer_len, apdu->a_body, size); > size += pki_applet->sign_buffer_len; > switch (apdu->a_p1) { > case 0x80: > /* p1 == 0x80 means we haven't yet sent the whole buffer, wait > for > * the rest */ > pki_applet->sign_buffer = sign_buffer; > pki_applet->sign_buffer_len = size; > *response = vcard_make_response(VCARD7816_STATUS_SUCCESS); > +retain_sign_buffer = TRUE; > break; > case 0x00: > /* we now have the whole buffer, do the operation, result will be > * in the sign_buffer */ > status = vcard_emul_rsa_op(card, pki_applet->key, > sign_buffer, size); > if (status != VCARD7816_STATUS_SUCCESS) { > *response = vcard_make_response(status); > break; > } > *response = vcard_re