summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Schmaus <flow@gentoo.org>2022-11-09 09:53:02 +0100
committerFlorian Schmaus <flow@gentoo.org>2022-11-09 09:53:02 +0100
commitfac86a27853d2f21c62fefcba9cca32e3b9bdcdc (patch)
tree57acbe9aadcfdb2594eec2e21f1bab81bd104235 /0070-tools-xenstore-don-t-use-conn-in-as-context-for-temp.patch
parentXen 4.16.3-pre-patchset-0 (diff)
downloadxen-upstream-patches-fac86a27853d2f21c62fefcba9cca32e3b9bdcdc.tar.gz
xen-upstream-patches-fac86a27853d2f21c62fefcba9cca32e3b9bdcdc.tar.bz2
xen-upstream-patches-fac86a27853d2f21c62fefcba9cca32e3b9bdcdc.zip
Xen 4.16.3-pre-patchset-14.16.3-pre-patchset-1
Signed-off-by: Florian Schmaus <flow@gentoo.org>
Diffstat (limited to '0070-tools-xenstore-don-t-use-conn-in-as-context-for-temp.patch')
-rw-r--r--0070-tools-xenstore-don-t-use-conn-in-as-context-for-temp.patch718
1 files changed, 718 insertions, 0 deletions
diff --git a/0070-tools-xenstore-don-t-use-conn-in-as-context-for-temp.patch b/0070-tools-xenstore-don-t-use-conn-in-as-context-for-temp.patch
new file mode 100644
index 0000000..434ad0c
--- /dev/null
+++ b/0070-tools-xenstore-don-t-use-conn-in-as-context-for-temp.patch
@@ -0,0 +1,718 @@
+From c758765e464e166b5495c76466facc79584bbe1e Mon Sep 17 00:00:00 2001
+From: Juergen Gross <jgross@suse.com>
+Date: Tue, 13 Sep 2022 07:35:10 +0200
+Subject: [PATCH 70/87] tools/xenstore: don't use conn->in as context for
+ temporary allocations
+
+Using the struct buffered data pointer of the current processed request
+for temporary data allocations has a major drawback: the used area (and
+with that the temporary data) is freed only after the response of the
+request has been written to the ring page or has been read via the
+socket. This can happen much later in case a guest isn't reading its
+responses fast enough.
+
+As the temporary data can be safely freed after creating the response,
+add a temporary context for that purpose and use that for allocating
+the temporary memory, as it was already the case before commit
+cc0612464896 ("xenstore: add small default data buffer to internal
+struct").
+
+Some sub-functions need to gain the "const" attribute for the talloc
+context.
+
+This is XSA-416 / CVE-2022-42319.
+
+Fixes: cc0612464896 ("xenstore: add small default data buffer to internal struct")
+Signed-off-by: Juergen Gross <jgross@suse.com>
+Reviewed-by: Julien Grall <jgrall@amazon.com>
+(cherry picked from commit 2a587de219cc0765330fbf9fac6827bfaf29e29b)
+---
+ tools/xenstore/xenstored_control.c | 31 ++++++-----
+ tools/xenstore/xenstored_control.h | 3 +-
+ tools/xenstore/xenstored_core.c | 76 ++++++++++++++++----------
+ tools/xenstore/xenstored_domain.c | 29 ++++++----
+ tools/xenstore/xenstored_domain.h | 21 ++++---
+ tools/xenstore/xenstored_transaction.c | 14 +++--
+ tools/xenstore/xenstored_transaction.h | 6 +-
+ tools/xenstore/xenstored_watch.c | 9 +--
+ tools/xenstore/xenstored_watch.h | 6 +-
+ 9 files changed, 118 insertions(+), 77 deletions(-)
+
+diff --git a/tools/xenstore/xenstored_control.c b/tools/xenstore/xenstored_control.c
+index 1031a81c3874..d0350c6ad861 100644
+--- a/tools/xenstore/xenstored_control.c
++++ b/tools/xenstore/xenstored_control.c
+@@ -155,7 +155,7 @@ bool lu_is_pending(void)
+
+ struct cmd_s {
+ char *cmd;
+- int (*func)(void *, struct connection *, char **, int);
++ int (*func)(const void *, struct connection *, char **, int);
+ char *pars;
+ /*
+ * max_pars can be used to limit the size of the parameter vector,
+@@ -167,7 +167,7 @@ struct cmd_s {
+ unsigned int max_pars;
+ };
+
+-static int do_control_check(void *ctx, struct connection *conn,
++static int do_control_check(const void *ctx, struct connection *conn,
+ char **vec, int num)
+ {
+ if (num)
+@@ -179,7 +179,7 @@ static int do_control_check(void *ctx, struct connection *conn,
+ return 0;
+ }
+
+-static int do_control_log(void *ctx, struct connection *conn,
++static int do_control_log(const void *ctx, struct connection *conn,
+ char **vec, int num)
+ {
+ if (num != 1)
+@@ -281,7 +281,7 @@ static int quota_get(const void *ctx, struct connection *conn,
+ return domain_get_quota(ctx, conn, atoi(vec[0]));
+ }
+
+-static int do_control_quota(void *ctx, struct connection *conn,
++static int do_control_quota(const void *ctx, struct connection *conn,
+ char **vec, int num)
+ {
+ if (num == 0)
+@@ -293,7 +293,7 @@ static int do_control_quota(void *ctx, struct connection *conn,
+ return quota_get(ctx, conn, vec, num);
+ }
+
+-static int do_control_quota_s(void *ctx, struct connection *conn,
++static int do_control_quota_s(const void *ctx, struct connection *conn,
+ char **vec, int num)
+ {
+ if (num == 0)
+@@ -306,7 +306,7 @@ static int do_control_quota_s(void *ctx, struct connection *conn,
+ }
+
+ #ifdef __MINIOS__
+-static int do_control_memreport(void *ctx, struct connection *conn,
++static int do_control_memreport(const void *ctx, struct connection *conn,
+ char **vec, int num)
+ {
+ if (num)
+@@ -318,7 +318,7 @@ static int do_control_memreport(void *ctx, struct connection *conn,
+ return 0;
+ }
+ #else
+-static int do_control_logfile(void *ctx, struct connection *conn,
++static int do_control_logfile(const void *ctx, struct connection *conn,
+ char **vec, int num)
+ {
+ if (num != 1)
+@@ -333,7 +333,7 @@ static int do_control_logfile(void *ctx, struct connection *conn,
+ return 0;
+ }
+
+-static int do_control_memreport(void *ctx, struct connection *conn,
++static int do_control_memreport(const void *ctx, struct connection *conn,
+ char **vec, int num)
+ {
+ FILE *fp;
+@@ -373,7 +373,7 @@ static int do_control_memreport(void *ctx, struct connection *conn,
+ }
+ #endif
+
+-static int do_control_print(void *ctx, struct connection *conn,
++static int do_control_print(const void *ctx, struct connection *conn,
+ char **vec, int num)
+ {
+ if (num != 1)
+@@ -875,7 +875,7 @@ static const char *lu_start(const void *ctx, struct connection *conn,
+ return NULL;
+ }
+
+-static int do_control_lu(void *ctx, struct connection *conn,
++static int do_control_lu(const void *ctx, struct connection *conn,
+ char **vec, int num)
+ {
+ const char *ret = NULL;
+@@ -922,7 +922,7 @@ static int do_control_lu(void *ctx, struct connection *conn,
+ }
+ #endif
+
+-static int do_control_help(void *, struct connection *, char **, int);
++static int do_control_help(const void *, struct connection *, char **, int);
+
+ static struct cmd_s cmds[] = {
+ { "check", do_control_check, "" },
+@@ -961,7 +961,7 @@ static struct cmd_s cmds[] = {
+ { "help", do_control_help, "" },
+ };
+
+-static int do_control_help(void *ctx, struct connection *conn,
++static int do_control_help(const void *ctx, struct connection *conn,
+ char **vec, int num)
+ {
+ int cmd, len = 0;
+@@ -997,7 +997,8 @@ static int do_control_help(void *ctx, struct connection *conn,
+ return 0;
+ }
+
+-int do_control(struct connection *conn, struct buffered_data *in)
++int do_control(const void *ctx, struct connection *conn,
++ struct buffered_data *in)
+ {
+ unsigned int cmd, num, off;
+ char **vec = NULL;
+@@ -1017,11 +1018,11 @@ int do_control(struct connection *conn, struct buffered_data *in)
+ num = xs_count_strings(in->buffer, in->used);
+ if (cmds[cmd].max_pars)
+ num = min(num, cmds[cmd].max_pars);
+- vec = talloc_array(in, char *, num);
++ vec = talloc_array(ctx, char *, num);
+ if (!vec)
+ return ENOMEM;
+ if (get_strings(in, vec, num) < num)
+ return EIO;
+
+- return cmds[cmd].func(in, conn, vec + 1, num - 1);
++ return cmds[cmd].func(ctx, conn, vec + 1, num - 1);
+ }
+diff --git a/tools/xenstore/xenstored_control.h b/tools/xenstore/xenstored_control.h
+index 98b6fbcea2b1..a8cb76559ba1 100644
+--- a/tools/xenstore/xenstored_control.h
++++ b/tools/xenstore/xenstored_control.h
+@@ -16,7 +16,8 @@
+ along with this program; If not, see <http://www.gnu.org/licenses/>.
+ */
+
+-int do_control(struct connection *conn, struct buffered_data *in);
++int do_control(const void *ctx, struct connection *conn,
++ struct buffered_data *in);
+ void lu_read_state(void);
+
+ struct connection *lu_get_connection(void);
+diff --git a/tools/xenstore/xenstored_core.c b/tools/xenstore/xenstored_core.c
+index 16504de42017..411cc0e44714 100644
+--- a/tools/xenstore/xenstored_core.c
++++ b/tools/xenstore/xenstored_core.c
+@@ -1248,11 +1248,13 @@ static struct node *get_node_canonicalized(struct connection *conn,
+ return get_node(conn, ctx, *canonical_name, perm);
+ }
+
+-static int send_directory(struct connection *conn, struct buffered_data *in)
++static int send_directory(const void *ctx, struct connection *conn,
++ struct buffered_data *in)
+ {
+ struct node *node;
+
+- node = get_node_canonicalized(conn, in, onearg(in), NULL, XS_PERM_READ);
++ node = get_node_canonicalized(conn, ctx, onearg(in), NULL,
++ XS_PERM_READ);
+ if (!node)
+ return errno;
+
+@@ -1261,7 +1263,7 @@ static int send_directory(struct connection *conn, struct buffered_data *in)
+ return 0;
+ }
+
+-static int send_directory_part(struct connection *conn,
++static int send_directory_part(const void *ctx, struct connection *conn,
+ struct buffered_data *in)
+ {
+ unsigned int off, len, maxlen, genlen;
+@@ -1273,7 +1275,8 @@ static int send_directory_part(struct connection *conn,
+ return EINVAL;
+
+ /* First arg is node name. */
+- node = get_node_canonicalized(conn, in, in->buffer, NULL, XS_PERM_READ);
++ node = get_node_canonicalized(conn, ctx, in->buffer, NULL,
++ XS_PERM_READ);
+ if (!node)
+ return errno;
+
+@@ -1300,7 +1303,7 @@ static int send_directory_part(struct connection *conn,
+ break;
+ }
+
+- data = talloc_array(in, char, genlen + len + 1);
++ data = talloc_array(ctx, char, genlen + len + 1);
+ if (!data)
+ return ENOMEM;
+
+@@ -1316,11 +1319,13 @@ static int send_directory_part(struct connection *conn,
+ return 0;
+ }
+
+-static int do_read(struct connection *conn, struct buffered_data *in)
++static int do_read(const void *ctx, struct connection *conn,
++ struct buffered_data *in)
+ {
+ struct node *node;
+
+- node = get_node_canonicalized(conn, in, onearg(in), NULL, XS_PERM_READ);
++ node = get_node_canonicalized(conn, ctx, onearg(in), NULL,
++ XS_PERM_READ);
+ if (!node)
+ return errno;
+
+@@ -1510,7 +1515,8 @@ err:
+ }
+
+ /* path, data... */
+-static int do_write(struct connection *conn, struct buffered_data *in)
++static int do_write(const void *ctx, struct connection *conn,
++ struct buffered_data *in)
+ {
+ unsigned int offset, datalen;
+ struct node *node;
+@@ -1524,12 +1530,12 @@ static int do_write(struct connection *conn, struct buffered_data *in)
+ offset = strlen(vec[0]) + 1;
+ datalen = in->used - offset;
+
+- node = get_node_canonicalized(conn, in, vec[0], &name, XS_PERM_WRITE);
++ node = get_node_canonicalized(conn, ctx, vec[0], &name, XS_PERM_WRITE);
+ if (!node) {
+ /* No permissions, invalid input? */
+ if (errno != ENOENT)
+ return errno;
+- node = create_node(conn, in, name, in->buffer + offset,
++ node = create_node(conn, ctx, name, in->buffer + offset,
+ datalen);
+ if (!node)
+ return errno;
+@@ -1540,18 +1546,19 @@ static int do_write(struct connection *conn, struct buffered_data *in)
+ return errno;
+ }
+
+- fire_watches(conn, in, name, node, false, NULL);
++ fire_watches(conn, ctx, name, node, false, NULL);
+ send_ack(conn, XS_WRITE);
+
+ return 0;
+ }
+
+-static int do_mkdir(struct connection *conn, struct buffered_data *in)
++static int do_mkdir(const void *ctx, struct connection *conn,
++ struct buffered_data *in)
+ {
+ struct node *node;
+ char *name;
+
+- node = get_node_canonicalized(conn, in, onearg(in), &name,
++ node = get_node_canonicalized(conn, ctx, onearg(in), &name,
+ XS_PERM_WRITE);
+
+ /* If it already exists, fine. */
+@@ -1561,10 +1568,10 @@ static int do_mkdir(struct connection *conn, struct buffered_data *in)
+ return errno;
+ if (!name)
+ return ENOMEM;
+- node = create_node(conn, in, name, NULL, 0);
++ node = create_node(conn, ctx, name, NULL, 0);
+ if (!node)
+ return errno;
+- fire_watches(conn, in, name, node, false, NULL);
++ fire_watches(conn, ctx, name, node, false, NULL);
+ }
+ send_ack(conn, XS_MKDIR);
+
+@@ -1662,24 +1669,25 @@ static int _rm(struct connection *conn, const void *ctx, struct node *node,
+ }
+
+
+-static int do_rm(struct connection *conn, struct buffered_data *in)
++static int do_rm(const void *ctx, struct connection *conn,
++ struct buffered_data *in)
+ {
+ struct node *node;
+ int ret;
+ char *name;
+ char *parentname;
+
+- node = get_node_canonicalized(conn, in, onearg(in), &name,
++ node = get_node_canonicalized(conn, ctx, onearg(in), &name,
+ XS_PERM_WRITE);
+ if (!node) {
+ /* Didn't exist already? Fine, if parent exists. */
+ if (errno == ENOENT) {
+ if (!name)
+ return ENOMEM;
+- parentname = get_parent(in, name);
++ parentname = get_parent(ctx, name);
+ if (!parentname)
+ return errno;
+- node = read_node(conn, in, parentname);
++ node = read_node(conn, ctx, parentname);
+ if (node) {
+ send_ack(conn, XS_RM);
+ return 0;
+@@ -1694,7 +1702,7 @@ static int do_rm(struct connection *conn, struct buffered_data *in)
+ if (streq(name, "/"))
+ return EINVAL;
+
+- ret = _rm(conn, in, node, name);
++ ret = _rm(conn, ctx, node, name);
+ if (ret)
+ return ret;
+
+@@ -1704,13 +1712,15 @@ static int do_rm(struct connection *conn, struct buffered_data *in)
+ }
+
+
+-static int do_get_perms(struct connection *conn, struct buffered_data *in)
++static int do_get_perms(const void *ctx, struct connection *conn,
++ struct buffered_data *in)
+ {
+ struct node *node;
+ char *strings;
+ unsigned int len;
+
+- node = get_node_canonicalized(conn, in, onearg(in), NULL, XS_PERM_READ);
++ node = get_node_canonicalized(conn, ctx, onearg(in), NULL,
++ XS_PERM_READ);
+ if (!node)
+ return errno;
+
+@@ -1723,7 +1733,8 @@ static int do_get_perms(struct connection *conn, struct buffered_data *in)
+ return 0;
+ }
+
+-static int do_set_perms(struct connection *conn, struct buffered_data *in)
++static int do_set_perms(const void *ctx, struct connection *conn,
++ struct buffered_data *in)
+ {
+ struct node_perms perms, old_perms;
+ char *name, *permstr;
+@@ -1740,7 +1751,7 @@ static int do_set_perms(struct connection *conn, struct buffered_data *in)
+
+ permstr = in->buffer + strlen(in->buffer) + 1;
+
+- perms.p = talloc_array(in, struct xs_permissions, perms.num);
++ perms.p = talloc_array(ctx, struct xs_permissions, perms.num);
+ if (!perms.p)
+ return ENOMEM;
+ if (!xs_strings_to_perms(perms.p, perms.num, permstr))
+@@ -1755,7 +1766,7 @@ static int do_set_perms(struct connection *conn, struct buffered_data *in)
+ }
+
+ /* We must own node to do this (tools can do this too). */
+- node = get_node_canonicalized(conn, in, in->buffer, &name,
++ node = get_node_canonicalized(conn, ctx, in->buffer, &name,
+ XS_PERM_WRITE | XS_PERM_OWNER);
+ if (!node)
+ return errno;
+@@ -1790,7 +1801,7 @@ static int do_set_perms(struct connection *conn, struct buffered_data *in)
+ return errno;
+ }
+
+- fire_watches(conn, in, name, node, false, &old_perms);
++ fire_watches(conn, ctx, name, node, false, &old_perms);
+ send_ack(conn, XS_SET_PERMS);
+
+ return 0;
+@@ -1798,7 +1809,8 @@ static int do_set_perms(struct connection *conn, struct buffered_data *in)
+
+ static struct {
+ const char *str;
+- int (*func)(struct connection *conn, struct buffered_data *in);
++ int (*func)(const void *ctx, struct connection *conn,
++ struct buffered_data *in);
+ unsigned int flags;
+ #define XS_FLAG_NOTID (1U << 0) /* Ignore transaction id. */
+ #define XS_FLAG_PRIV (1U << 1) /* Privileged domain only. */
+@@ -1874,6 +1886,7 @@ static void process_message(struct connection *conn, struct buffered_data *in)
+ struct transaction *trans;
+ enum xsd_sockmsg_type type = in->hdr.msg.type;
+ int ret;
++ void *ctx;
+
+ /* At least send_error() and send_reply() expects conn->in == in */
+ assert(conn->in == in);
+@@ -1898,10 +1911,17 @@ static void process_message(struct connection *conn, struct buffered_data *in)
+ return;
+ }
+
++ ctx = talloc_new(NULL);
++ if (!ctx) {
++ send_error(conn, ENOMEM);
++ return;
++ }
++
+ assert(conn->transaction == NULL);
+ conn->transaction = trans;
+
+- ret = wire_funcs[type].func(conn, in);
++ ret = wire_funcs[type].func(ctx, conn, in);
++ talloc_free(ctx);
+ if (ret)
+ send_error(conn, ret);
+
+diff --git a/tools/xenstore/xenstored_domain.c b/tools/xenstore/xenstored_domain.c
+index e7c6886ccf47..fb732d0a14c3 100644
+--- a/tools/xenstore/xenstored_domain.c
++++ b/tools/xenstore/xenstored_domain.c
+@@ -330,7 +330,7 @@ bool domain_is_unprivileged(struct connection *conn)
+ domid_is_unprivileged(conn->domain->domid);
+ }
+
+-static char *talloc_domain_path(void *context, unsigned int domid)
++static char *talloc_domain_path(const void *context, unsigned int domid)
+ {
+ return talloc_asprintf(context, "/local/domain/%u", domid);
+ }
+@@ -534,7 +534,8 @@ static struct domain *introduce_domain(const void *ctx,
+ }
+
+ /* domid, gfn, evtchn, path */
+-int do_introduce(struct connection *conn, struct buffered_data *in)
++int do_introduce(const void *ctx, struct connection *conn,
++ struct buffered_data *in)
+ {
+ struct domain *domain;
+ char *vec[3];
+@@ -552,7 +553,7 @@ int do_introduce(struct connection *conn, struct buffered_data *in)
+ if (port <= 0)
+ return EINVAL;
+
+- domain = introduce_domain(in, domid, port, false);
++ domain = introduce_domain(ctx, domid, port, false);
+ if (!domain)
+ return errno;
+
+@@ -575,7 +576,8 @@ static struct domain *find_connected_domain(unsigned int domid)
+ return domain;
+ }
+
+-int do_set_target(struct connection *conn, struct buffered_data *in)
++int do_set_target(const void *ctx, struct connection *conn,
++ struct buffered_data *in)
+ {
+ char *vec[2];
+ unsigned int domid, tdomid;
+@@ -619,7 +621,8 @@ static struct domain *onearg_domain(struct connection *conn,
+ }
+
+ /* domid */
+-int do_release(struct connection *conn, struct buffered_data *in)
++int do_release(const void *ctx, struct connection *conn,
++ struct buffered_data *in)
+ {
+ struct domain *domain;
+
+@@ -634,7 +637,8 @@ int do_release(struct connection *conn, struct buffered_data *in)
+ return 0;
+ }
+
+-int do_resume(struct connection *conn, struct buffered_data *in)
++int do_resume(const void *ctx, struct connection *conn,
++ struct buffered_data *in)
+ {
+ struct domain *domain;
+
+@@ -649,7 +653,8 @@ int do_resume(struct connection *conn, struct buffered_data *in)
+ return 0;
+ }
+
+-int do_get_domain_path(struct connection *conn, struct buffered_data *in)
++int do_get_domain_path(const void *ctx, struct connection *conn,
++ struct buffered_data *in)
+ {
+ char *path;
+ const char *domid_str = onearg(in);
+@@ -657,18 +662,17 @@ int do_get_domain_path(struct connection *conn, struct buffered_data *in)
+ if (!domid_str)
+ return EINVAL;
+
+- path = talloc_domain_path(conn, atoi(domid_str));
++ path = talloc_domain_path(ctx, atoi(domid_str));
+ if (!path)
+ return errno;
+
+ send_reply(conn, XS_GET_DOMAIN_PATH, path, strlen(path) + 1);
+
+- talloc_free(path);
+-
+ return 0;
+ }
+
+-int do_is_domain_introduced(struct connection *conn, struct buffered_data *in)
++int do_is_domain_introduced(const void *ctx, struct connection *conn,
++ struct buffered_data *in)
+ {
+ int result;
+ unsigned int domid;
+@@ -689,7 +693,8 @@ int do_is_domain_introduced(struct connection *conn, struct buffered_data *in)
+ }
+
+ /* Allow guest to reset all watches */
+-int do_reset_watches(struct connection *conn, struct buffered_data *in)
++int do_reset_watches(const void *ctx, struct connection *conn,
++ struct buffered_data *in)
+ {
+ conn_delete_all_watches(conn);
+ conn_delete_all_transactions(conn);
+diff --git a/tools/xenstore/xenstored_domain.h b/tools/xenstore/xenstored_domain.h
+index 904faa923afb..b9e152890149 100644
+--- a/tools/xenstore/xenstored_domain.h
++++ b/tools/xenstore/xenstored_domain.h
+@@ -24,25 +24,32 @@ void handle_event(void);
+ void check_domains(void);
+
+ /* domid, mfn, eventchn, path */
+-int do_introduce(struct connection *conn, struct buffered_data *in);
++int do_introduce(const void *ctx, struct connection *conn,
++ struct buffered_data *in);
+
+ /* domid */
+-int do_is_domain_introduced(struct connection *conn, struct buffered_data *in);
++int do_is_domain_introduced(const void *ctx, struct connection *conn,
++ struct buffered_data *in);
+
+ /* domid */
+-int do_release(struct connection *conn, struct buffered_data *in);
++int do_release(const void *ctx, struct connection *conn,
++ struct buffered_data *in);
+
+ /* domid */
+-int do_resume(struct connection *conn, struct buffered_data *in);
++int do_resume(const void *ctx, struct connection *conn,
++ struct buffered_data *in);
+
+ /* domid, target */
+-int do_set_target(struct connection *conn, struct buffered_data *in);
++int do_set_target(const void *ctx, struct connection *conn,
++ struct buffered_data *in);
+
+ /* domid */
+-int do_get_domain_path(struct connection *conn, struct buffered_data *in);
++int do_get_domain_path(const void *ctx, struct connection *conn,
++ struct buffered_data *in);
+
+ /* Allow guest to reset all watches */
+-int do_reset_watches(struct connection *conn, struct buffered_data *in);
++int do_reset_watches(const void *ctx, struct connection *conn,
++ struct buffered_data *in);
+
+ void domain_init(int evtfd);
+ void dom0_init(void);
+diff --git a/tools/xenstore/xenstored_transaction.c b/tools/xenstore/xenstored_transaction.c
+index 28774813de83..3e3eb47326cc 100644
+--- a/tools/xenstore/xenstored_transaction.c
++++ b/tools/xenstore/xenstored_transaction.c
+@@ -481,7 +481,8 @@ struct transaction *transaction_lookup(struct connection *conn, uint32_t id)
+ return ERR_PTR(-ENOENT);
+ }
+
+-int do_transaction_start(struct connection *conn, struct buffered_data *in)
++int do_transaction_start(const void *ctx, struct connection *conn,
++ struct buffered_data *in)
+ {
+ struct transaction *trans, *exists;
+ char id_str[20];
+@@ -494,8 +495,8 @@ int do_transaction_start(struct connection *conn, struct buffered_data *in)
+ conn->transaction_started > quota_max_transaction)
+ return ENOSPC;
+
+- /* Attach transaction to input for autofree until it's complete */
+- trans = talloc_zero(in, struct transaction);
++ /* Attach transaction to ctx for autofree until it's complete */
++ trans = talloc_zero(ctx, struct transaction);
+ if (!trans)
+ return ENOMEM;
+
+@@ -544,7 +545,8 @@ static int transaction_fix_domains(struct transaction *trans, bool update)
+ return 0;
+ }
+
+-int do_transaction_end(struct connection *conn, struct buffered_data *in)
++int do_transaction_end(const void *ctx, struct connection *conn,
++ struct buffered_data *in)
+ {
+ const char *arg = onearg(in);
+ struct transaction *trans;
+@@ -562,8 +564,8 @@ int do_transaction_end(struct connection *conn, struct buffered_data *in)
+ if (!conn->transaction_started)
+ conn->ta_start_time = 0;
+
+- /* Attach transaction to in for auto-cleanup */
+- talloc_steal(in, trans);
++ /* Attach transaction to ctx for auto-cleanup */
++ talloc_steal(ctx, trans);
+
+ if (streq(arg, "T")) {
+ if (trans->fail)
+diff --git a/tools/xenstore/xenstored_transaction.h b/tools/xenstore/xenstored_transaction.h
+index e3cbd6b23095..39d7f81c5127 100644
+--- a/tools/xenstore/xenstored_transaction.h
++++ b/tools/xenstore/xenstored_transaction.h
+@@ -29,8 +29,10 @@ struct transaction;
+
+ extern uint64_t generation;
+
+-int do_transaction_start(struct connection *conn, struct buffered_data *node);
+-int do_transaction_end(struct connection *conn, struct buffered_data *in);
++int do_transaction_start(const void *ctx, struct connection *conn,
++ struct buffered_data *node);
++int do_transaction_end(const void *ctx, struct connection *conn,
++ struct buffered_data *in);
+
+ struct transaction *transaction_lookup(struct connection *conn, uint32_t id);
+
+diff --git a/tools/xenstore/xenstored_watch.c b/tools/xenstore/xenstored_watch.c
+index 85362bcce314..316c08b7f754 100644
+--- a/tools/xenstore/xenstored_watch.c
++++ b/tools/xenstore/xenstored_watch.c
+@@ -243,7 +243,7 @@ static struct watch *add_watch(struct connection *conn, char *path, char *token,
+ return NULL;
+ }
+
+-int do_watch(struct connection *conn, struct buffered_data *in)
++int do_watch(const void *ctx, struct connection *conn, struct buffered_data *in)
+ {
+ struct watch *watch;
+ char *vec[2];
+@@ -252,7 +252,7 @@ int do_watch(struct connection *conn, struct buffered_data *in)
+ if (get_strings(in, vec, ARRAY_SIZE(vec)) != ARRAY_SIZE(vec))
+ return EINVAL;
+
+- errno = check_watch_path(conn, in, &(vec[0]), &relative);
++ errno = check_watch_path(conn, ctx, &(vec[0]), &relative);
+ if (errno)
+ return errno;
+
+@@ -283,7 +283,8 @@ int do_watch(struct connection *conn, struct buffered_data *in)
+ return 0;
+ }
+
+-int do_unwatch(struct connection *conn, struct buffered_data *in)
++int do_unwatch(const void *ctx, struct connection *conn,
++ struct buffered_data *in)
+ {
+ struct watch *watch;
+ char *node, *vec[2];
+@@ -291,7 +292,7 @@ int do_unwatch(struct connection *conn, struct buffered_data *in)
+ if (get_strings(in, vec, ARRAY_SIZE(vec)) != ARRAY_SIZE(vec))
+ return EINVAL;
+
+- node = canonicalize(conn, in, vec[0]);
++ node = canonicalize(conn, ctx, vec[0]);
+ if (!node)
+ return ENOMEM;
+ list_for_each_entry(watch, &conn->watches, list) {
+diff --git a/tools/xenstore/xenstored_watch.h b/tools/xenstore/xenstored_watch.h
+index 0e693f0839cd..091890edca96 100644
+--- a/tools/xenstore/xenstored_watch.h
++++ b/tools/xenstore/xenstored_watch.h
+@@ -21,8 +21,10 @@
+
+ #include "xenstored_core.h"
+
+-int do_watch(struct connection *conn, struct buffered_data *in);
+-int do_unwatch(struct connection *conn, struct buffered_data *in);
++int do_watch(const void *ctx, struct connection *conn,
++ struct buffered_data *in);
++int do_unwatch(const void *ctx, struct connection *conn,
++ struct buffered_data *in);
+
+ /* Fire all watches: !exact means all the children are affected (ie. rm). */
+ void fire_watches(struct connection *conn, const void *tmp, const char *name,
+--
+2.37.4
+