From: "Daniel P. Berrange" <berrange(a)redhat.com>
Currently the LXC driver logs audit messages when a container
is started or stopped. These audit messages, however, contain
the PID of the libvirt_lxc supervisor process. To enable
sysadmins to correlate with audit messages generated by
processes /inside/ the container, we need to include the
container init process PID.
We can't do this in the main 'start' audit message, since
the init PID is not available at that point. Instead we output
a completely new audit record, that lists both PIDs.
type=VIRT_CONTROL msg=audit(1353433750.071:363): pid=20180 uid=0 auid=501 ses=3
subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 msg='virt=lxc op=init
vm="busy" uuid=dda7b947-0846-1759-2873-0f375df7d7eb vm-pid=20371 init-pid=20372
exe="/home/berrange/src/virt/libvirt/daemon/.libs/lt-libvirtd" hostname=? addr=?
terminal=pts/6 res=success'
---
src/conf/domain_audit.c | 26 ++++++++++++++++++++++++++
src/conf/domain_audit.h | 3 +++
src/libvirt_private.syms | 1 +
src/lxc/lxc_controller.c | 31 ++++++++++++++++++++++++++++++-
src/lxc/lxc_monitor.c | 23 +++++++++++++++++++++++
src/lxc/lxc_monitor.h | 5 +++++
src/lxc/lxc_process.c | 8 ++++++++
src/lxc/lxc_protocol.x | 7 ++++++-
8 files changed, 102 insertions(+), 2 deletions(-)
diff --git a/src/conf/domain_audit.c b/src/conf/domain_audit.c
index 0f3924a..34cd92e 100644
--- a/src/conf/domain_audit.c
+++ b/src/conf/domain_audit.c
@@ -605,6 +605,32 @@ virDomainAuditStart(virDomainObjPtr vm, const char *reason, bool
success)
virDomainAuditLifecycle(vm, "start", reason, success);
}
+void
+virDomainAuditInit(virDomainObjPtr vm,
+ unsigned long long initpid)
+{
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ char *vmname;
+ const char *virt;
+
+ virUUIDFormat(vm->def->uuid, uuidstr);
+
+ if (!(vmname = virAuditEncode("vm", vm->def->name))) {
+ VIR_WARN("OOM while encoding audit message");
+ return;
+ }
+
+ if (!(virt = virDomainVirtTypeToString(vm->def->virtType))) {
+ VIR_WARN("Unexpected virt type %d while encoding audit message",
vm->def->virtType);
+ virt = "?";
+ }
+
+ VIR_AUDIT(VIR_AUDIT_RECORD_MACHINE_CONTROL, true,
+ "virt=%s op=init %s uuid=%s vm-pid=%lld init-pid=%lld",
+ virt, vmname, uuidstr, (long long)vm->pid, initpid);
+
+ VIR_FREE(vmname);
+}
void
virDomainAuditStop(virDomainObjPtr vm, const char *reason)
diff --git a/src/conf/domain_audit.h b/src/conf/domain_audit.h
index db35d09..94b1198 100644
--- a/src/conf/domain_audit.h
+++ b/src/conf/domain_audit.h
@@ -31,6 +31,9 @@ void virDomainAuditStart(virDomainObjPtr vm,
const char *reason,
bool success)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+void virDomainAuditInit(virDomainObjPtr vm,
+ unsigned long long pid)
+ ATTRIBUTE_NONNULL(1);
void virDomainAuditStop(virDomainObjPtr vm,
const char *reason)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 5a07139..23369e7 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -258,6 +258,7 @@ virDomainAuditCgroupPath;
virDomainAuditDisk;
virDomainAuditFS;
virDomainAuditHostdev;
+virDomainAuditInit;
virDomainAuditMemory;
virDomainAuditNet;
virDomainAuditNetDevice;
diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
index 4746897..65d117a 100644
--- a/src/lxc/lxc_controller.c
+++ b/src/lxc/lxc_controller.c
@@ -123,6 +123,7 @@ struct _virLXCController {
/* Server socket */
virNetServerPtr server;
+ bool firstClient;
virNetServerClientPtr client;
virNetServerProgramPtr prog;
bool inShutdown;
@@ -132,6 +133,8 @@ struct _virLXCController {
#include "lxc_controller_dispatch.h"
static void virLXCControllerFree(virLXCControllerPtr ctrl);
+static int virLXCControllerEventSendInit(virLXCControllerPtr ctrl,
+ pid_t initpid);
static void virLXCControllerQuitTimer(int timer ATTRIBUTE_UNUSED, void *opaque)
{
@@ -152,6 +155,7 @@ static virLXCControllerPtr virLXCControllerNew(const char *name)
goto no_memory;
ctrl->timerShutdown = -1;
+ ctrl->firstClient = true;
if (!(ctrl->name = strdup(name)))
goto no_memory;
@@ -588,6 +592,11 @@ static void *virLXCControllerClientPrivateNew(virNetServerClientPtr
client,
virNetServerClientSetCloseHook(client, virLXCControllerClientCloseHook);
VIR_DEBUG("Got new client %p", client);
ctrl->client = client;
+
+ if (ctrl->initpid && ctrl->firstClient)
+ virLXCControllerEventSendInit(ctrl, ctrl->initpid);
+ ctrl->firstClient = false;
+
return dummy;
}
@@ -1283,8 +1292,10 @@ virLXCControllerEventSend(virLXCControllerPtr ctrl,
{
virNetMessagePtr msg;
- if (!ctrl->client)
+ if (!ctrl->client) {
+ VIR_WARN("Dropping event %d becuase libvirtd is not connected",
procnr);
return;
+ }
VIR_DEBUG("Send event %d client=%p", procnr, ctrl->client);
if (!(msg = virNetMessageNew(false)))
@@ -1352,6 +1363,24 @@ virLXCControllerEventSendExit(virLXCControllerPtr ctrl,
static int
+virLXCControllerEventSendInit(virLXCControllerPtr ctrl,
+ pid_t initpid)
+{
+ virLXCProtocolInitEventMsg msg;
+
+ VIR_DEBUG("Init pid %llu", (unsigned long long)initpid);
+ memset(&msg, 0, sizeof(msg));
+ msg.initpid = initpid;
+
+ virLXCControllerEventSend(ctrl,
+ VIR_LXC_PROTOCOL_PROC_INIT_EVENT,
+ (xdrproc_t)xdr_virLXCProtocolInitEventMsg,
+ (void*)&msg);
+ return 0;
+}
+
+
+static int
virLXCControllerRun(virLXCControllerPtr ctrl)
{
int rc = -1;
diff --git a/src/lxc/lxc_monitor.c b/src/lxc/lxc_monitor.c
index 3e00751..97ff828 100644
--- a/src/lxc/lxc_monitor.c
+++ b/src/lxc/lxc_monitor.c
@@ -65,12 +65,20 @@ static void
virLXCMonitorHandleEventExit(virNetClientProgramPtr prog,
virNetClientPtr client,
void *evdata, void *opaque);
+static void
+virLXCMonitorHandleEventInit(virNetClientProgramPtr prog,
+ virNetClientPtr client,
+ void *evdata, void *opaque);
static virNetClientProgramEvent virLXCProtocolEvents[] = {
{ VIR_LXC_PROTOCOL_PROC_EXIT_EVENT,
virLXCMonitorHandleEventExit,
sizeof(virLXCProtocolExitEventMsg),
(xdrproc_t)xdr_virLXCProtocolExitEventMsg },
+ { VIR_LXC_PROTOCOL_PROC_INIT_EVENT,
+ virLXCMonitorHandleEventInit,
+ sizeof(virLXCProtocolInitEventMsg),
+ (xdrproc_t)xdr_virLXCProtocolInitEventMsg },
};
@@ -88,6 +96,21 @@ virLXCMonitorHandleEventExit(virNetClientProgramPtr prog
ATTRIBUTE_UNUSED,
}
+static void
+virLXCMonitorHandleEventInit(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
+ virNetClientPtr client ATTRIBUTE_UNUSED,
+ void *evdata, void *opaque)
+{
+ virLXCMonitorPtr mon = opaque;
+ virLXCProtocolInitEventMsg *msg = evdata;
+
+ VIR_DEBUG("Event init %llu",
+ (unsigned long long)msg->initpid);
+ if (mon->cb.initNotify)
+ mon->cb.initNotify(mon, msg->initpid, mon->vm);
+}
+
+
static void virLXCMonitorEOFNotify(virNetClientPtr client ATTRIBUTE_UNUSED,
int reason ATTRIBUTE_UNUSED,
void *opaque)
diff --git a/src/lxc/lxc_monitor.h b/src/lxc/lxc_monitor.h
index bb8349a..fd8efd9 100644
--- a/src/lxc/lxc_monitor.h
+++ b/src/lxc/lxc_monitor.h
@@ -40,10 +40,15 @@ typedef void (*virLXCMonitorCallbackExitNotify)(virLXCMonitorPtr mon,
virLXCProtocolExitStatus status,
virDomainObjPtr vm);
+typedef void (*virLXCMonitorCallbackInitNotify)(virLXCMonitorPtr mon,
+ unsigned long long pid,
+ virDomainObjPtr vm);
+
struct _virLXCMonitorCallbacks {
virLXCMonitorCallbackDestroy destroy;
virLXCMonitorCallbackEOFNotify eofNotify;
virLXCMonitorCallbackExitNotify exitNotify;
+ virLXCMonitorCallbackInitNotify initNotify;
};
virLXCMonitorPtr virLXCMonitorNew(virDomainObjPtr vm,
diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c
index 079bc3a..c1ef2bd 100644
--- a/src/lxc/lxc_process.c
+++ b/src/lxc/lxc_process.c
@@ -637,9 +637,17 @@ static void virLXCProcessMonitorExitNotify(virLXCMonitorPtr mon
ATTRIBUTE_UNUSED
priv->stopReason, status);
}
+static void virLXCProcessMonitorInitNotify(virLXCMonitorPtr mon ATTRIBUTE_UNUSED,
+ unsigned long long initpid,
+ virDomainObjPtr vm)
+{
+ virDomainAuditInit(vm, initpid);
+}
+
static virLXCMonitorCallbacks monitorCallbacks = {
.eofNotify = virLXCProcessMonitorEOFNotify,
.exitNotify = virLXCProcessMonitorExitNotify,
+ .initNotify = virLXCProcessMonitorInitNotify,
};
diff --git a/src/lxc/lxc_protocol.x b/src/lxc/lxc_protocol.x
index e437217..0f041f6 100644
--- a/src/lxc/lxc_protocol.x
+++ b/src/lxc/lxc_protocol.x
@@ -14,9 +14,14 @@ struct virLXCProtocolExitEventMsg {
enum virLXCProtocolExitStatus status;
};
+struct virLXCProtocolInitEventMsg {
+ unsigned hyper initpid;
+};
+
const VIR_LXC_PROTOCOL_PROGRAM = 0x12341234;
const VIR_LXC_PROTOCOL_PROGRAM_VERSION = 1;
enum virLXCProtocolProcedure {
- VIR_LXC_PROTOCOL_PROC_EXIT_EVENT = 1 /* skipgen skipgen */
+ VIR_LXC_PROTOCOL_PROC_EXIT_EVENT = 1, /* skipgen skipgen */
+ VIR_LXC_PROTOCOL_PROC_INIT_EVENT = 2 /* skipgen skipgen */
};
--
1.7.11.7