/** * Import an existing talloc pointer into a Python object. */ _PUBLIC_ PyObject *pytalloc_steal_ex(PyTypeObject *py_type, TALLOC_CTX *mem_ctx, void *ptr) { PyTypeObject *BaseObjectType = pytalloc_GetBaseObjectType(); PyTypeObject *ObjectType = pytalloc_GetObjectType(); if (mem_ctx == NULL) { return PyErr_NoMemory(); } if (PyType_IsSubtype(py_type, BaseObjectType)) { pytalloc_BaseObject *ret = (pytalloc_BaseObject *)py_type->tp_alloc(py_type, 0); ret->talloc_ctx = talloc_new(NULL); if (ret->talloc_ctx == NULL) { return NULL; } /* * This allows us to keep multiple references to this object - * we only reference this context, which is per ptr, not the * talloc_ctx, which is per pytalloc_Object */ if (talloc_steal(ret->talloc_ctx, mem_ctx) == NULL) { return NULL; } ret->talloc_ptr_ctx = mem_ctx; talloc_set_name_const(ret->talloc_ctx, py_type->tp_name); ret->ptr = ptr; return (PyObject *)ret; } else if (PyType_IsSubtype(py_type, ObjectType)) { pytalloc_Object *ret = (pytalloc_Object *)py_type->tp_alloc(py_type, 0); ret->talloc_ctx = talloc_new(NULL); if (ret->talloc_ctx == NULL) { return NULL; } if (talloc_steal(ret->talloc_ctx, mem_ctx) == NULL) { return NULL; } talloc_set_name_const(ret->talloc_ctx, py_type->tp_name); ret->ptr = ptr; return (PyObject *)ret; } else { PyErr_SetString(PyExc_RuntimeError, "pytalloc_steal_ex() called for object type " "not based on talloc"); return NULL; } }
void *_policy_handle_create(struct pipes_struct *p, struct policy_handle *hnd, uint32_t access_granted, size_t data_size, const char *type, NTSTATUS *pstatus) { struct dcesrv_handle *rpc_hnd; void *data; if (p->pipe_handles->count > MAX_OPEN_POLS) { DEBUG(0, ("ERROR: Too many handles (%d) for RPC connection %s\n", (int) p->pipe_handles->count, get_pipe_name_from_syntax(talloc_tos(), &p->contexts->syntax))); *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES; return NULL; } data = talloc_size(talloc_tos(), data_size); if (data == NULL) { *pstatus = NT_STATUS_NO_MEMORY; return NULL; } talloc_set_name_const(data, type); rpc_hnd = create_rpc_handle_internal(p, hnd, data); if (rpc_hnd == NULL) { TALLOC_FREE(data); *pstatus = NT_STATUS_NO_MEMORY; return NULL; } rpc_hnd->access_granted = access_granted; *pstatus = NT_STATUS_OK; return data; }
/** Setup an LDAP sync request * * Allocates a request, with request/reply packets. * * Sets various fields in the request->packet with information from the file descriptor * we received from libldap. * * @param[in] listen The common listener encapsulating the libldap fd. * @param[in] inst of the proto_ldap_sync module. * @param[in] sync_id the unique identifier of the sync. * @return * - A new request on success. * - NULL on error. */ static REQUEST *proto_ldap_request_setup(rad_listen_t *listen, proto_ldap_inst_t *inst, int sync_id) { TALLOC_CTX *ctx; RADIUS_PACKET *packet; REQUEST *request; ctx = talloc_pool(NULL, main_config->talloc_pool_size); if (!ctx) return NULL; talloc_set_name_const(ctx, "ldap_inst_pool"); packet = fr_radius_alloc(ctx, false); packet->sockfd = listen->fd; packet->id = sync_id; packet->src_ipaddr = inst->dst_ipaddr; packet->src_port = inst->dst_port; packet->dst_ipaddr = inst->src_ipaddr; packet->dst_port = inst->src_port; gettimeofday(&packet->timestamp, NULL); request = request_setup(ctx, listen, packet, inst->client, NULL); if (!request) return NULL; request->process = request_queued; return request; }
/* convert a dom_sid to a string */ char *dom_sid_string(TALLOC_CTX *mem_ctx, const struct dom_sid *sid) { char buf[DOM_SID_STR_BUFLEN]; char *result; int len; len = dom_sid_string_buf(sid, buf, sizeof(buf)); if (len+1 > sizeof(buf)) { return talloc_strdup(mem_ctx, "(SID ERR)"); } /* * Avoid calling strlen (via talloc_strdup), we already have * the length */ result = (char *)talloc_memdup(mem_ctx, buf, len+1); if (result == NULL) { return NULL; } /* * beautify the talloc_report output */ talloc_set_name_const(result, result); return result; }
struct tsocket_context *_tsocket_context_create(TALLOC_CTX *mem_ctx, const struct tsocket_context_ops *ops, void *pstate, size_t psize, const char *type, const char *location) { void **ppstate = (void **)pstate; struct tsocket_context *sock; sock = talloc_zero(mem_ctx, struct tsocket_context); if (!sock) { return NULL; } sock->ops = ops; sock->location = location; sock->private_data = talloc_size(sock, psize); if (!sock->private_data) { talloc_free(sock); return NULL; } talloc_set_name_const(sock->private_data, type); talloc_set_destructor(sock, tsocket_context_destructor); *ppstate = sock->private_data; return sock; }
struct tsocket_address *_tsocket_address_create(TALLOC_CTX *mem_ctx, const struct tsocket_address_ops *ops, void *pstate, size_t psize, const char *type, const char *location) { void **ppstate = (void **)pstate; struct tsocket_address *addr; addr = talloc_zero(mem_ctx, struct tsocket_address); if (!addr) { return NULL; } addr->ops = ops; addr->location = location; addr->private_data = talloc_size(addr, psize); if (!addr->private_data) { talloc_free(addr); return NULL; } talloc_set_name_const(addr->private_data, type); *ppstate = addr->private_data; return addr; }
void *_policy_handle_create(struct pipes_struct *p, struct policy_handle *hnd, uint32_t access_granted, size_t data_size, const char *type, NTSTATUS *pstatus) { struct policy *pol; void *data; if (p->pipe_handles->count > MAX_OPEN_POLS) { DEBUG(0, ("policy_handle_create: ERROR: too many handles (%d) " "on pipe %s.\n", (int)p->pipe_handles->count, get_pipe_name_from_syntax(talloc_tos(), &p->syntax))); *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES; return NULL; } data = talloc_size(talloc_tos(), data_size); if (data == NULL) { *pstatus = NT_STATUS_NO_MEMORY; return NULL; } talloc_set_name_const(data, type); pol = create_policy_hnd_internal(p, hnd, data); if (pol == NULL) { TALLOC_FREE(data); *pstatus = NT_STATUS_NO_MEMORY; return NULL; } pol->access_granted = access_granted; *pstatus = NT_STATUS_OK; return data; }
/**************************************************************** Callback to get the PAC_LOGON_INFO from the blob ****************************************************************/ static NTSTATUS kerberos_fetch_pac(struct auth4_context *auth_ctx, TALLOC_CTX *mem_ctx, struct smb_krb5_context *smb_krb5_context, DATA_BLOB *pac_blob, const char *princ_name, const struct tsocket_address *remote_address, uint32_t session_info_flags, struct auth_session_info **session_info) { TALLOC_CTX *tmp_ctx; struct PAC_DATA *pac_data = NULL; struct PAC_DATA_CTR *pac_data_ctr = NULL; NTSTATUS status = NT_STATUS_INTERNAL_ERROR; tmp_ctx = talloc_new(mem_ctx); if (!tmp_ctx) { return NT_STATUS_NO_MEMORY; } if (pac_blob) { status = kerberos_decode_pac(tmp_ctx, *pac_blob, NULL, NULL, NULL, NULL, 0, &pac_data); if (!NT_STATUS_IS_OK(status)) { goto done; } } pac_data_ctr = talloc(mem_ctx, struct PAC_DATA_CTR); if (pac_data_ctr == NULL) { status = NT_STATUS_NO_MEMORY; goto done; } talloc_set_name_const(pac_data_ctr, "struct PAC_DATA_CTR"); pac_data_ctr->pac_data = talloc_steal(pac_data_ctr, pac_data); pac_data_ctr->pac_blob = data_blob_talloc(pac_data_ctr, pac_blob->data, pac_blob->length); auth_ctx->private_data = talloc_steal(auth_ctx, pac_data_ctr); *session_info = talloc_zero(mem_ctx, struct auth_session_info); if (!*session_info) { status = NT_STATUS_NO_MEMORY; goto done; } status = NT_STATUS_OK; done: TALLOC_FREE(tmp_ctx); return status; }
/** * Import an existing talloc pointer into a Python object, leaving the * original parent, and creating a reference to the object in the python * object. * * We remember the object we hold the reference to (a * possibly-non-talloc pointer), the existing parent (typically the * start of the array) and the new referenced parent. That way we can * cope with the fact that we will have multiple parents, one per time * python sees the object. */ _PUBLIC_ PyObject *pytalloc_reference_ex(PyTypeObject *py_type, TALLOC_CTX *mem_ctx, void *ptr) { PyTypeObject *BaseObjectType = pytalloc_GetBaseObjectType(); PyTypeObject *ObjectType = pytalloc_GetObjectType(); if (mem_ctx == NULL) { return PyErr_NoMemory(); } if (PyType_IsSubtype(py_type, BaseObjectType)) { pytalloc_BaseObject *ret = (pytalloc_BaseObject *)py_type->tp_alloc(py_type, 0); ret->talloc_ctx = talloc_new(NULL); if (ret->talloc_ctx == NULL) { return NULL; } if (talloc_reference(ret->talloc_ctx, mem_ctx) == NULL) { return NULL; } talloc_set_name_const(ret->talloc_ctx, py_type->tp_name); ret->talloc_ptr_ctx = mem_ctx; ret->ptr = ptr; return (PyObject *)ret; } else if (PyType_IsSubtype(py_type, ObjectType)) { pytalloc_Object *ret = (pytalloc_Object *)py_type->tp_alloc(py_type, 0); ret->talloc_ctx = talloc_new(NULL); if (ret->talloc_ctx == NULL) { return NULL; } if (talloc_reference(ret->talloc_ctx, mem_ctx) == NULL) { return NULL; } talloc_set_name_const(ret->talloc_ctx, py_type->tp_name); ret->ptr = ptr; return (PyObject *)ret; } else { PyErr_SetString(PyExc_RuntimeError, "pytalloc_reference_ex() called for object type " "not based on talloc"); return NULL; } }
_PUBLIC_ bool cli_credentials_set_old_password(struct cli_credentials *cred, const char *val, enum credentials_obtained obtained) { cred->old_password = talloc_strdup(cred, val); if (cred->old_password) { /* Don't print the actual password in talloc memory dumps */ talloc_set_name_const(cred->old_password, "password set via cli_credentials_set_old_password"); } return true; }
char* ez_strchompc (char *string, char c) { char *s; ez_return_val_if_fail (string != NULL, NULL); for (s = string + strlen (string) - 1; s >= string && (uchar)*s == c; s--) *s = '\0'; talloc_set_name_const (string, string); return string; }
char* ez_strchugc (char *string, char c) { uchar *s; ez_return_val_if_fail (string != NULL, NULL); for (s = (uchar*) string; *s && (uchar)*s == c; s++) ;; memmove (string, s, strlen ((char *) s) + 1); talloc_set_name_const (string, string); return string; }
char* ez_strchug (char *string) { uchar *start; ez_return_val_if_fail (string != NULL, NULL); for (start = (uchar*) string; *start && isspace (*start); start++) ;; memmove (string, start, strlen ((char *) start) + 1); talloc_set_name_const (string, string); return string; }
/* make a remote ctdb call - async send. Called in daemon context. This constructs a ctdb_call request and queues it for processing. This call never blocks. */ struct ctdb_call_state *ctdb_daemon_call_send_remote(struct ctdb_db_context *ctdb_db, struct ctdb_call *call, struct ctdb_ltdb_header *header) { uint32_t len; struct ctdb_call_state *state; struct ctdb_context *ctdb = ctdb_db->ctdb; state = talloc_zero(ctdb_db, struct ctdb_call_state); CTDB_NO_MEMORY_NULL(ctdb, state); len = offsetof(struct ctdb_req_call, data) + call->key.dsize + call->call_data.dsize; state->c = ctdb->methods->allocate_pkt(state, len); CTDB_NO_MEMORY_NULL(ctdb, state->c); talloc_set_name_const(state->c, "req_call packet"); state->c->hdr.length = len; state->c->hdr.ctdb_magic = CTDB_MAGIC; state->c->hdr.ctdb_version = CTDB_VERSION; state->c->hdr.operation = CTDB_REQ_CALL; state->c->hdr.destnode = header->dmaster; state->c->hdr.srcnode = ctdb->vnn; /* this limits us to 16k outstanding messages - not unreasonable */ state->c->hdr.reqid = idr_get_new(ctdb->idr, state, 0xFFFF); state->c->flags = call->flags; state->c->db_id = ctdb_db->db_id; state->c->callid = call->call_id; state->c->keylen = call->key.dsize; state->c->calldatalen = call->call_data.dsize; memcpy(&state->c->data[0], call->key.dptr, call->key.dsize); memcpy(&state->c->data[call->key.dsize], call->call_data.dptr, call->call_data.dsize); state->call = *call; state->call.call_data.dptr = &state->c->data[call->key.dsize]; state->call.key.dptr = &state->c->data[0]; state->node = ctdb->nodes[header->dmaster]; state->state = CTDB_CALL_WAIT; state->header = *header; state->ctdb_db = ctdb_db; talloc_set_destructor(state, ctdb_call_destructor); ctdb_queue_packet(ctdb, &state->c->hdr); event_add_timed(ctdb->ev, state, timeval_current_ofs(CTDB_REQ_TIMEOUT, 0), ctdb_call_timeout, state); return state; }
/** * Import an existing talloc pointer into a Python object. */ _PUBLIC_ PyObject *pytalloc_steal_ex(PyTypeObject *py_type, TALLOC_CTX *mem_ctx, void *ptr) { pytalloc_Object *ret = (pytalloc_Object *)py_type->tp_alloc(py_type, 0); ret->talloc_ctx = talloc_new(NULL); if (ret->talloc_ctx == NULL) { return NULL; } if (talloc_steal(ret->talloc_ctx, mem_ctx) == NULL) { return NULL; } talloc_set_name_const(ret->talloc_ctx, py_type->tp_name); ret->ptr = ptr; return (PyObject *)ret; }
char *server_id_str(TALLOC_CTX *mem_ctx, const struct server_id *id) { struct server_id_buf tmp; char *result; result = talloc_strdup(mem_ctx, server_id_str_buf(*id, &tmp)); if (result == NULL) { return NULL; } /* * beautify the talloc_report output */ talloc_set_name_const(result, result); return result; }
char* ez_strconcat (const char *string1, ...) { size_t l; va_list args; char *s; char *concat; char *ptr; ez_return_val_if_fail (string1 != NULL, NULL); l = 1 + strlen (string1); va_start (args, string1); s = va_arg (args, char*); while (s) { l += strlen (s); s = va_arg (args, char*); } va_end (args); concat = ez_new (char, l); ptr = concat; ptr = ez_stpcpy (ptr, string1); va_start (args, string1); s = va_arg (args, char*); while (s) { ptr = ez_stpcpy (ptr, s); s = va_arg (args, char*); } va_end (args); talloc_set_name_const (concat, concat); return concat; }
static bool test_free_children(void) { void *root; const char *p1, *p2, *name, *name2; talloc_enable_null_tracking(); root = talloc_new(NULL); p1 = talloc_strdup(root, "foo1"); p2 = talloc_strdup(p1, "foo2"); talloc_set_name(p1, "%s", "testname"); talloc_free_children(p1); /* check its still a valid talloc ptr */ talloc_get_size(talloc_get_name(p1)); if (strcmp(talloc_get_name(p1), "testname") != 0) { return false; } talloc_set_name(p1, "%s", "testname"); name = talloc_get_name(p1); talloc_free_children(p1); /* check its still a valid talloc ptr */ talloc_get_size(talloc_get_name(p1)); torture_assert("name", name == talloc_get_name(p1), "name ptr changed"); torture_assert("namecheck", strcmp(talloc_get_name(p1), "testname") == 0, "wrong name"); CHECK_BLOCKS("name1", p1, 2); /* note that this does not free the old child name */ talloc_set_name_const(p1, "testname2"); name2 = talloc_get_name(p1); /* but this does */ talloc_free_children(p1); torture_assert("namecheck", strcmp(talloc_get_name(p1), "testname2") == 0, "wrong name"); CHECK_BLOCKS("name1", p1, 1); talloc_report_full(root, stdout); talloc_free(root); return true; }
/** * Allocate for @context a new node with given @name and @type. This * function returns NULL if there's not enough memory. */ Node *new_node(TALLOC_CTX *context, const char *name, ssize_t length, int type) { Node *node; node = talloc_zero(context, Node); if (node == NULL) return NULL; if (length < 0) length = strlen(name); node->name = talloc_strndup(node, name, length); if (node->name == NULL) return NULL; talloc_set_name_const(node->name, "$name"); node->type = type; node->parent = node; return node; }
/* send a redirect reply */ static void ctdb_call_send_redirect(struct ctdb_context *ctdb, struct ctdb_req_call *c, struct ctdb_ltdb_header *header) { struct ctdb_reply_redirect *r; r = ctdb->methods->allocate_pkt(ctdb, sizeof(*r)); CTDB_NO_MEMORY_FATAL(ctdb, r); talloc_set_name_const(r, "send_redirect packet"); r->hdr.length = sizeof(*r); r->hdr.ctdb_magic = CTDB_MAGIC; r->hdr.ctdb_version = CTDB_VERSION; r->hdr.operation = CTDB_REPLY_REDIRECT; r->hdr.destnode = c->hdr.srcnode; r->hdr.srcnode = ctdb->vnn; r->hdr.reqid = c->hdr.reqid; r->dmaster = header->dmaster; ctdb_queue_packet(ctdb, &r->hdr); talloc_free(r); }
_PUBLIC_ bool cli_credentials_set_password(struct cli_credentials *cred, const char *val, enum credentials_obtained obtained) { if (obtained >= cred->password_obtained) { cred->password_tries = 0; cred->password = talloc_strdup(cred, val); if (cred->password) { /* Don't print the actual password in talloc memory dumps */ talloc_set_name_const(cred->password, "password set via cli_credentials_set_password"); } cred->password_obtained = obtained; cli_credentials_invalidate_ccache(cred, cred->password_obtained); cred->nt_hash = NULL; cred->lm_response = data_blob(NULL, 0); cred->nt_response = data_blob(NULL, 0); return true; } return false; }
/* message handler for when we are in daemon mode. This redirects the message to the right client */ static void daemon_message_handler(uint64_t srvid, TDB_DATA data, void *private_data) { struct ctdb_client *client = talloc_get_type(private_data, struct ctdb_client); struct ctdb_req_message *r; int len; /* construct a message to send to the client containing the data */ len = offsetof(struct ctdb_req_message, data) + data.dsize; r = ctdbd_allocate_pkt(client->ctdb, client->ctdb, CTDB_REQ_MESSAGE, len, struct ctdb_req_message); CTDB_NO_MEMORY_VOID(client->ctdb, r); talloc_set_name_const(r, "req_message packet"); r->srvid = srvid; r->datalen = data.dsize; memcpy(&r->data[0], data.dptr, data.dsize); daemon_queue_send(client, &r->hdr); talloc_free(r); }
struct tevent_req *_tevent_req_create(TALLOC_CTX *mem_ctx, void *pdata, size_t data_size, const char *type, const char *location) { struct tevent_req *req; void **ppdata = (void **)pdata; void *data; req = talloc_zero(mem_ctx, struct tevent_req); if (req == NULL) { return NULL; } req->internal.private_type = type; req->internal.create_location = location; req->internal.finish_location = NULL; req->internal.state = TEVENT_REQ_IN_PROGRESS; req->internal.trigger = tevent_create_immediate(req); if (!req->internal.trigger) { talloc_free(req); return NULL; } req->internal.defer_callback_ev = NULL; data = talloc_zero_size(req, data_size); if (data == NULL) { talloc_free(req); return NULL; } talloc_set_name_const(data, type); req->data = data; *ppdata = data; return req; }
static void ctdb_send_error(struct ctdb_context *ctdb, struct ctdb_req_header *hdr, uint32_t status, const char *fmt, ...) { va_list ap; struct ctdb_reply_error *r; char *msg; int msglen, len; va_start(ap, fmt); msg = talloc_vasprintf(ctdb, fmt, ap); if (msg == NULL) { ctdb_fatal(ctdb, "Unable to allocate error in ctdb_send_error\n"); } va_end(ap); msglen = strlen(msg)+1; len = offsetof(struct ctdb_reply_error, msg); r = ctdb->methods->allocate_pkt(msg, len + msglen); CTDB_NO_MEMORY_FATAL(ctdb, r); talloc_set_name_const(r, "send_error packet"); r->hdr.length = len + msglen; r->hdr.ctdb_magic = CTDB_MAGIC; r->hdr.ctdb_version = CTDB_VERSION; r->hdr.operation = CTDB_REPLY_ERROR; r->hdr.destnode = hdr->srcnode; r->hdr.srcnode = ctdb->vnn; r->hdr.reqid = hdr->reqid; r->status = status; r->msglen = msglen; memcpy(&r->msg[0], msg, msglen); ctdb_queue_packet(ctdb, &r->hdr); talloc_free(msg); }
struct dcerpc_binding_handle *_dcerpc_binding_handle_create(TALLOC_CTX *mem_ctx, const struct dcerpc_binding_handle_ops *ops, const struct GUID *object, const struct ndr_interface_table *table, void *pstate, size_t psize, const char *type, const char *location) { struct dcerpc_binding_handle *h; void **ppstate = (void **)pstate; void *state; h = talloc_zero(mem_ctx, struct dcerpc_binding_handle); if (h == NULL) { return NULL; } h->ops = ops; h->location = location; h->object = object; h->table = table; state = talloc_zero_size(h, psize); if (state == NULL) { talloc_free(h); return NULL; } talloc_set_name_const(state, type); h->private_data = state; talloc_set_destructor(h, dcerpc_binding_handle_destructor); *ppstate = state; return h; }
/* send a dmaster request (give another node the dmaster for a record) This is always sent to the lmaster, which ensures that the lmaster always knows who the dmaster is. The lmaster will then send a CTDB_REPLY_DMASTER to the new dmaster */ static void ctdb_call_send_dmaster(struct ctdb_db_context *ctdb_db, struct ctdb_req_call *c, struct ctdb_ltdb_header *header, TDB_DATA *key, TDB_DATA *data) { struct ctdb_req_dmaster *r; struct ctdb_context *ctdb = ctdb_db->ctdb; int len; len = offsetof(struct ctdb_req_dmaster, data) + key->dsize + data->dsize; r = ctdb->methods->allocate_pkt(ctdb, len); CTDB_NO_MEMORY_FATAL(ctdb, r); talloc_set_name_const(r, "send_dmaster packet"); r->hdr.length = len; r->hdr.ctdb_magic = CTDB_MAGIC; r->hdr.ctdb_version = CTDB_VERSION; r->hdr.operation = CTDB_REQ_DMASTER; r->hdr.destnode = ctdb_lmaster(ctdb, key); r->hdr.srcnode = ctdb->vnn; r->hdr.reqid = c->hdr.reqid; r->db_id = c->db_id; r->dmaster = c->hdr.srcnode; r->keylen = key->dsize; r->datalen = data->dsize; memcpy(&r->data[0], key->dptr, key->dsize); memcpy(&r->data[key->dsize], data->dptr, data->dsize); /* XXX - probably not necessary when lmaster==dmaster update the ltdb to record the new dmaster */ header->dmaster = r->hdr.destnode; ctdb_ltdb_store(ctdb_db, *key, header, *data); ctdb_queue_packet(ctdb, &r->hdr); talloc_free(r); }
/* miscellaneous tests to try to get a higher test coverage percentage */ static bool test_misc(void) { void *root, *p1; char *p2; double *d; const char *name; printf("test: misc\n# MISCELLANEOUS\n"); root = talloc_new(NULL); p1 = talloc_size(root, 0x7fffffff); torture_assert("misc", !p1, "failed: large talloc allowed\n"); p1 = talloc_strdup(root, "foo"); talloc_increase_ref_count(p1); talloc_increase_ref_count(p1); talloc_increase_ref_count(p1); CHECK_BLOCKS("misc", p1, 1); CHECK_BLOCKS("misc", root, 2); talloc_unlink(NULL, p1); CHECK_BLOCKS("misc", p1, 1); CHECK_BLOCKS("misc", root, 2); talloc_unlink(NULL, p1); CHECK_BLOCKS("misc", p1, 1); CHECK_BLOCKS("misc", root, 2); p2 = talloc_strdup(p1, "foo"); torture_assert("misc", talloc_unlink(root, p2) == -1, "failed: talloc_unlink() of non-reference context should return -1\n"); torture_assert("misc", talloc_unlink(p1, p2) == 0, "failed: talloc_unlink() of parent should succeed\n"); talloc_unlink(NULL, p1); CHECK_BLOCKS("misc", p1, 1); CHECK_BLOCKS("misc", root, 2); name = talloc_set_name(p1, "my name is %s", "foo"); torture_assert_str_equal("misc", talloc_get_name(p1), "my name is foo", "failed: wrong name after talloc_set_name(my name is foo)"); torture_assert_str_equal("misc", talloc_get_name(p1), name, "failed: wrong name after talloc_set_name(my name is foo)"); CHECK_BLOCKS("misc", p1, 2); CHECK_BLOCKS("misc", root, 3); talloc_set_name_const(p1, NULL); torture_assert_str_equal ("misc", talloc_get_name(p1), "UNNAMED", "failed: wrong name after talloc_set_name(NULL)"); CHECK_BLOCKS("misc", p1, 2); CHECK_BLOCKS("misc", root, 3); torture_assert("misc", talloc_free(NULL) == -1, "talloc_free(NULL) should give -1\n"); talloc_set_destructor(p1, fail_destructor); torture_assert("misc", talloc_free(p1) == -1, "Failed destructor should cause talloc_free to fail\n"); talloc_set_destructor(p1, NULL); talloc_report(root, stderr); p2 = (char *)talloc_zero_size(p1, 20); torture_assert("misc", p2[19] == 0, "Failed to give zero memory\n"); talloc_free(p2); torture_assert("misc", talloc_strdup(root, NULL) == NULL, "failed: strdup on NULL should give NULL\n"); p2 = talloc_strndup(p1, "foo", 2); torture_assert("misc", strcmp("fo", p2) == 0, "strndup doesn't work\n"); p2 = talloc_asprintf_append_buffer(p2, "o%c", 'd'); torture_assert("misc", strcmp("food", p2) == 0, "talloc_asprintf_append_buffer doesn't work\n"); CHECK_BLOCKS("misc", p2, 1); CHECK_BLOCKS("misc", p1, 3); p2 = talloc_asprintf_append_buffer(NULL, "hello %s", "world"); torture_assert("misc", strcmp("hello world", p2) == 0, "talloc_asprintf_append_buffer doesn't work\n"); CHECK_BLOCKS("misc", p2, 1); CHECK_BLOCKS("misc", p1, 3); talloc_free(p2); d = talloc_array(p1, double, 0x20000000); torture_assert("misc", !d, "failed: integer overflow not detected\n"); d = talloc_realloc(p1, d, double, 0x20000000); torture_assert("misc", !d, "failed: integer overflow not detected\n"); talloc_free(p1); CHECK_BLOCKS("misc", root, 1); p1 = talloc_named(root, 100, "%d bytes", 100); CHECK_BLOCKS("misc", p1, 2); CHECK_BLOCKS("misc", root, 3); talloc_unlink(root, p1); p1 = talloc_init("%d bytes", 200); p2 = talloc_asprintf(p1, "my test '%s'", "string"); torture_assert_str_equal("misc", p2, "my test 'string'", "failed: talloc_asprintf(\"my test '%%s'\", \"string\") gave: \"%s\""); CHECK_BLOCKS("misc", p1, 3); CHECK_SIZE("misc", p2, 17); CHECK_BLOCKS("misc", root, 1); talloc_unlink(NULL, p1); p1 = talloc_named_const(root, 10, "p1"); p2 = (char *)talloc_named_const(root, 20, "p2"); (void)talloc_reference(p1, p2); talloc_report_full(root, stderr); talloc_unlink(root, p2); talloc_report_full(root, stderr); CHECK_BLOCKS("misc", p2, 1); CHECK_BLOCKS("misc", p1, 2); CHECK_BLOCKS("misc", root, 3); talloc_unlink(p1, p2); talloc_unlink(root, p1); p1 = talloc_named_const(root, 10, "p1"); p2 = (char *)talloc_named_const(root, 20, "p2"); (void)talloc_reference(NULL, p2); talloc_report_full(root, stderr); talloc_unlink(root, p2); talloc_report_full(root, stderr); CHECK_BLOCKS("misc", p2, 1); CHECK_BLOCKS("misc", p1, 1); CHECK_BLOCKS("misc", root, 2); talloc_unlink(NULL, p2); talloc_unlink(root, p1); /* Test that talloc_unlink is a no-op */ torture_assert("misc", talloc_unlink(root, NULL) == -1, "failed: talloc_unlink(root, NULL) == -1\n"); talloc_report(root, stderr); talloc_report(NULL, stderr); CHECK_SIZE("misc", root, 0); talloc_free(root); CHECK_SIZE("misc", NULL, 0); talloc_enable_null_tracking_no_autofree(); talloc_enable_leak_report(); talloc_enable_leak_report_full(); printf("success: misc\n"); return true; }
/* queue a packet for sending */ int ctdb_queue_send(struct ctdb_queue *queue, uint8_t *data, uint32_t length) { struct ctdb_req_header *hdr = (struct ctdb_req_header *)data; struct ctdb_queue_pkt *pkt; uint32_t length2, full_length; if (queue->alignment) { /* enforce the length and alignment rules from the tcp packet allocator */ length2 = (length+(queue->alignment-1)) & ~(queue->alignment-1); *(uint32_t *)data = length2; } else { length2 = length; } if (length2 != length) { memset(data+length, 0, length2-length); } full_length = length2; /* if the queue is empty then try an immediate write, avoiding queue overhead. This relies on non-blocking sockets */ if (queue->out_queue == NULL && queue->fd != -1 && !(queue->ctdb->flags & CTDB_FLAG_TORTURE)) { ssize_t n = write(queue->fd, data, length2); if (n == -1 && errno != EAGAIN && errno != EWOULDBLOCK) { talloc_free(queue->fde); queue->fde = NULL; queue->fd = -1; tevent_schedule_immediate(queue->im, queue->ctdb->ev, queue_dead, queue); /* yes, we report success, as the dead node is handled via a separate event */ return 0; } if (n > 0) { data += n; length2 -= n; } if (length2 == 0) return 0; } pkt = talloc_size( queue, offsetof(struct ctdb_queue_pkt, buf) + length2); CTDB_NO_MEMORY(queue->ctdb, pkt); talloc_set_name_const(pkt, "struct ctdb_queue_pkt"); pkt->data = pkt->buf; memcpy(pkt->data, data, length2); pkt->length = length2; pkt->full_length = full_length; if (queue->out_queue == NULL && queue->fd != -1) { TEVENT_FD_WRITEABLE(queue->fde); } DLIST_ADD_END(queue->out_queue, pkt, NULL); queue->out_queue_length++; if (queue->ctdb->tunable.verbose_memory_names != 0) { switch (hdr->operation) { case CTDB_REQ_CONTROL: { struct ctdb_req_control_old *c = (struct ctdb_req_control_old *)hdr; talloc_set_name(pkt, "ctdb_queue_pkt: %s control opcode=%u srvid=%llu datalen=%u", queue->name, (unsigned)c->opcode, (unsigned long long)c->srvid, (unsigned)c->datalen); break; } case CTDB_REQ_MESSAGE: { struct ctdb_req_message_old *m = (struct ctdb_req_message_old *)hdr; talloc_set_name(pkt, "ctdb_queue_pkt: %s message srvid=%llu datalen=%u", queue->name, (unsigned long long)m->srvid, (unsigned)m->datalen); break; } default: talloc_set_name(pkt, "ctdb_queue_pkt: %s operation=%u length=%u src=%u dest=%u", queue->name, (unsigned)hdr->operation, (unsigned)hdr->length, (unsigned)hdr->srcnode, (unsigned)hdr->destnode); break; } } return 0; }
/** * Start the loading of @tracee. This function returns no error since * it's either too late to do anything useful (the calling process is * already replaced) or the error reported by the kernel * (syscall_result < 0) will be propagated as-is. */ void translate_execve_exit(Tracee *tracee) { word_t syscall_result; int status; if (IS_NOTIFICATION_PTRACED_LOAD_DONE(tracee)) { /* Be sure not to confuse the ptracer with an * unexpected syscall/returned value. */ poke_reg(tracee, SYSARG_RESULT, 0); set_sysnum(tracee, PR_execve); /* According to most ABIs, all registers have * undefined values at program startup except: * * - the stack pointer * - the instruction pointer * - the rtld_fini pointer * - the state flags */ poke_reg(tracee, STACK_POINTER, peek_reg(tracee, ORIGINAL, SYSARG_2)); poke_reg(tracee, INSTR_POINTER, peek_reg(tracee, ORIGINAL, SYSARG_3)); poke_reg(tracee, RTLD_FINI, 0); poke_reg(tracee, STATE_FLAGS, 0); /* Restore registers to their current values. */ save_current_regs(tracee, ORIGINAL); tracee->_regs_were_changed = true; /* This is is required to make GDB work correctly * under PRoot, however it deserves to be used * unconditionally. */ (void) bind_proc_pid_auxv(tracee); /* If the PTRACE_O_TRACEEXEC option is *not* in effect * for the execing tracee, the kernel delivers an * extra SIGTRAP to the tracee after execve(2) * *returns*. This is an ordinary signal (similar to * one which can be generated by "kill -TRAP"), not a * special kind of ptrace-stop. Employing * PTRACE_GETSIGINFO for this signal returns si_code * set to 0 (SI_USER). This signal may be blocked by * signal mask, and thus may be delivered (much) * later. -- man 2 ptrace * * This signal is delayed so far since the program was * not fully loaded yet; GDB would get "invalid * adress" errors otherwise. */ if ((tracee->as_ptracee.options & PTRACE_O_TRACEEXEC) == 0) kill(tracee->pid, SIGTRAP); return; } syscall_result = peek_reg(tracee, CURRENT, SYSARG_RESULT); if ((int) syscall_result < 0) return; /* Execve happened; commit the new "/proc/self/exe". */ if (tracee->new_exe != NULL) { (void) talloc_unlink(tracee, tracee->exe); tracee->exe = talloc_reference(tracee, tracee->new_exe); talloc_set_name_const(tracee->exe, "$exe"); } /* New processes have no heap. */ bzero(tracee->heap, sizeof(Heap)); /* Transfer the load script to the loader. */ status = transfer_load_script(tracee); if (status < 0) note(tracee, ERROR, INTERNAL, "can't transfer load script: %s", strerror(-status)); return; }
const Object_Class* OBJECT_CLASS_PTR(Object) { static Object_Class the_class = { .magic = CLASS_MAGIC, .name = "Object", .super = NULL, .size = sizeof (Object), .initializer = NULL, .finalize = NULL, }; static const Object the_default_object = { ._.isa = &the_class }; if (the_class.initializer == NULL) { _ObjectClass_Lock(); the_class.initializer = &the_default_object; _ObjectClass_Unlock(); } return &the_class; } const Object_Class* OBJECT_BASE_CLASS_PTR(Object) { return OBJECT_CLASS_PTR(Object); } /***************************************************************************** * _Object_check_alloc *****************************************************************************/ static const char* const NAME_UNDER_CONSTRUCTION = "under construction"; Object* _Object_check_alloc (void* talloc_context, const Object_Class* isa) { /* * 1) check if we have a "real" context, or an object already * allocated and under construction. */ if (talloc_get_name (talloc_context) == NAME_UNDER_CONSTRUCTION) { return talloc_context; // ----------> } /* * 2) Allocate a new object */ if (isa == NULL) { Log_Print (LOG_ERROR, "Object CreateBase NULL isa class"); return NULL; // ----------> } Object* obj = talloc_named_const (talloc_context, isa->size, NAME_UNDER_CONSTRUCTION); if (obj == NULL) { Log_Print (LOG_ERROR, "Object CreateBase Out of Memory"); return NULL; // ----------> } // Init fields to default values if (isa->initializer) memcpy (obj, isa->initializer, isa->size); _OBJECT_SET_CLASS (obj, isa); // Register destructor talloc_set_destructor (obj, destroy); return obj; } /***************************************************************************** * Object_Create *****************************************************************************/ Object* Object_Create (void* parent_context, void* unused) { (void) unused; Object* self = _Object_check_alloc (parent_context, OBJECT_BASE_CLASS_PTR (Object)); // Finalize construction if (self != NULL) talloc_set_name_const (self, OBJECT_GET_CLASS_NAME (self)); return self; }