diff --git a/25912-partial-libxl.patch b/25912-partial-libxl.patch new file mode 100644 index 0000000..baafd03 --- /dev/null +++ b/25912-partial-libxl.patch @@ -0,0 +1,146 @@ +No functional change. + +The purpose is to make it easier to backport patches from Xen 4.3's +libxl, as Xen 4.3's libxl has had this done: + + libxl: Enable -Wshadow. + + It was convenient to invent $(CFLAGS_LIBXL) to do this. + + Various renamings to avoid shadowing standard functions: + - index(3) + - listen(2) + - link(2) + - abort(3) + - abs(3) + + Signed-off-by: Ian Campbell + +In this patch we do not change the others, and we do not enable +-Wshadow. We're just trying to bring 4.2's libxl textually closer to +4.3's. + +Signed-off-by: Ian Jackson +--- + tools/libxl/libxl_event.c | 34 +++++++++++++++++----------------- + 1 files changed, 17 insertions(+), 17 deletions(-) + +Index: xen-4.2.1-testing/tools/libxl/libxl_event.c +=================================================================== +--- xen-4.2.1-testing.orig/tools/libxl/libxl_event.c ++++ xen-4.2.1-testing/tools/libxl/libxl_event.c +@@ -167,15 +167,15 @@ static void time_insert_finite(libxl__gc + } + + static int time_register_finite(libxl__gc *gc, libxl__ev_time *ev, +- struct timeval abs) ++ struct timeval absolute) + { + int rc; + +- rc = OSEVENT_HOOK(timeout_register, &ev->for_app_reg, abs, ev); ++ rc = OSEVENT_HOOK(timeout_register, &ev->for_app_reg, absolute, ev); + if (rc) return rc; + + ev->infinite = 0; +- ev->abs = abs; ++ ev->abs = absolute; + time_insert_finite(gc, ev); + + return 0; +@@ -202,16 +202,16 @@ static void time_done_debug(libxl__gc *g + + int libxl__ev_time_register_abs(libxl__gc *gc, libxl__ev_time *ev, + libxl__ev_time_callback *func, +- struct timeval abs) ++ struct timeval absolute) + { + int rc; + + CTX_LOCK; + + DBG("ev_time=%p register abs=%lu.%06lu", +- ev, (unsigned long)abs.tv_sec, (unsigned long)abs.tv_usec); ++ ev, (unsigned long)absolute.tv_sec, (unsigned long)absolute.tv_usec); + +- rc = time_register_finite(gc, ev, abs); ++ rc = time_register_finite(gc, ev, absolute); + if (rc) goto out; + + ev->func = func; +@@ -228,7 +228,7 @@ int libxl__ev_time_register_rel(libxl__g + libxl__ev_time_callback *func, + int milliseconds /* as for poll(2) */) + { +- struct timeval abs; ++ struct timeval absolute; + int rc; + + CTX_LOCK; +@@ -238,10 +238,10 @@ int libxl__ev_time_register_rel(libxl__g + if (milliseconds < 0) { + ev->infinite = 1; + } else { +- rc = time_rel_to_abs(gc, milliseconds, &abs); ++ rc = time_rel_to_abs(gc, milliseconds, &absolute); + if (rc) goto out; + +- rc = time_register_finite(gc, ev, abs); ++ rc = time_register_finite(gc, ev, absolute); + if (rc) goto out; + } + +@@ -255,26 +255,26 @@ int libxl__ev_time_register_rel(libxl__g + } + + int libxl__ev_time_modify_abs(libxl__gc *gc, libxl__ev_time *ev, +- struct timeval abs) ++ struct timeval absolute) + { + int rc; + + CTX_LOCK; + + DBG("ev_time=%p modify abs==%lu.%06lu", +- ev, (unsigned long)abs.tv_sec, (unsigned long)abs.tv_usec); ++ ev, (unsigned long)absolute.tv_sec, (unsigned long)absolute.tv_usec); + + assert(libxl__ev_time_isregistered(ev)); + + if (ev->infinite) { +- rc = time_register_finite(gc, ev, abs); ++ rc = time_register_finite(gc, ev, absolute); + if (rc) goto out; + } else { +- rc = OSEVENT_HOOK(timeout_modify, &ev->for_app_reg, abs); ++ rc = OSEVENT_HOOK(timeout_modify, &ev->for_app_reg, absolute); + if (rc) goto out; + + LIBXL_TAILQ_REMOVE(&CTX->etimes, ev, entry); +- ev->abs = abs; ++ ev->abs = absolute; + time_insert_finite(gc, ev); + } + +@@ -288,7 +288,7 @@ int libxl__ev_time_modify_abs(libxl__gc + int libxl__ev_time_modify_rel(libxl__gc *gc, libxl__ev_time *ev, + int milliseconds) + { +- struct timeval abs; ++ struct timeval absolute; + int rc; + + CTX_LOCK; +@@ -304,10 +304,10 @@ int libxl__ev_time_modify_rel(libxl__gc + goto out; + } + +- rc = time_rel_to_abs(gc, milliseconds, &abs); ++ rc = time_rel_to_abs(gc, milliseconds, &absolute); + if (rc) goto out; + +- rc = libxl__ev_time_modify_abs(gc, ev, abs); ++ rc = libxl__ev_time_modify_abs(gc, ev, absolute); + if (rc) goto out; + + rc = 0; diff --git a/26372-tools-paths.patch b/26372-tools-paths.patch new file mode 100644 index 0000000..6bf56d7 --- /dev/null +++ b/26372-tools-paths.patch @@ -0,0 +1,56 @@ +# HG changeset patch +# User Bamvor Jian Zhang +# Date 1357906948 0 +# Node ID 2ad5792b4274d76ced39515cbd3f84898b181768 +# Parent ba2d73234d73fc0faa027cd9bdfd3ac90642733c +fix wrong path while calling pygrub and libxl-save-helper + +in current xen x86_64, the default libexec directory is /usr/lib/xen/bin, +while the private binder is /usr/lib64/xen/bin. but some commands(pygrub, +libxl-save-helper) located in private binder directory is called from +libexec directory which lead to the following error: +1, for pygrub bootloader: + +libxl: debug: libxl_bootloader.c:429:bootloader_disk_attached_cb: /usr/lib/xen/bin/pygrub doesn't exist, falling back to config path + +2, for libxl-save-helper: + +libxl: cannot execute /usr/lib/xen/bin/libxl-save-helper: No such file or directory +libxl: error: libxl_utils.c:363:libxl_read_exactly: file/stream truncated reading ipc msg header from domain 3 save/restore helper stdout pipe +libxl: error: libxl_exec.c:118:libxl_report_child_exitstatus: domain 3 save/restore helper [10222] exited with error status 255 + +there are two ways to fix above error. the first one is make such command +store in the /usr/lib/xen/bin and /usr/lib64/xen/bin(symbol link to +previous), e.g. qemu-dm. The second way is using private binder dir +instead of libexec dir. e.g. xenconsole. +For these cases, the latter one is suitable. + +Signed-off-by: Bamvor Jian Zhang +Committed-by: Ian Campbell + +Index: xen-4.2.1-testing/tools/libxl/libxl_bootloader.c +=================================================================== +--- xen-4.2.1-testing.orig/tools/libxl/libxl_bootloader.c ++++ xen-4.2.1-testing/tools/libxl/libxl_bootloader.c +@@ -419,7 +419,7 @@ static void bootloader_disk_attached_cb( + const char *bltmp; + struct stat st; + +- bltmp = libxl__abs_path(gc, bootloader, libxl__libexec_path()); ++ bltmp = libxl__abs_path(gc, bootloader, libxl__private_bindir_path()); + /* Check to see if the file exists in this location; if not, + * fall back to checking the path */ + LOG(DEBUG, "Checking for bootloader in libexec path: %s", bltmp); +Index: xen-4.2.1-testing/tools/libxl/libxl_save_callout.c +=================================================================== +--- xen-4.2.1-testing.orig/tools/libxl/libxl_save_callout.c ++++ xen-4.2.1-testing/tools/libxl/libxl_save_callout.c +@@ -172,7 +172,7 @@ static void run_helper(libxl__egc *egc, + shs->stdout_what = GCSPRINTF("domain %"PRIu32" save/restore helper" + " stdout pipe", domid); + +- *arg++ = getenv("LIBXL_SAVE_HELPER") ?: LIBEXEC "/" "libxl-save-helper"; ++ *arg++ = getenv("LIBXL_SAVE_HELPER") ?: PRIVATE_BINDIR "/" "libxl-save-helper"; + *arg++ = mode_arg; + const char **stream_fd_arg = arg++; + for (i=0; i +# Date 1359031672 0 +# Node ID a181bf3e77df891c97fc20dff4e9b90b7584022b +# Parent 3e93c50982de4f2f7db99d92b04684556320541c +libxl: fix stale fd event callback race + +Because there is not necessarily any lock held at the point the +application (eg, libvirt) calls libxl_osevent_occurred_timeout and +..._fd, in a multithreaded program those calls may be arbitrarily +delayed in relation to other activities within the program. + +libxl therefore needs to be prepared to receive very old event +callbacks. Arrange for this to be the case for fd callbacks. + +This requires a new layer of indirection through a "hook nexus" struct +which can outlive the libxl__ev_foo. Allocation and deallocation of +these nexi is mostly handled in the OSEVENT macros which wrap up +the application's callbacks. + +Document the problem and the solution in a comment in libxl_event.c +just before the definition of struct libxl__osevent_hook_nexus. + +There is still a race relating to libxl__osevent_occurred_timeout; +this will be addressed in the following patch. + +Reported-by: Bamvor Jian Zhang +Cc: Bamvor Jian Zhang +Cc: Ian Campbell +Tested-by: Jim Fehlig +Acked-by: Jim Fehlig +Signed-off-by: Ian Jackson +Committed-by: Ian Campbell + +Index: xen-4.2.1-testing/tools/libxl/libxl_event.c +=================================================================== +--- xen-4.2.1-testing.orig/tools/libxl/libxl_event.c ++++ xen-4.2.1-testing/tools/libxl/libxl_event.c +@@ -38,23 +38,131 @@ + * The application's registration hooks should be called ONLY via + * these macros, with the ctx locked. Likewise all the "occurred" + * entrypoints from the application should assert(!in_hook); ++ * ++ * During the hook call - including while the arguments are being ++ * evaluated - ev->nexus is guaranteed to be valid and refer to the ++ * nexus which is being used for this event registration. The ++ * arguments should specify ev->nexus for the for_libxl argument and ++ * ev->nexus->for_app_reg (or a pointer to it) for for_app_reg. + */ +-#define OSEVENT_HOOK_INTERN(retval, hookname, ...) do { \ +- if (CTX->osevent_hooks) { \ +- CTX->osevent_in_hook++; \ +- retval CTX->osevent_hooks->hookname(CTX->osevent_user, __VA_ARGS__); \ +- CTX->osevent_in_hook--; \ +- } \ ++#define OSEVENT_HOOK_INTERN(retval, failedp, evkind, hookop, nexusop, ...) do { \ ++ if (CTX->osevent_hooks) { \ ++ CTX->osevent_in_hook++; \ ++ libxl__osevent_hook_nexi *nexi = &CTX->hook_##evkind##_nexi_idle; \ ++ osevent_hook_pre_##nexusop(gc, ev, nexi, &ev->nexus); \ ++ retval CTX->osevent_hooks->evkind##_##hookop \ ++ (CTX->osevent_user, __VA_ARGS__); \ ++ if ((failedp)) \ ++ osevent_hook_failed_##nexusop(gc, ev, nexi, &ev->nexus); \ ++ CTX->osevent_in_hook--; \ ++ } \ + } while (0) + +-#define OSEVENT_HOOK(hookname, ...) ({ \ +- int osevent_hook_rc = 0; \ +- OSEVENT_HOOK_INTERN(osevent_hook_rc = , hookname, __VA_ARGS__); \ +- osevent_hook_rc; \ ++#define OSEVENT_HOOK(evkind, hookop, nexusop, ...) ({ \ ++ int osevent_hook_rc = 0; \ ++ OSEVENT_HOOK_INTERN(osevent_hook_rc =, !!osevent_hook_rc, \ ++ evkind, hookop, nexusop, __VA_ARGS__); \ ++ osevent_hook_rc; \ + }) + +-#define OSEVENT_HOOK_VOID(hookname, ...) \ +- OSEVENT_HOOK_INTERN(/* void */, hookname, __VA_ARGS__) ++#define OSEVENT_HOOK_VOID(evkind, hookop, nexusop, ...) \ ++ OSEVENT_HOOK_INTERN(/* void */, 0, evkind, hookop, nexusop, __VA_ARGS__) ++ ++/* ++ * The application's calls to libxl_osevent_occurred_... may be ++ * indefinitely delayed with respect to the rest of the program (since ++ * they are not necessarily called with any lock held). So the ++ * for_libxl value we receive may be (almost) arbitrarily old. All we ++ * know is that it came from this ctx. ++ * ++ * Therefore we may not free the object referred to by any for_libxl ++ * value until we free the whole libxl_ctx. And if we reuse it we ++ * must be able to tell when an old use turns up, and discard the ++ * stale event. ++ * ++ * Thus we cannot use the ev directly as the for_libxl value - we need ++ * a layer of indirection. ++ * ++ * We do this by keeping a pool of libxl__osevent_hook_nexus structs, ++ * and use pointers to them as for_libxl values. In fact, there are ++ * two pools: one for fds and one for timeouts. This ensures that we ++ * don't risk a type error when we upcast nexus->ev. In each nexus ++ * the ev is either null or points to a valid libxl__ev_time or ++ * libxl__ev_fd, as applicable. ++ * ++ * We /do/ allow ourselves to reassociate an old nexus with a new ev ++ * as otherwise we would have to leak nexi. (This reassociation ++ * might, of course, be an old ev being reused for a new purpose so ++ * simply comparing the ev pointer is not sufficient.) Thus the ++ * libxl_osevent_occurred functions need to check that the condition ++ * allegedly signalled by this event actually exists. ++ * ++ * The nexi and the lists are all protected by the ctx lock. ++ */ ++ ++struct libxl__osevent_hook_nexus { ++ void *ev; ++ void *for_app_reg; ++ LIBXL_SLIST_ENTRY(libxl__osevent_hook_nexus) next; ++}; ++ ++static void *osevent_ev_from_hook_nexus(libxl_ctx *ctx, ++ libxl__osevent_hook_nexus *nexus /* pass void *for_libxl */) ++{ ++ return nexus->ev; ++} ++ ++static void osevent_release_nexus(libxl__gc *gc, ++ libxl__osevent_hook_nexi *nexi_idle, ++ libxl__osevent_hook_nexus *nexus) ++{ ++ nexus->ev = 0; ++ LIBXL_SLIST_INSERT_HEAD(nexi_idle, nexus, next); ++} ++ ++/*----- OSEVENT* hook functions for nexusop "alloc" -----*/ ++static void osevent_hook_pre_alloc(libxl__gc *gc, void *ev, ++ libxl__osevent_hook_nexi *nexi_idle, ++ libxl__osevent_hook_nexus **nexus_r) ++{ ++ libxl__osevent_hook_nexus *nexus = LIBXL_SLIST_FIRST(nexi_idle); ++ if (nexus) { ++ LIBXL_SLIST_REMOVE_HEAD(nexi_idle, next); ++ } else { ++ nexus = libxl__zalloc(NOGC, sizeof(*nexus)); ++ } ++ nexus->ev = ev; ++ *nexus_r = nexus; ++} ++static void osevent_hook_failed_alloc(libxl__gc *gc, void *ev, ++ libxl__osevent_hook_nexi *nexi_idle, ++ libxl__osevent_hook_nexus **nexus) ++{ ++ osevent_release_nexus(gc, nexi_idle, *nexus); ++} ++ ++/*----- OSEVENT* hook functions for nexusop "release" -----*/ ++static void osevent_hook_pre_release(libxl__gc *gc, void *ev, ++ libxl__osevent_hook_nexi *nexi_idle, ++ libxl__osevent_hook_nexus **nexus) ++{ ++ osevent_release_nexus(gc, nexi_idle, *nexus); ++} ++static void osevent_hook_failed_release(libxl__gc *gc, void *ev, ++ libxl__osevent_hook_nexi *nexi_idle, ++ libxl__osevent_hook_nexus **nexus) ++{ ++ abort(); ++} ++ ++/*----- OSEVENT* hook functions for nexusop "noop" -----*/ ++static void osevent_hook_pre_noop(libxl__gc *gc, void *ev, ++ libxl__osevent_hook_nexi *nexi_idle, ++ libxl__osevent_hook_nexus **nexus) { } ++static void osevent_hook_failed_noop(libxl__gc *gc, void *ev, ++ libxl__osevent_hook_nexi *nexi_idle, ++ libxl__osevent_hook_nexus **nexus) { } ++ + + /* + * fd events +@@ -72,7 +180,8 @@ int libxl__ev_fd_register(libxl__gc *gc, + + DBG("ev_fd=%p register fd=%d events=%x", ev, fd, events); + +- rc = OSEVENT_HOOK(fd_register, fd, &ev->for_app_reg, events, ev); ++ rc = OSEVENT_HOOK(fd,register, alloc, fd, &ev->nexus->for_app_reg, ++ events, ev->nexus); + if (rc) goto out; + + ev->fd = fd; +@@ -97,7 +206,7 @@ int libxl__ev_fd_modify(libxl__gc *gc, l + + DBG("ev_fd=%p modify fd=%d events=%x", ev, ev->fd, events); + +- rc = OSEVENT_HOOK(fd_modify, ev->fd, &ev->for_app_reg, events); ++ rc = OSEVENT_HOOK(fd,modify, noop, ev->fd, &ev->nexus->for_app_reg, events); + if (rc) goto out; + + ev->events = events; +@@ -119,7 +228,7 @@ void libxl__ev_fd_deregister(libxl__gc * + + DBG("ev_fd=%p deregister fd=%d", ev, ev->fd); + +- OSEVENT_HOOK_VOID(fd_deregister, ev->fd, ev->for_app_reg); ++ OSEVENT_HOOK_VOID(fd,deregister, release, ev->fd, ev->nexus->for_app_reg); + LIBXL_LIST_REMOVE(ev, entry); + ev->fd = -1; + +@@ -171,7 +280,8 @@ static int time_register_finite(libxl__g + { + int rc; + +- rc = OSEVENT_HOOK(timeout_register, &ev->for_app_reg, absolute, ev); ++ rc = OSEVENT_HOOK(timeout,register, alloc, &ev->nexus->for_app_reg, ++ absolute, ev->nexus); + if (rc) return rc; + + ev->infinite = 0; +@@ -184,7 +294,7 @@ static int time_register_finite(libxl__g + static void time_deregister(libxl__gc *gc, libxl__ev_time *ev) + { + if (!ev->infinite) { +- OSEVENT_HOOK_VOID(timeout_deregister, ev->for_app_reg); ++ OSEVENT_HOOK_VOID(timeout,deregister, release, ev->nexus->for_app_reg); + LIBXL_TAILQ_REMOVE(&CTX->etimes, ev, entry); + } + } +@@ -270,7 +380,8 @@ int libxl__ev_time_modify_abs(libxl__gc + rc = time_register_finite(gc, ev, absolute); + if (rc) goto out; + } else { +- rc = OSEVENT_HOOK(timeout_modify, &ev->for_app_reg, absolute); ++ rc = OSEVENT_HOOK(timeout,modify, noop, ++ &ev->nexus->for_app_reg, absolute); + if (rc) goto out; + + LIBXL_TAILQ_REMOVE(&CTX->etimes, ev, entry); +@@ -1009,35 +1120,54 @@ void libxl_osevent_register_hooks(libxl_ + + + void libxl_osevent_occurred_fd(libxl_ctx *ctx, void *for_libxl, +- int fd, short events, short revents) ++ int fd, short events_ign, short revents_ign) + { +- libxl__ev_fd *ev = for_libxl; +- + EGC_INIT(ctx); + CTX_LOCK; + assert(!CTX->osevent_in_hook); + +- assert(fd == ev->fd); +- revents &= ev->events; +- if (revents) +- ev->func(egc, ev, fd, ev->events, revents); ++ libxl__ev_fd *ev = osevent_ev_from_hook_nexus(ctx, for_libxl); ++ if (!ev) goto out; ++ if (ev->fd != fd) goto out; + ++ struct pollfd check; ++ for (;;) { ++ check.fd = fd; ++ check.events = ev->events; ++ int r = poll(&check, 1, 0); ++ if (!r) ++ goto out; ++ if (r==1) ++ break; ++ assert(r<0); ++ if (errno != EINTR) { ++ LIBXL__EVENT_DISASTER(egc, "failed poll to check for fd", errno, 0); ++ goto out; ++ } ++ } ++ ++ if (check.revents) ++ ev->func(egc, ev, fd, ev->events, check.revents); ++ ++ out: + CTX_UNLOCK; + EGC_FREE; + } + + void libxl_osevent_occurred_timeout(libxl_ctx *ctx, void *for_libxl) + { +- libxl__ev_time *ev = for_libxl; +- + EGC_INIT(ctx); + CTX_LOCK; + assert(!CTX->osevent_in_hook); + ++ libxl__ev_time *ev = osevent_ev_from_hook_nexus(ctx, for_libxl); ++ if (!ev) goto out; + assert(!ev->infinite); ++ + LIBXL_TAILQ_REMOVE(&CTX->etimes, ev, entry); + ev->func(egc, ev, &ev->abs); + ++ out: + CTX_UNLOCK; + EGC_FREE; + } +Index: xen-4.2.1-testing/tools/libxl/libxl_internal.h +=================================================================== +--- xen-4.2.1-testing.orig/tools/libxl/libxl_internal.h ++++ xen-4.2.1-testing/tools/libxl/libxl_internal.h +@@ -136,6 +136,8 @@ typedef struct libxl__gc libxl__gc; + typedef struct libxl__egc libxl__egc; + typedef struct libxl__ao libxl__ao; + typedef struct libxl__aop_occurred libxl__aop_occurred; ++typedef struct libxl__osevent_hook_nexus libxl__osevent_hook_nexus; ++typedef struct libxl__osevent_hook_nexi libxl__osevent_hook_nexi; + + _hidden void libxl__alloc_failed(libxl_ctx *, const char *func, + size_t nmemb, size_t size) __attribute__((noreturn)); +@@ -163,7 +165,7 @@ struct libxl__ev_fd { + libxl__ev_fd_callback *func; + /* remainder is private for libxl__ev_fd... */ + LIBXL_LIST_ENTRY(libxl__ev_fd) entry; +- void *for_app_reg; ++ libxl__osevent_hook_nexus *nexus; + }; + + +@@ -178,7 +180,7 @@ struct libxl__ev_time { + int infinite; /* not registered in list or with app if infinite */ + LIBXL_TAILQ_ENTRY(libxl__ev_time) entry; + struct timeval abs; +- void *for_app_reg; ++ libxl__osevent_hook_nexus *nexus; + }; + + typedef struct libxl__ev_xswatch libxl__ev_xswatch; +@@ -329,6 +331,8 @@ struct libxl__ctx { + libxl__poller poller_app; /* libxl_osevent_beforepoll and _afterpoll */ + LIBXL_LIST_HEAD(, libxl__poller) pollers_event, pollers_idle; + ++ LIBXL_SLIST_HEAD(libxl__osevent_hook_nexi, libxl__osevent_hook_nexus) ++ hook_fd_nexi_idle, hook_timeout_nexi_idle; + LIBXL_LIST_HEAD(, libxl__ev_fd) efds; + LIBXL_TAILQ_HEAD(, libxl__ev_time) etimes; + diff --git a/26469-libxl-race.patch b/26469-libxl-race.patch new file mode 100644 index 0000000..a099ff6 --- /dev/null +++ b/26469-libxl-race.patch @@ -0,0 +1,228 @@ +# HG changeset patch +# User Ian Jackson +# Date 1359031673 0 +# Node ID a162a72e719a85799e3b08f52af7bb2147a407b8 +# Parent a181bf3e77df891c97fc20dff4e9b90b7584022b +libxl: fix stale timeout event callback race + +Because there is not necessarily any lock held at the point the +application (eg, libvirt) calls libxl_osevent_occurred_timeout, in a +multithreaded program those calls may be arbitrarily delayed in +relation to other activities within the program. + +Specifically this means when ->timeout_deregister returns, libxl does +not know whether it can safely dispose of the for_libxl value or +whether it needs to retain it in case of an in-progress call to +_occurred_timeout. + +The interface could be fixed by requiring the application to make a +new call into libxl to say that the deregistration was complete. + +However that new call would have to be threaded through the +application's event loop; this is complicated and some application +authors are likely not to implement it properly. Furthermore the +easiest way to implement this facility in most event loops is to queue +up a time event for "now". + +Shortcut all of this by having libxl always call timeout_modify +setting abs={0,0} (ie, ASAP) instead of timeout_deregister. This will +cause the application to call _occurred_timeout. When processing this +calldown we see that we were no longer actually interested and simply +throw it away. + +Additionally, there is a race between _occurred_timeout and +->timeout_modify. If libxl ever adjusts the deadline for a timeout +the application may already be in the process of calling _occurred, in +which case the situation with for_app's lifetime becomes very +complicated. Therefore abolish libxl__ev_time_modify_{abs,rel} (which +have no callers) and promise to the application only ever to call +->timeout_modify with abs=={0,0}. The application still needs to cope +with ->timeout_modify racing with its internal function which calls +_occurred_timeout. Document this. + +This is a forwards-compatible change for applications using the libxl +API, and will hopefully eliminate these races in callback-supplying +applications (such as libvirt) without the need for corresponding +changes to the application. (It is possible that this might expose +bugs in applications, though, as previously libxl would never call +libxl_osevent_hooks->timeout_modify and now it never calls +->timeout_deregister). + +For clarity, fold the body of time_register_finite into its one +remaining call site. This makes the semantics of ev->infinite +slightly clearer. + +Cc: Bamvor Jian Zhang +Cc: Ian Campbell +Tested-by: Jim Fehlig +Acked-by: Jim Fehlig +Signed-off-by: Ian Jackson +Committed-by: Ian Campbell + +Index: xen-4.2.1-testing/tools/libxl/libxl_event.c +=================================================================== +--- xen-4.2.1-testing.orig/tools/libxl/libxl_event.c ++++ xen-4.2.1-testing/tools/libxl/libxl_event.c +@@ -267,18 +267,11 @@ static int time_rel_to_abs(libxl__gc *gc + return 0; + } + +-static void time_insert_finite(libxl__gc *gc, libxl__ev_time *ev) +-{ +- libxl__ev_time *evsearch; +- LIBXL_TAILQ_INSERT_SORTED(&CTX->etimes, entry, ev, evsearch, /*empty*/, +- timercmp(&ev->abs, &evsearch->abs, >)); +- ev->infinite = 0; +-} +- + static int time_register_finite(libxl__gc *gc, libxl__ev_time *ev, + struct timeval absolute) + { + int rc; ++ libxl__ev_time *evsearch; + + rc = OSEVENT_HOOK(timeout,register, alloc, &ev->nexus->for_app_reg, + absolute, ev->nexus); +@@ -286,7 +279,8 @@ static int time_register_finite(libxl__g + + ev->infinite = 0; + ev->abs = absolute; +- time_insert_finite(gc, ev); ++ LIBXL_TAILQ_INSERT_SORTED(&CTX->etimes, entry, ev, evsearch, /*empty*/, ++ timercmp(&ev->abs, &evsearch->abs, >)); + + return 0; + } +@@ -294,7 +288,12 @@ static int time_register_finite(libxl__g + static void time_deregister(libxl__gc *gc, libxl__ev_time *ev) + { + if (!ev->infinite) { +- OSEVENT_HOOK_VOID(timeout,deregister, release, ev->nexus->for_app_reg); ++ struct timeval right_away = { 0, 0 }; ++ if (ev->nexus) /* only set if app provided hooks */ ++ ev->nexus->ev = 0; ++ OSEVENT_HOOK_VOID(timeout,modify, ++ noop /* release nexus in _occurred_ */, ++ &ev->nexus->for_app_reg, right_away); + LIBXL_TAILQ_REMOVE(&CTX->etimes, ev, entry); + } + } +@@ -364,70 +363,6 @@ int libxl__ev_time_register_rel(libxl__g + return rc; + } + +-int libxl__ev_time_modify_abs(libxl__gc *gc, libxl__ev_time *ev, +- struct timeval absolute) +-{ +- int rc; +- +- CTX_LOCK; +- +- DBG("ev_time=%p modify abs==%lu.%06lu", +- ev, (unsigned long)absolute.tv_sec, (unsigned long)absolute.tv_usec); +- +- assert(libxl__ev_time_isregistered(ev)); +- +- if (ev->infinite) { +- rc = time_register_finite(gc, ev, absolute); +- if (rc) goto out; +- } else { +- rc = OSEVENT_HOOK(timeout,modify, noop, +- &ev->nexus->for_app_reg, absolute); +- if (rc) goto out; +- +- LIBXL_TAILQ_REMOVE(&CTX->etimes, ev, entry); +- ev->abs = absolute; +- time_insert_finite(gc, ev); +- } +- +- rc = 0; +- out: +- time_done_debug(gc,__func__,ev,rc); +- CTX_UNLOCK; +- return rc; +-} +- +-int libxl__ev_time_modify_rel(libxl__gc *gc, libxl__ev_time *ev, +- int milliseconds) +-{ +- struct timeval absolute; +- int rc; +- +- CTX_LOCK; +- +- DBG("ev_time=%p modify ms=%d", ev, milliseconds); +- +- assert(libxl__ev_time_isregistered(ev)); +- +- if (milliseconds < 0) { +- time_deregister(gc, ev); +- ev->infinite = 1; +- rc = 0; +- goto out; +- } +- +- rc = time_rel_to_abs(gc, milliseconds, &absolute); +- if (rc) goto out; +- +- rc = libxl__ev_time_modify_abs(gc, ev, absolute); +- if (rc) goto out; +- +- rc = 0; +- out: +- time_done_debug(gc,__func__,ev,rc); +- CTX_UNLOCK; +- return rc; +-} +- + void libxl__ev_time_deregister(libxl__gc *gc, libxl__ev_time *ev) + { + CTX_LOCK; +@@ -1160,7 +1095,11 @@ void libxl_osevent_occurred_timeout(libx + CTX_LOCK; + assert(!CTX->osevent_in_hook); + +- libxl__ev_time *ev = osevent_ev_from_hook_nexus(ctx, for_libxl); ++ libxl__osevent_hook_nexus *nexus = for_libxl; ++ libxl__ev_time *ev = osevent_ev_from_hook_nexus(ctx, nexus); ++ ++ osevent_release_nexus(gc, &CTX->hook_timeout_nexi_idle, nexus); ++ + if (!ev) goto out; + assert(!ev->infinite); + +Index: xen-4.2.1-testing/tools/libxl/libxl_event.h +=================================================================== +--- xen-4.2.1-testing.orig/tools/libxl/libxl_event.h ++++ xen-4.2.1-testing/tools/libxl/libxl_event.h +@@ -287,8 +287,10 @@ typedef struct libxl_osevent_hooks { + int (*timeout_register)(void *user, void **for_app_registration_out, + struct timeval abs, void *for_libxl); + int (*timeout_modify)(void *user, void **for_app_registration_update, +- struct timeval abs); +- void (*timeout_deregister)(void *user, void *for_app_registration); ++ struct timeval abs) ++ /* only ever called with abs={0,0}, meaning ASAP */; ++ void (*timeout_deregister)(void *user, void *for_app_registration) ++ /* will never be called */; + } libxl_osevent_hooks; + + /* The application which calls register_fd_hooks promises to +@@ -337,6 +339,17 @@ typedef struct libxl_osevent_hooks { + * register (or modify), and pass it to subsequent calls to modify + * or deregister. + * ++ * Note that the application must cope with a call from libxl to ++ * timeout_modify racing with its own call to ++ * libxl__osevent_occurred_timeout. libxl guarantees that ++ * timeout_modify will only be called with abs={0,0} but the ++ * application must still ensure that libxl's attempt to cause the ++ * timeout to occur immediately is safely ignored even the timeout is ++ * actually already in the process of occurring. ++ * ++ * timeout_deregister is not used because it forms part of a ++ * deprecated unsafe mode of use of the API. ++ * + * osevent_register_hooks may be called only once for each libxl_ctx. + * libxl may make calls to register/modify/deregister from within + * any libxl function (indeed, it will usually call register from diff --git a/init.xend b/init.xend index 36de204..98fabdc 100644 --- a/init.xend +++ b/init.xend @@ -7,9 +7,9 @@ # ### BEGIN INIT INFO # Provides: xend -# Required-Start: $syslog $remote_fs +# Required-Start: $syslog $network $remote_fs # Should-Start: iscsi $time -# Required-Stop: $syslog $remote_fs +# Required-Stop: $syslog $network $remote_fs # Should-Stop: iscsi $time # Default-Start: 3 5 # Default-Stop: 0 1 2 6 diff --git a/xen.changes b/xen.changes index da8dc8b..5a8645a 100644 --- a/xen.changes +++ b/xen.changes @@ -1,3 +1,18 @@ +------------------------------------------------------------------- +Fri Jan 25 14:57:30 MST 2013 - jfehlig@suse.com + +- bnc#798188 - Add $network to xend initscript dependencies + +------------------------------------------------------------------- +Thu Jan 24 15:57:12 MST 2013 - jfehlig@suse.com + +- Add upstream patches to fix libxl bugs. These patches have + already been posted for inclusion in xen-4.2-testing. + 25912-partial-libxl.patch + 26372-tools-paths.patch + 26468-libxl-race.patch + 26469-libxl-race.patch + ------------------------------------------------------------------- Tue Jan 22 08:12:39 MST 2013 - carnold@novell.com @@ -18,7 +33,7 @@ Thu Jan 17 14:13:52 MST 2013 - carnold@novell.com Removed reverse-24757-use-grant-references.patch ------------------------------------------------------------------- -Wed Jan 16 11:26:29 MST 2013 +Wed Jan 16 11:26:29 MST 2013 - carnold@novell.com - bnc#797523 - VUL-1: CVE-2012-6075: qemu / kvm-qemu: e1000 overflows under some conditions diff --git a/xen.spec b/xen.spec index 9285ee9..0e753ba 100644 --- a/xen.spec +++ b/xen.spec @@ -15,7 +15,6 @@ # Please submit bugfixes or comments via http://bugs.opensuse.org/ # - Name: xen ExclusiveArch: %ix86 x86_64 %define xvers 4.2 @@ -115,7 +114,7 @@ BuildRequires: kernel-syms BuildRequires: module-init-tools BuildRequires: xorg-x11 %endif -Version: 4.2.1_03 +Version: 4.2.1_04 Release: 0 PreReq: %insserv_prereq %fillup_prereq Summary: Xen Virtualization: Hypervisor (aka VMM aka Microkernel) @@ -173,6 +172,7 @@ Patch25866: 25866-sercon-ns16550-pci-irq.patch Patch25867: 25867-sercon-ns16550-parse.patch Patch25874: 25874-x86-EFI-chain-cfg.patch Patch25909: 25909-xenpm-consistent.patch +Patch25912: 25912-partial-libxl.patch Patch25920: 25920-x86-APICV-enable.patch Patch25921: 25921-x86-APICV-delivery.patch Patch25922: 25922-x86-APICV-x2APIC.patch @@ -222,6 +222,9 @@ Patch26341: 26341-hvm-firmware-passthrough.patch Patch26342: 26342-hvm-firmware-passthrough.patch Patch26343: 26343-hvm-firmware-passthrough.patch Patch26344: 26344-hvm-firmware-passthrough.patch +Patch26372: 26372-tools-paths.patch +Patch26468: 26468-libxl-race.patch +Patch26469: 26469-libxl-race.patch Patch33: CVE-2012-5634-xsa33.patch Patch34: CVE-2013-0151-xsa34.patch Patch35: CVE-2013-0152-xsa35.patch @@ -689,6 +692,7 @@ tar xfj %{SOURCE6} -C $RPM_BUILD_DIR/%{xen_build_dir}/tools %patch25867 -p1 %patch25874 -p1 %patch25909 -p1 +%patch25912 -p1 %patch25920 -p1 %patch25921 -p1 %patch25922 -p1 @@ -738,6 +742,9 @@ tar xfj %{SOURCE6} -C $RPM_BUILD_DIR/%{xen_build_dir}/tools %patch26342 -p1 %patch26343 -p1 %patch26344 -p1 +%patch26372 -p1 +%patch26468 -p1 +%patch26469 -p1 %patch33 -p1 %patch34 -p1 %patch35 -p1