@@ -224,3 +224,31 @@ device-specific memory (DMA, emulated MMIO, reserved by a passthrough
device etc.). It is up to the user to determine, using the guest operating
system data structures, the areas that are safe to access (code, stack, heap
etc.).
+
+Commands
+--------
+
+The following C structures are meant to be used directly when communicating
+over the wire. The peer that detects any size mismatch should simply close
+the connection and report the error.
+
+1. KVMI_GET_VERSION
+-------------------
+
+:Architectures: all
+:Versions: >= 1
+:Parameters: none
+:Returns:
+
+::
+
+ struct kvmi_error_code;
+ struct kvmi_get_version_reply {
+ __u32 version;
+ __u32 padding;
+ };
+
+Returns the introspection API version.
+
+This command is always allowed and successful (if the introspection is
+built in kernel).
@@ -78,4 +78,9 @@ struct kvmi_error_code {
__u32 padding;
};
+struct kvmi_get_version_reply {
+ __u32 version;
+ __u32 padding;
+};
+
#endif /* _UAPI__LINUX_KVMI_H */
@@ -68,6 +68,8 @@ static bool alloc_kvmi(struct kvm *kvm, const struct kvm_introspection *qemu)
if (!ikvm)
return false;
+ set_bit(KVMI_GET_VERSION, ikvm->cmd_allow_mask);
+
memcpy(&ikvm->uuid, &qemu->uuid, sizeof(ikvm->uuid));
ikvm->kvm = kvm;
@@ -290,6 +292,18 @@ int kvmi_ioctl_command(struct kvm *kvm, void __user *argp)
bitmap_from_u64(known, KVMI_KNOWN_COMMANDS);
bitmap_and(requested, requested, known, KVMI_NUM_COMMANDS);
+ if (!allow) {
+ DECLARE_BITMAP(always_allowed, KVMI_NUM_COMMANDS);
+
+ if (id == KVMI_GET_VERSION)
+ return -EPERM;
+
+ set_bit(KVMI_GET_VERSION, always_allowed);
+
+ bitmap_andnot(requested, requested, always_allowed,
+ KVMI_NUM_COMMANDS);
+ }
+
return kvmi_ioctl_feature(kvm, allow, requested,
offsetof(struct kvmi, cmd_allow_mask),
KVMI_NUM_COMMANDS);
@@ -9,6 +9,7 @@
#include "kvmi_int.h"
static const char *const msg_IDs[] = {
+ [KVMI_GET_VERSION] = "KVMI_GET_VERSION",
};
static bool is_known_message(u16 id)
@@ -129,6 +130,17 @@ static int kvmi_msg_vm_reply(struct kvmi *ikvm,
return kvmi_msg_reply(ikvm, msg, err, rpl, rpl_size);
}
+static int handle_get_version(struct kvmi *ikvm,
+ const struct kvmi_msg_hdr *msg, const void *req)
+{
+ struct kvmi_get_version_reply rpl;
+
+ memset(&rpl, 0, sizeof(rpl));
+ rpl.version = KVMI_VERSION;
+
+ return kvmi_msg_vm_reply(ikvm, msg, 0, &rpl, sizeof(rpl));
+}
+
static bool is_command_allowed(struct kvmi *ikvm, int id)
{
return test_bit(id, ikvm->cmd_allow_mask);
@@ -139,6 +151,7 @@ static bool is_command_allowed(struct kvmi *ikvm, int id)
*/
static int(*const msg_vm[])(struct kvmi *, const struct kvmi_msg_hdr *,
const void *) = {
+ [KVMI_GET_VERSION] = handle_get_version,
};
static bool is_vm_message(u16 id)
This command should be used by the introspection tool to identify the commands/events supported by the KVMi subsystem and, most important, what messages must be used for event replies. The kernel side will accept smaller or bigger command messages, but it can be more strict with bigger event reply messages. The command is always allowed and any attempt from userspace to disallow it through KVM_INTROSPECTION_COMMAND will get -EPERM (unless userspace choose to disable all commands, using id=-1, in which case KVMI_GET_VERSION is quietly allowed, without an error). Signed-off-by: Adalbert Lazăr <alazar@bitdefender.com> --- Documentation/virtual/kvm/kvmi.rst | 28 ++++++++++++++++++++++++++++ include/uapi/linux/kvmi.h | 5 +++++ virt/kvm/kvmi.c | 14 ++++++++++++++ virt/kvm/kvmi_msg.c | 13 +++++++++++++ 4 files changed, 60 insertions(+)