[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v1 1/4] xen: add hypercall for getting parameters at runtime
Add a sysctl hypercall to support getting hypervisor parameters at runtime. Signed-off-by: Vasilis Liaskovitis <vliaskovitis@xxxxxxxx> --- tools/flask/policy/modules/dom0.te | 2 +- xen/common/kernel.c | 109 ++++++++++++++++++++++++++++ xen/common/sysctl.c | 45 ++++++++++++ xen/include/public/sysctl.h | 18 +++++ xen/include/xen/lib.h | 1 + xen/xsm/flask/hooks.c | 3 + xen/xsm/flask/policy/access_vectors | 2 + 7 files changed, 179 insertions(+), 1 deletion(-) diff --git a/tools/flask/policy/modules/dom0.te b/tools/flask/policy/modules/dom0.te index a347d664f8..681d1a101b 100644 --- a/tools/flask/policy/modules/dom0.te +++ b/tools/flask/policy/modules/dom0.te @@ -16,7 +16,7 @@ allow dom0_t xen_t:xen { allow dom0_t xen_t:xen2 { resource_op psr_cmt_op psr_alloc pmu_ctrl get_symbol get_cpu_levelling_caps get_cpu_featureset livepatch_op - coverage_op set_parameter + coverage_op set_parameter get_parameter }; # Allow dom0 to use all XENVER_ subops that have checks. diff --git a/xen/common/kernel.c b/xen/common/kernel.c index 612575430f..83225afd93 100644 --- a/xen/common/kernel.c +++ b/xen/common/kernel.c @@ -52,6 +52,110 @@ static int assign_integer_param(const struct kernel_param *param, uint64_t val) return 0; } +static int get_integer_param(const struct kernel_param *param, uint64_t *val) +{ + switch ( param->len ) + { + case sizeof(uint8_t): + *val = *(uint8_t *)param->par.var; + break; + case sizeof(uint16_t): + *val = *(uint16_t *)param->par.var; + break; + case sizeof(uint32_t): + *val = *(uint32_t *)param->par.var; + break; + case sizeof(uint64_t): + *val = *(uint64_t *)param->par.var; + break; + default: + BUG(); + } + + return 0; +} + +static int get_params(const char *cmdline, char *values, + const struct kernel_param *start, + const struct kernel_param *end) +{ + char opt[128], *optkey, *q; + const char *p = cmdline, *val = values; + const struct kernel_param *param; + int len, rc = 0; + uint64_t param_int; + bool found; + + if (!values) + return -EFAULT; + + for ( ; ; ) + { + /* Skip whitespace. */ + while ( *p == ' ' ) + p++; + if ( *p == '\0' ) + break; + + /* Grab the next whitespace-delimited option. */ + q = optkey = opt; + while ( (*p != ' ') && (*p != '\0') ) + { + if ( (q-opt) < (sizeof(opt)-1) ) /* avoid overflow */ + *q++ = *p; + p++; + } + *q = '\0'; + + /* Boolean parameters can be inverted with 'no-' prefix. */ + + found = false; + for ( param = start; param < end; param++ ) + { + + if ( strcmp(param->name, optkey) ) + continue; + + found = true; + switch ( param->type ) + { + case OPT_STR: + len = snprintf((char*)val, sizeof(values), "%s ", + (char*)param->par.var); + val += len; + break; + case OPT_UINT: + get_integer_param(param, ¶m_int); + len = snprintf((char*)val, sizeof(values), "%lu ", param_int); + val += len; + break; + case OPT_BOOL: + get_integer_param(param, ¶m_int); + len = snprintf((char*)val, sizeof(values), "%s", + param_int ? "true" : "false"); + val += len; + break; + case OPT_SIZE: + case OPT_CUSTOM: + rc = -EINVAL; + break; + default: + BUG(); + break; + } + } + + if ( !found ) + { + printk("get-parameters: parameter \"%s\" unknown!\n", optkey); + rc = -EINVAL; + } + } + *val = '\0'; + + return rc; +} + static int parse_params(const char *cmdline, const struct kernel_param *start, const struct kernel_param *end) { @@ -199,6 +303,11 @@ int runtime_parse(const char *line) return parse_params(line, __param_start, __param_end); } +int runtime_get_parameter(const char *line, char *values) +{ + return get_params(line, values, __param_start, __param_end); +} + /** * cmdline_parse -- parses the xen command line. * If CONFIG_CMDLINE is set, it would be parsed prior to @cmdline. diff --git a/xen/common/sysctl.c b/xen/common/sysctl.c index c0aa6bde4e..d8597de9cd 100644 --- a/xen/common/sysctl.c +++ b/xen/common/sysctl.c @@ -501,6 +501,51 @@ long do_sysctl(XEN_GUEST_HANDLE_PARAM(xen_sysctl_t) u_sysctl) break; } + case XEN_SYSCTL_get_parameter: + { +#define XEN_GET_PARAMETER_MAX_SIZE 1023 + char *params; + char *values; + + if ( op->u.get_parameter.pad[0] || op->u.get_parameter.pad[1] || + op->u.get_parameter.pad[2] ) + { + ret = -EINVAL; + break; + } + if ( op->u.get_parameter.size > XEN_GET_PARAMETER_MAX_SIZE ) + { + ret = -E2BIG; + break; + } + params = xmalloc_bytes(op->u.get_parameter.size + 1); + values = xmalloc_bytes(XEN_GET_PARAMETER_MAX_SIZE); + if ( !params ) + { + ret = -ENOMEM; + break; + } + if ( copy_from_guest(params, op->u.get_parameter.params, + op->u.get_parameter.size) ) + ret = -EFAULT; + else + { + params[op->u.get_parameter.size] = 0; + ret = runtime_get(params, values); + + if ( copy_to_guest(op->u.get_parameter.values, values, + strlen(values)) ) + { + ret = -EFAULT; + break; + } + } + + xfree(params); + xfree(values); + + break; + } default: ret = arch_do_sysctl(op, u_sysctl); diff --git a/xen/include/public/sysctl.h b/xen/include/public/sysctl.h index c49b4dcc99..7d77d57115 100644 --- a/xen/include/public/sysctl.h +++ b/xen/include/public/sysctl.h @@ -1100,6 +1100,22 @@ typedef struct xen_sysctl_cpu_policy xen_sysctl_cpu_policy_t; DEFINE_XEN_GUEST_HANDLE(xen_sysctl_cpu_policy_t); #endif +/* + * XEN_SYSCTL_get_parameter + * + * Read hypervisor parameters at runtime. + * Parameters are a single string terminated by a NUL byte of max. size + * characters. Multiple settings can be specified by separating them + * with blanks. + */ + +struct xen_sysctl_get_parameter { + XEN_GUEST_HANDLE_64(char) params; /* IN: pointer to parameters. */ + XEN_GUEST_HANDLE_64(char) values; /* OUT: pointer to output values. */ + uint16_t size; /* IN: size of parameters. */ + uint16_t pad[3]; /* IN: MUST be zero. */ +}; + struct xen_sysctl { uint32_t cmd; #define XEN_SYSCTL_readconsole 1 @@ -1130,6 +1146,7 @@ struct xen_sysctl { #define XEN_SYSCTL_livepatch_op 27 #define XEN_SYSCTL_set_parameter 28 #define XEN_SYSCTL_get_cpu_policy 29 +#define XEN_SYSCTL_get_parameter 30 uint32_t interface_version; /* XEN_SYSCTL_INTERFACE_VERSION */ union { struct xen_sysctl_readconsole readconsole; @@ -1162,6 +1179,7 @@ struct xen_sysctl { #if defined(__i386__) || defined(__x86_64__) struct xen_sysctl_cpu_policy cpu_policy; #endif + struct xen_sysctl_get_parameter get_parameter; uint8_t pad[128]; } u; }; diff --git a/xen/include/xen/lib.h b/xen/include/xen/lib.h index 89939f43c8..3d5896c0b7 100644 --- a/xen/include/xen/lib.h +++ b/xen/include/xen/lib.h @@ -71,6 +71,7 @@ struct domain; void cmdline_parse(const char *cmdline); int runtime_parse(const char *line); int parse_bool(const char *s, const char *e); +int runtime_get_parameter(const char *line, char *values); /** * Given a specific name, parses a string of the form: diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c index 3d00c747f6..1b832e9a4c 100644 --- a/xen/xsm/flask/hooks.c +++ b/xen/xsm/flask/hooks.c @@ -830,6 +830,9 @@ static int flask_sysctl(int cmd) case XEN_SYSCTL_set_parameter: return avc_current_has_perm(SECINITSID_XEN, SECCLASS_XEN2, XEN2__SET_PARAMETER, NULL); + case XEN_SYSCTL_get_parameter: + return avc_current_has_perm(SECINITSID_XEN, SECCLASS_XEN2, + XEN2__GET_PARAMETER, NULL); default: return avc_unknown_permission("sysctl", cmd); diff --git a/xen/xsm/flask/policy/access_vectors b/xen/xsm/flask/policy/access_vectors index e00448b776..c5ee21d852 100644 --- a/xen/xsm/flask/policy/access_vectors +++ b/xen/xsm/flask/policy/access_vectors @@ -103,6 +103,8 @@ class xen2 coverage_op # XEN_SYSCTL_set_parameter set_parameter +# XEN_SYSCTL_get_parameter + get_parameter } # Classes domain and domain2 consist of operations that a domain performs on -- 2.20.1 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |