From f8402a98b4fe345d403bd35166c33e8c6fda63b7 Mon Sep 17 00:00:00 2001 From: Juergen Gross Date: Fri, 20 Mar 2026 16:01:10 +0100 Subject: [PATCH] tools/xenstored: add helper to parse domid Today a domid passed in by a command is parsed using atoi(). This will still "succeed" even with a domid like "x", resulting in "0" to be used instead. Use a common domid parser instead rejecting everything but integers in the range 0..65535 like specified in docs/misc/xenstore.txt. Signed-off-by: Juergen Gross Reviewed-by: Anthony PERARD --- tools/xenstored/domain.c | 47 +++++++++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/tools/xenstored/domain.c b/tools/xenstored/domain.c index e453b3061f..a70acddf94 100644 --- a/tools/xenstored/domain.c +++ b/tools/xenstored/domain.c @@ -732,6 +732,18 @@ static char *talloc_domain_path(const void *context, unsigned int domid) return talloc_asprintf(context, "/local/domain/%u", domid); } +/* Parse a domid. Sets errno either to 0 or EINVAL. */ +static unsigned int parse_domid(const char *input) +{ + unsigned long domid; + char *endptr; + + domid = strtoul(input, &endptr, 10); + errno = (*endptr != 0 || domid > 65535) ? EINVAL : 0; + + return domid; +} + int domain_get_quota(const void *ctx, struct connection *conn, unsigned int domid) { @@ -1077,7 +1089,10 @@ int do_introduce(const void *ctx, struct connection *conn, if (get_strings(in, vec, ARRAY_SIZE(vec)) < ARRAY_SIZE(vec)) return EINVAL; - domid = atoi(vec[0]); + domid = parse_domid(vec[0]); + if (errno) + return errno; + /* Ignore the gfn, we don't need it. */ port = atoi(vec[2]); @@ -1124,8 +1139,12 @@ int do_set_target(const void *ctx, struct connection *conn, if (get_strings(in, vec, ARRAY_SIZE(vec)) < ARRAY_SIZE(vec)) return EINVAL; - domid = atoi(vec[0]); - tdomid = atoi(vec[1]); + domid = parse_domid(vec[0]); + if (errno) + return errno; + tdomid = parse_domid(vec[1]); + if (errno) + return errno; domain = find_connected_domain(domid); if (IS_ERR(domain)) @@ -1152,7 +1171,9 @@ static struct domain *onearg_domain(struct connection *conn, if (!domid_str) return ERR_PTR(-EINVAL); - domid = atoi(domid_str); + domid = parse_domid(domid_str); + if (errno) + return ERR_PTR(-errno); if (domid == store_domid || domid == priv_domid) return ERR_PTR(-EINVAL); @@ -1200,11 +1221,15 @@ int do_get_domain_path(const void *ctx, struct connection *conn, { char *path; const char *domid_str = onearg(in); + unsigned int domid; if (!domid_str) return EINVAL; - path = talloc_domain_path(ctx, atoi(domid_str)); + domid = parse_domid(domid_str); + if (errno) + return errno; + path = talloc_domain_path(ctx, domid); if (!path) return errno; @@ -1223,7 +1248,9 @@ int do_is_domain_introduced(const void *ctx, struct connection *conn, if (!domid_str) return EINVAL; - domid = atoi(domid_str); + domid = parse_domid(domid_str); + if (errno) + return errno; if (domid == DOMID_SELF) result = 1; else @@ -1261,7 +1288,9 @@ int do_get_feature(const void *ctx, struct connection *conn, return EINVAL; if (n_args == 1) { - domid = atoi(vec[0]); + domid = parse_domid(vec[0]); + if (errno) + return errno; domain = find_or_alloc_existing_domain(domid); if (!domain) return ENOENT; @@ -1289,7 +1318,9 @@ int do_set_feature(const void *ctx, struct connection *conn, if (get_strings(in, vec, ARRAY_SIZE(vec)) != ARRAY_SIZE(vec)) return EINVAL; - domid = atoi(vec[0]); + domid = parse_domid(vec[0]); + if (errno) + return errno; features = atoi(vec[1]); domain = find_or_alloc_existing_domain(domid); if (!domain)