--- tools/xenstore/xenstored_core.c.orig 2007-09-17 08:11:14.000000000 +0800 +++ tools/xenstore/xenstored_core.c 2007-09-17 13:02:42.000000000 +0800 @@ -347,6 +347,11 @@ int *talloc_open(const char *pathname, i int *fd; fd = talloc(pathname, int); + if (!fd) + { + errno = ENOMEM; + return NULL; + } *fd = open(pathname, flags, mode); if (*fd < 0) { int saved_errno = errno; @@ -397,6 +402,11 @@ static struct node *read_node(struct con } node = talloc(name, struct node); + if (!node) + { + errno = ENOMEM; + return NULL; + } node->name = talloc_strdup(node, name); node->parent = NULL; node->tdb = tdb_context(conn); @@ -493,8 +503,9 @@ static char *get_parent(const char *node /* What do parents say? */ static enum xs_perm_type ask_parents(struct connection *conn, const char *name) { - struct node *node; - + struct node *node = NULL; + enum xs_perm_type status; + do { name = get_parent(name); node = read_node(conn, name); @@ -506,7 +517,12 @@ static enum xs_perm_type ask_parents(str if (!node) corrupt(conn, "No permissions file at root"); - return perm_for_conn(conn, node->perms, node->num_perms); + status = perm_for_conn(conn, node->perms, node->num_perms); + if (node) + talloc_free(node); + + /* FIXME: name as returned from get_parent() can sometimes be allocated memory and sometimes otherwise, and if it is allocated it has to be deallocated here */ + return status; } /* We have a weird permissions system. You can allow someone into a @@ -729,6 +745,7 @@ static void send_directory(struct connec } send_reply(conn, XS_DIRECTORY, node->children, node->childlen); + talloc_free(node); } static void do_read(struct connection *conn, const char *name) @@ -743,6 +760,7 @@ static void do_read(struct connection *c } send_reply(conn, XS_READ, node->data, node->datalen); + talloc_free(node); } static void delete_node_single(struct connection *conn, struct node *node) @@ -793,6 +811,11 @@ static struct node *construct_node(struc /* Allocate node */ node = talloc(name, struct node); + if (!node) + { + errno = ENOMEM; + return NULL; + } node->tdb = tdb_context(conn); node->name = talloc_strdup(node, name); @@ -808,9 +831,15 @@ static struct node *construct_node(struc node->childlen = node->datalen = 0; node->parent = parent; domain_entry_inc(conn, node); + talloc_free(parentname); + return node; } +/* FIXME: construct_node() as above has a lot of allocated memory in its */ +/* structure, these therefore have to be deallocated inside destroy_node() */ +/* is not deallocated */ + static int destroy_node(void *_node) { struct node *node = _node; @@ -937,17 +966,19 @@ static void delete_node(struct connectio for (i = 0; i < node->childlen; i += strlen(node->children+i) + 1) { struct node *child; - child = read_node(conn, - talloc_asprintf(node, "%s/%s", node->name, - node->children + i)); + /* talloc_asprintf() will return an allocated memory pointer */ + char *pnode = talloc_asprintf(node, "%s/%s", node->name, node->children + i); + child = read_node(conn, pnode); if (child) { delete_node(conn, child); + talloc_free(child); } else { trace("delete_node: No child '%s/%s' found!\n", node->name, node->children + i); /* Skip it, we've already deleted the parent. */ } + talloc_free(pnode); } } @@ -989,18 +1020,29 @@ static int _rm(struct connection *conn, /* Delete from parent first, then if we crash, the worst that can happen is the child will continue to take up space, but will otherwise be unreachable. */ - struct node *parent = read_node(conn, get_parent(name)); + char *parentname = get_parent(name); + struct node *parent; + + if (!parentname) + return 0; + + parent = read_node(conn, parentname); if (!parent) { send_error(conn, EINVAL); + talloc_free(parentname); return 0; } if (!delete_child(conn, parent, basename(name))) { send_error(conn, EINVAL); + talloc_free(parent); + talloc_free(parentname); return 0; } delete_node(conn, node); + talloc_free(parent); + talloc_free(parentname); return 1; } @@ -1025,7 +1067,14 @@ static void do_rm(struct connection *con if (!node) { /* Didn't exist already? Fine, if parent exists. */ if (errno == ENOENT) { - node = read_node(conn, get_parent(name)); + char *parentname = get_parent(name); + + if (!parentname) + { + errno = ENOMEM; + return; + } + node = read_node(conn, parentname); if (node) { send_ack(conn, XS_RM); return; @@ -1067,7 +1116,11 @@ static void do_get_perms(struct connecti if (!strings) send_error(conn, errno); else + { send_reply(conn, XS_GET_PERMS, strings, len); + talloc_free(strings); + } + talloc_free(node); } static void do_set_perms(struct connection *conn, struct buffered_data *in) @@ -1098,6 +1151,7 @@ static void do_set_perms(struct connecti perms = talloc_array(node, struct xs_permissions, num); if (!xs_strings_to_perms(perms, num, permstr)) { send_error(conn, errno); + talloc_free(node); return; } @@ -1105,6 +1159,7 @@ static void do_set_perms(struct connecti if (domain_is_unprivileged(conn) && perms[0].id != node->perms[0].id) { send_error(conn, EPERM); + talloc_free(node); return; } @@ -1115,8 +1170,10 @@ static void do_set_perms(struct connecti if (!write_node(conn, node)) { send_error(conn, errno); + talloc_free(node); return; } + talloc_free(node); add_change_node(conn->transaction, name, false); fire_watches(conn, name, false); @@ -1301,7 +1358,7 @@ static void handle_input(struct connecti bad_client: /* Kill it. */ - talloc_free(conn); + talloc_free(conn->in); } static void handle_output(struct connection *conn)