|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v1 1/4] xen: add hypercall for getting parameters at runtime
>>> On 06.03.19 at 13:58, <vliaskovitis@xxxxxxxx> wrote:
> +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;
Why is val a pointer to const char? There are several casts below
because of this, and all these casts should go away.
> + 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++;
For a user exposed interface I think it would be better to at least
use isspace() here.
> + 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 */
Even if you copy existing code, please correct obvious style
violations in the new instance - here there are blanks missing
around binary operators.
> + *q++ = *p;
> + p++;
> + }
> + *q = '\0';
> +
> + /* Boolean parameters can be inverted with 'no-' prefix. */
This is an inapplicable comment in this function.
> + found = false;
I don't think you need this variable here, or if so, it shouldn't
be boolean: Either you mean to support returning data for
multiple matching options (there are no runtime ones at
present, but we at least used to have multiple-instance
boot time ones), in which case you may need to invent a
means to disambiguate them. Or you don't, in which case
you could bail from the loop once you've found a match.
> + 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 ",
Here and below, sizeof(values) is wrong in two ways: For one
it's sizeof(char*), not sizeof(char[nn]). And then you need to
subtract the amount of space consumed already.
> + (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);
This is going to fail to build on 32-bit Arm. I'm also
unconvinced this is appropriate if the value is actually
a signed quantity.
> + val += len;
> + break;
> + case OPT_BOOL:
> + get_integer_param(param, ¶m_int);
> + len = snprintf((char*)val, sizeof(values), "%s",
Above you add trailing blanks - why not here?
> + param_int ? "true" : "false");
> + val += len;
> + break;
> + case OPT_SIZE:
> + case OPT_CUSTOM:
> + rc = -EINVAL;
> + break;
I can see why custom parameters can't be dealt with yet,
but why also size ones? As to custom ones - four out of the
seven runtime parameters we currently have are custom
ones, so this limits the utility of the change quite a bit.
> + default:
> + BUG();
> + break;
> + }
> + }
> +
> + if ( !found )
> + {
> + printk("get-parameters: parameter \"%s\" unknown!\n", optkey);
I don't think logging of a message is appropriate here.
> + rc = -EINVAL;
> + }
> + }
> + *val = '\0';
Blank line above this one please. But does this even build, with val
being pointer to const char?
> @@ -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);
> +}
I don't see the need for this wrapper.
> --- 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
May I suggest to re-use XEN_SET_PARAMETER_MAX_SIZE,
perhaps after renaming to XEN_PARAMETER_MAX_SIZE?
> + 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;
> + }
What if params is non-NULL, but values is NULL? Also here and in one
instance below you leak memory on the error paths.
> + 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;
Even if this is a sysctl, please use array_access_nospec() here.
> + ret = runtime_get(params, values);
> +
> + if ( copy_to_guest(op->u.get_parameter.values, values,
> + strlen(values)) )
You should only copy when ret is zero.
Jan
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |