[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH 8/9] libxl: Kill QEMU by uid when possible
George Dunlap writes ("[PATCH 8/9] libxl: Kill QEMU by uid when possible"): > The privcmd fd that a dm_restrict'ed QEMU has gives it permission to > one specific domain ID. This domain ID will probably eventually be > used again. It is therefore necessary to make absolutely sure that a > rogue QEMU process cannot hang around after its domain has exited. Thanks. This looks roughly right but I have some coding style quibbles, and I am not convinced the error handling is right. > @@ -2382,6 +2389,15 @@ void libxl__spawn_local_dm(libxl__egc *egc, > libxl__dm_spawn_state *dmss) > > const char *dom_path = libxl__xs_get_dompath(gc, domid); > > + /* > + * If we're stating the dm with a non-root UID, save the UID so Typo for `starting'. > + * that we can reliably kill it and any subprocesses > + */ ... > +static void kill_device_model_uid_cb(libxl__egc *egc, > + libxl__ev_child *destroyer, > + pid_t pid, int status); > + > void libxl__destroy_device_model(libxl__egc *egc, > libxl__destroy_devicemodel_state *ddms) > { > @@ -2658,15 +2678,103 @@ void libxl__destroy_device_model(libxl__egc *egc, > int rc; > int domid = ddms->domid; > char *path = DEVICE_MODEL_XS_PATH(gc, LIBXL_TOOLSTACK_DOMID, domid, ""); > + const char * dm_uid_str; > + uid_t dm_uid; > + int reaper_pid; > + int ret; > > if (!xs_rm(CTX->xsh, XBT_NULL, path)) > LOGD(ERROR, domid, "xs_rm failed for %s", path); > > - /* We should try to destroy the device model anyway. */ > - rc = kill_device_model(gc, > - GCSPRINTF("/local/domain/%d/image/device-model-pid", domid)); > + /* > + * We should try to destroy the device model anyway. Check to see > + * if we can kill by UID > + */ > + ret = libxl__xs_read_checked(gc, XBT_NULL, > + > GCSPRINTF("/local/domain/%d/image/device-model-uid", > + domid), > + &dm_uid_str); I know this function is bad in its use of `rc' for syscall return but please don't make it worse by introducing `ret' for what should be `rc'. Would you mind adding a pre-patch to change `rc' to `r' and then you can use `rc' ? > + if (ret || !dm_uid_str) { Shouldn't we fail if libxl__xs_read_checked fails ? Otherwise we risk leaving fragments of domain behind even if we fail. (Possibly we should carry on, but accumulate errors in rc.) > + /* No uid in xenstore; just kill the pid we have */ > + LOGD(DEBUG, domid, "Didn't find dm UID; destroying by pid"); > + > + rc = kill_device_model(gc, > + > GCSPRINTF("/local/domain/%d/image/device-model-pid", domid)); > + > + libxl__qmp_cleanup(gc, domid); > + > + ddms->callback(egc, ddms, rc); > + return; Can you please break out this little exit code fragment + libxl__qmp_cleanup(gc, domid); + ddms->callback(egc, ddms, rc); into a sub-function ? It occurs twice and it is easier to reason about things if the operation has a single exit path. > + /* QEMU has its own uid; kill all processes with that UID */ > + LOGD(DEBUG, domid, "Found DM uid %s, destroying by uid", dm_uid_str); > + > + dm_uid = atoi(dm_uid_str); I am tempted to suggest a more robust use of strtoul here but since this came from our own xenstore node, fine. > + reaper_pid = libxl__ev_child_fork(gc, &ddms->destroyer, > + kill_device_model_uid_cb); > + if (reaper_pid < 0) > + ddms->callback(egc, ddms, ERROR_FAIL); > + } > + And, voila! Didn't you mean to call libxl__qmp_cleanup ? You're missing the exit path. And maybe the call to it should be an `out' block in this function. Also, amazingly, you don't return or anything here. This is only not a bug because the rest is all the child process. > + if (!reaper_pid) { /* child */ > + const char * call; > + > + /* > + * FIXME: the second uid needs to be distinct to avoid being > + * killed by a potential rogue process > + */ This is a bit of a funny way of introducing this but fine. > + ret = setresuid(dm_uid, dm_uid, 0); > + if (ret) { > + call = "setresuid"; > + goto badchild; > + } > + > + /* And kill everyone but me */ > + ret = kill(-1, 9); > + if (ret) { > + call = "kill"; > + goto badchild; > + } > + _exit(0); > + > + badchild: > + if (errno > 0 && errno < 126) { > + _exit(errno); > + } else { > + LOGED(ERROR, domid, > + "Call %s failed (with difficult errno value %d)", > + call, errno); > + _exit(-1); > + } > + } I don't much like these gotos either. Maybe a subfunction is called for. Furthermore, once again please see CODING_STYLE re conventional variable names `r' and `rc'· > +out: > + libxl__qmp_cleanup(gc, ddms->domid); > ddms->callback(egc, ddms, rc); Here's that finish fragment again. > index 899a86e84b..59eac0662a 100644 > --- a/tools/libxl/libxl_internal.h > +++ b/tools/libxl/libxl_internal.h > @@ -1135,7 +1135,7 @@ typedef struct { > const char * shim_cmdline; > const char * pv_cmdline; > > - char * dm_runas; > + char * dm_runas, *dm_uid; It would be nice to drop the spurious space before dm_runas while you are here, and then presumably the double space before *dm_uid would not be needed. Thanks, Ian. _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |