CHECK_build_id;
CHECK_compile_info;
CHECK_feature_info;
+CHECK_varbuf;
#endif
enum system_state system_state = SYS_STATE_early_boot;
__initcall(param_init);
#endif
+static long xenver_varbuf_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
+{
+ struct xen_varbuf user_str;
+ const char *str = NULL;
+ size_t sz;
+
+ switch ( cmd )
+ {
+ case XENVER_extraversion2:
+ str = xen_extra_version();
+ break;
+
+ case XENVER_changeset2:
+ str = xen_changeset();
+ break;
+
+ case XENVER_commandline2:
+ str = saved_cmdline;
+ break;
+
+ case XENVER_capabilities2:
+ str = xen_cap_info;
+ break;
+
+ default:
+ ASSERT_UNREACHABLE();
+ return -ENODATA;
+ }
+
+ sz = strlen(str);
+
+ if ( sz > KB(64) ) /* Arbitrary limit. Avoid long-running operations. */
+ return -E2BIG;
+
+ if ( guest_handle_is_null(arg) ) /* Length request */
+ return sz;
+
+ if ( copy_from_guest(&user_str, arg, 1) )
+ return -EFAULT;
+
+ if ( sz > user_str.len )
+ return -ENOBUFS;
+
+ if ( copy_to_guest_offset(arg, offsetof(struct xen_varbuf, buf),
+ str, sz) )
+ return -EFAULT;
+
+ return sz;
+}
+
long do_xen_version(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
{
bool deny = xsm_xen_version(XSM_OTHER, cmd);
return sz;
}
+
+ case XENVER_extraversion2:
+ case XENVER_capabilities2:
+ case XENVER_changeset2:
+ case XENVER_commandline2:
+ if ( deny )
+ return -EPERM;
+ return xenver_varbuf_op(cmd, arg);
}
return -ENOSYS;
/* arg == NULL; returns major:minor (16:16). */
#define XENVER_version 0
-/* arg == xen_extraversion_t. */
+/*
+ * arg == xen_extraversion_t.
+ *
+ * This API/ABI is broken. Use XENVER_extraversion2 where possible.
+ */
#define XENVER_extraversion 1
typedef char xen_extraversion_t[16];
#define XEN_EXTRAVERSION_LEN (sizeof(xen_extraversion_t))
-/* arg == xen_compile_info_t. */
+/*
+ * arg == xen_compile_info_t.
+ *
+ * This API/ABI is broken and truncates data.
+ */
#define XENVER_compile_info 2
struct xen_compile_info {
char compiler[64];
};
typedef struct xen_compile_info xen_compile_info_t;
+/*
+ * arg == xen_capabilities_info_t.
+ *
+ * This API/ABI is broken. Use XENVER_capabilities2 where possible.
+ */
#define XENVER_capabilities 3
typedef char xen_capabilities_info_t[1024];
#define XEN_CAPABILITIES_INFO_LEN (sizeof(xen_capabilities_info_t))
+/*
+ * arg == xen_changeset_info_t.
+ *
+ * This API/ABI is broken. Use XENVER_changeset2 where possible.
+ */
#define XENVER_changeset 4
typedef char xen_changeset_info_t[64];
#define XEN_CHANGESET_INFO_LEN (sizeof(xen_changeset_info_t))
*/
#define XENVER_guest_handle 8
+/*
+ * arg == xen_commandline_t.
+ *
+ * This API/ABI is broken. Use XENVER_commandline2 where possible.
+ */
#define XENVER_commandline 9
typedef char xen_commandline_t[1024];
};
typedef struct xen_build_id xen_build_id_t;
+/*
+ * Container for an arbitrary variable length buffer.
+ */
+struct xen_varbuf {
+ uint32_t len; /* IN: size of buf[] in bytes. */
+ unsigned char buf[XEN_FLEX_ARRAY_DIM]; /* OUT: requested data. */
+};
+typedef struct xen_varbuf xen_varbuf_t;
+
+/*
+ * arg == xen_varbuf_t
+ *
+ * Equivalent to the original ops, but with a non-truncating API/ABI.
+ *
+ * These hypercalls can fail for a number of reasons. All callers must handle
+ * -XEN_xxx return values appropriately.
+ *
+ * Passing arg == NULL is a request for size, which will be signalled with a
+ * non-negative return value. Note: a return size of 0 may be legitimate for
+ * the requested subop.
+ *
+ * Otherwise, the input xen_varbuf_t provides the size of the following
+ * buffer. Xen will fill the buffer, and return the number of bytes written
+ * (e.g. if the input buffer was longer than necessary).
+ *
+ * Some subops may return binary data. Some subops may be expected to return
+ * textural data. These are returned without a NUL terminator, and while the
+ * contents is expected to be ASCII/UTF-8, Xen makes no guarentees to this
+ * effect. e.g. Xen has no control over the formatting used for the command
+ * line.
+ */
+#define XENVER_extraversion2 11
+#define XENVER_capabilities2 12
+#define XENVER_changeset2 13
+#define XENVER_commandline2 14
+
#endif /* __XEN_PUBLIC_VERSION_H__ */
/*
? build_id version.h
? compile_info version.h
? feature_info version.h
+? varbuf version.h
? xenoprof_init xenoprof.h
? xenoprof_passive xenoprof.h
block_speculation();
return 0;
case XENVER_extraversion:
+ case XENVER_extraversion2:
case XENVER_compile_info:
case XENVER_capabilities:
+ case XENVER_capabilities2:
case XENVER_changeset:
+ case XENVER_changeset2:
case XENVER_pagesize:
case XENVER_guest_handle:
/* These MUST always be accessible to any guest by default. */
/* These sub-ops ignore the permission checks and return data. */
return 0;
case XENVER_extraversion:
+ case XENVER_extraversion2:
return avc_has_perm(dsid, SECINITSID_XEN, SECCLASS_VERSION,
VERSION__XEN_EXTRAVERSION, NULL);
case XENVER_compile_info:
return avc_has_perm(dsid, SECINITSID_XEN, SECCLASS_VERSION,
VERSION__XEN_COMPILE_INFO, NULL);
case XENVER_capabilities:
+ case XENVER_capabilities2:
return avc_has_perm(dsid, SECINITSID_XEN, SECCLASS_VERSION,
VERSION__XEN_CAPABILITIES, NULL);
case XENVER_changeset:
+ case XENVER_changeset2:
return avc_has_perm(dsid, SECINITSID_XEN, SECCLASS_VERSION,
VERSION__XEN_CHANGESET, NULL);
case XENVER_pagesize:
return avc_has_perm(dsid, SECINITSID_XEN, SECCLASS_VERSION,
VERSION__XEN_GUEST_HANDLE, NULL);
case XENVER_commandline:
+ case XENVER_commandline2:
return avc_has_perm(dsid, SECINITSID_XEN, SECCLASS_VERSION,
VERSION__XEN_COMMANDLINE, NULL);
case XENVER_build_id: