void test_local (void) { void *parent; void *_ptr; TEST_GROUP ("nih_local"); /* Make sure that when a variable goes out of scope, it's freed. */ TEST_FEATURE ("with variable going out of scope"); do { nih_local void *ptr; ptr = nih_alloc (NULL, 100); nih_alloc_set_destructor (ptr, destructor_called); destructor_was_called = 0; } while (0); TEST_TRUE (destructor_was_called); /* Make sure that if a variable is referenced while in scope, it * is not freed. */ TEST_FEATURE ("with referenced variable"); parent = nih_alloc (NULL, 100); do { nih_local void *ptr; ptr = nih_alloc (NULL, 100); nih_ref (ptr, parent); _ptr = ptr; nih_alloc_set_destructor (ptr, destructor_called); destructor_was_called = 0; } while (0); TEST_FALSE (destructor_was_called); TEST_ALLOC_PARENT (_ptr, parent); nih_free (parent); /* Make sure we don't need to allocate the variable. */ TEST_FEATURE ("with NULL variable"); do { nih_local void *ptr = NULL; } while (0); }
void test_parent (void) { void *ptr1; void *ptr2; void *ptr3; TEST_FUNCTION ("nih_alloc_parent"); /* Check that nih_alloc_parent returns TRUE when the passed object * is a child of the passed parent. */ TEST_FEATURE ("with child and parent"); ptr1 = nih_alloc (NULL, 10); ptr2 = nih_alloc (ptr1, 10); TEST_TRUE (nih_alloc_parent (ptr2, ptr1)); nih_free (ptr1); /* Check that nih_alloc_parent returns TRUE when the passed object * is a child of the NULL parent. */ TEST_FEATURE ("with child and NULL parent"); ptr1 = nih_alloc (NULL, 10); TEST_TRUE (nih_alloc_parent (ptr1, NULL)); nih_free (ptr1); /* Check that nih_alloc_parent returns FALSE when the passed object * is a child but not of the passed parent. */ TEST_FEATURE ("with child and wrong parent"); ptr1 = nih_alloc (NULL, 10); ptr2 = nih_alloc (ptr1, 10); ptr3 = nih_alloc (NULL, 10); TEST_FALSE (nih_alloc_parent (ptr2, ptr3)); nih_free (ptr1); nih_free (ptr3); /* Check that nih_alloc_parent returns FALSE when the passed object * is an orphan. */ TEST_FEATURE ("with orphan"); ptr1 = nih_alloc (NULL, 10); ptr2 = nih_alloc (NULL, 10); TEST_FALSE (nih_alloc_parent (ptr2, ptr1)); nih_free (ptr1); nih_free (ptr2); }
void test_alloc (void) { void *ptr1; void *ptr2; TEST_FUNCTION ("nih_alloc"); /* Check allocation remembers the size, and is possible without * a parent. */ TEST_FEATURE ("with no parent"); ptr1 = nih_alloc (NULL, 8096); memset (ptr1, 'x', 8096); TEST_ALLOC_SIZE (ptr1, 8096); TEST_ALLOC_PARENT (ptr1, NULL); /* Check that allocation with a parent remembers the parent */ TEST_FEATURE ("with a parent"); ptr2 = nih_alloc (ptr1, 10); memset (ptr2, 'x', 10); TEST_ALLOC_SIZE (ptr2, 10); TEST_ALLOC_PARENT (ptr2, ptr1); nih_free (ptr1); /* Check that nih_alloc returns NULL if allocation fails. */ TEST_FEATURE ("with failed allocation"); __nih_malloc = malloc_null; ptr1 = nih_new (NULL, int); __nih_malloc = malloc; TEST_EQ_P (ptr1, NULL); }
/** * make_safe_string: * @parent: parent, * @original: original string. * * Strip non-printable and non-blank bytes from specified string. * * Notes: * * Sadly, this is necessary as some hardware (such as battery devices) * exposes non-printable bytes in their descriptive registers to the * kernel. Since neither the kernel nor udev specify any encoding for * udev messages, these (probably bogus) bytes get passed up to userland * to deal with. This is sub-optimal since it implies that _every_ * application that processes udev messages must perform its own * sanitizing on the messages. Let's just hope they all deal with the * problem in the same way... * * Note that *iff* the kernel/udev did specify an encoding model, this * problem could go away since one of the lower layers could then * detect the out-of-bound data and deal with it at source. All instances * of this issue seen so far seem to indicate the binary control data * being presented by the hardware is in fact bogus ("corruption") and * looks like some block of memory has not been initialized correctly. * * The approach taken here is to simulate the approach already adopted * by 'upower' (up_device_supply_make_safe_string()), with the exception * that we also allow blank characters (such as tabs). * * Returns a copy of @original stripped of all non-printable and * non-blank characters, or NULL if insufficient memory. **/ char * make_safe_string (const void *parent, const char *original) { size_t len; size_t i, j; char *cleaned; nih_assert (original); len = strlen (original); cleaned = nih_alloc (parent, len + 1); if (! cleaned) return NULL; for (i=0, j=0; i < len; ) { /* Skip over bogus bytes */ if (! (isprint (original[i]) || isblank (original[i]))) { i++; continue; } /* Copy what remains */ cleaned[j] = original[i]; i++; j++; } /* Terminate */ cleaned[j] = '\0'; if (i != j) nih_debug ("removed unexpected bytes from udev message data"); /* Note that strictly we should realloc the string if * bogus bytes were found (since it will now be shorter). * However, since all the strings are short (and short-lived) we * do not do this to avoid the associated overhead. */ return cleaned; }
void test_unref (void) { void *ptr1; void *ptr2; void *ptr3; TEST_FUNCTION ("nih_unref"); /* Check that we can remove a reference from an object with multiple * parents, which means the object will not be freed. */ TEST_FEATURE ("with multiple parents"); ptr1 = nih_alloc (NULL, 100); memset (ptr1, 'x', 100); ptr2 = nih_alloc (ptr1, 100); memset (ptr2, 'y', 100); ptr3 = nih_alloc (NULL, 100); memset (ptr2, 'z', 100); nih_ref (ptr2, ptr3); nih_alloc_set_destructor (ptr2, destructor_called); destructor_was_called = 0; nih_unref (ptr2, ptr1); TEST_FALSE (destructor_was_called); TEST_ALLOC_PARENT (ptr2, ptr3); nih_free (ptr1); nih_free (ptr3); /* Check that when we remove the last reference from an object, * the object is freed. */ TEST_FEATURE ("with last parent"); ptr1 = nih_alloc (NULL, 100); memset (ptr1, 'x', 100); ptr2 = nih_alloc (ptr1, 100); memset (ptr2, 'y', 100); nih_alloc_set_destructor (ptr2, destructor_called); destructor_was_called = 0; nih_unref (ptr2, ptr1); TEST_TRUE (destructor_was_called); nih_free (ptr1); /* Check that we have to remove the NULL reference from an object * for it to be freed. */ TEST_FEATURE ("with only NULL parent"); ptr1 = nih_alloc (NULL, 100); memset (ptr1, 'x', 100); nih_alloc_set_destructor (ptr1, destructor_called); destructor_was_called = 0; nih_unref (ptr1, NULL); TEST_TRUE (destructor_was_called); /* Check that we can remove the NULL reference leaving a reference * to a different object. */ TEST_FEATURE ("with no parent and other parent"); ptr1 = nih_alloc (NULL, 100); memset (ptr1, 'x', 100); ptr2 = nih_alloc (NULL, 100); memset (ptr2, 'y', 100); nih_ref (ptr2, ptr1); nih_alloc_set_destructor (ptr2, destructor_called); destructor_was_called = 0; nih_unref (ptr2, NULL); TEST_FALSE (destructor_was_called); TEST_ALLOC_PARENT (ptr2, ptr1); TEST_FALSE (nih_alloc_parent (ptr2, NULL)); nih_free (ptr1); /* Check that an object with multiple NULL references must have * them both removed before it will be freed. */ TEST_FEATURE ("with multiple NULL parents"); ptr1 = nih_alloc (NULL, 100); memset (ptr1, 'x', 100); nih_ref (ptr1, NULL); nih_alloc_set_destructor (ptr1, destructor_called); destructor_was_called = 0; nih_unref (ptr1, NULL); TEST_FALSE (destructor_was_called); nih_unref (ptr1, NULL); TEST_TRUE (destructor_was_called); /* Check that an object with multiple identical references must have * them both removed before it will be freed. */ TEST_FEATURE ("with multiple identical parents"); ptr1 = nih_alloc (NULL, 100); memset (ptr1, 'x', 100); ptr2 = nih_alloc (ptr1, 100); memset (ptr2, 'y', 100); nih_ref (ptr2, ptr1); nih_alloc_set_destructor (ptr2, destructor_called); destructor_was_called = 0; nih_unref (ptr2, ptr1); TEST_FALSE (destructor_was_called); nih_unref (ptr2, ptr1); TEST_TRUE (destructor_was_called); nih_free (ptr1); }
void test_ref (void) { void *ptr1; void *ptr2; void *ptr3; TEST_FUNCTION ("nih_ref"); /* Check that we can add a reference to an object that has no * parent, and this does not remove the NULL reference. */ TEST_FEATURE ("with no parent"); ptr1 = nih_alloc (NULL, 100); memset (ptr1, 'x', 100); ptr2 = nih_alloc (NULL, 100); memset (ptr2, 'y', 100); nih_ref (ptr1, ptr2); TEST_ALLOC_PARENT (ptr1, ptr2); TEST_ALLOC_PARENT (ptr1, NULL); nih_free (ptr1); nih_free (ptr2); /* Check that we can add a reference to an object that already has * a parent, and that both shall be parents afterwards. */ TEST_FEATURE ("with existing parent"); ptr1 = nih_alloc (NULL, 100); memset (ptr1, 'x', 100); ptr2 = nih_alloc (ptr1, 100); memset (ptr2, 'y', 100); ptr3 = nih_alloc (NULL, 100); memset (ptr2, 'z', 100); nih_ref (ptr2, ptr3); TEST_ALLOC_PARENT (ptr2, ptr1); TEST_ALLOC_PARENT (ptr2, ptr3); nih_free (ptr1); nih_free (ptr3); /* Check that we can add a new NULL reference to an object that * already has a parent, and that both shall be parents afterwards. */ TEST_FEATURE ("with existing parent and new NULL"); ptr1 = nih_alloc (NULL, 100); memset (ptr1, 'x', 100); ptr2 = nih_alloc (ptr1, 100); memset (ptr2, 'y', 100); nih_ref (ptr2, NULL); TEST_ALLOC_PARENT (ptr2, ptr1); TEST_ALLOC_PARENT (ptr2, NULL); nih_free (ptr1); nih_free (ptr2); /* Check that we can add a second NULL reference to an object that * already has one. */ TEST_FEATURE ("with additional NULL parent"); ptr1 = nih_alloc (NULL, 100); memset (ptr1, 'x', 100); nih_ref (ptr1, NULL); TEST_ALLOC_PARENT (ptr1, NULL); nih_free (ptr1); /* Check that we can add a second reference to an object that already * has a reference from the same parent. */ TEST_FEATURE ("with additional existing parent"); ptr1 = nih_alloc (NULL, 100); memset (ptr1, 'x', 100); ptr2 = nih_alloc (ptr1, 100); memset (ptr2, 'y', 100); nih_ref (ptr2, ptr1); TEST_ALLOC_PARENT (ptr2, ptr1); nih_free (ptr2); nih_free (ptr1); }
void test_discard (void) { void *ptr1; void *ptr2; int ret; TEST_FUNCTION ("nih_discard"); /* Check that nih_discard works if the block has no parent, freeing * the object. The destructor should get called and nih_discard * should return that return value. */ TEST_FEATURE ("with no parent"); ptr1 = nih_alloc (NULL, 10); nih_alloc_set_destructor (ptr1, destructor_called); destructor_was_called = 0; ret = nih_discard (ptr1); TEST_TRUE (destructor_was_called); TEST_EQ (ret, 2); /* Check that nih_discard does nothing it the block has a parent. */ TEST_FEATURE ("with parent"); ptr2 = nih_alloc (NULL, 20); ptr1 = nih_alloc (ptr2, 10); nih_alloc_set_destructor (ptr1, destructor_called); destructor_was_called = 0; ret = nih_discard (ptr1); TEST_FALSE (destructor_was_called); TEST_EQ (ret, 0); nih_free (ptr2); /* Check that the destructor on any children also gets called, which * is as good a indication as any that the children are being freed. */ TEST_FEATURE ("with destructor on child"); ptr1 = nih_alloc (NULL, 10); ptr2 = nih_alloc (ptr1, 10); nih_alloc_set_destructor (ptr2, child_destructor_called); child_destructor_was_called = 0; ret = nih_discard (ptr1); TEST_TRUE (child_destructor_was_called); TEST_EQ (ret, 0); /* Check that both destructors on parent and children are called, * and that the return value from nih_discard is that of the parent's. */ TEST_FEATURE ("with child and destructors"); ptr1 = nih_alloc (NULL, 10); ptr2 = nih_alloc (ptr1, 10); nih_alloc_set_destructor (ptr1, destructor_called); nih_alloc_set_destructor (ptr2, child_destructor_called); destructor_was_called = 0; child_destructor_was_called = 0; ret = nih_discard (ptr1); TEST_TRUE (destructor_was_called); TEST_TRUE (child_destructor_was_called); TEST_EQ (ret, 2); }
void test_free (void) { void * ptr1; void * ptr2; Parent *parent; int ret; TEST_FUNCTION ("nih_free"); /* Check that nih_free works if the block has no parent. The * destructor should get called and nih_free should return that * return value. */ TEST_FEATURE ("with no parent"); ptr1 = nih_alloc (NULL, 10); nih_alloc_set_destructor (ptr1, destructor_called); destructor_was_called = 0; ret = nih_free (ptr1); TEST_TRUE (destructor_was_called); TEST_EQ (ret, 2); /* Check that nih_free works if the block has a parent. The * destructor should get called and nih_free should return that * return value. */ TEST_FEATURE ("with parent"); ptr2 = nih_alloc (NULL, 20); ptr1 = nih_alloc (ptr2, 10); nih_alloc_set_destructor (ptr1, destructor_called); destructor_was_called = 0; ret = nih_free (ptr1); TEST_TRUE (destructor_was_called); TEST_EQ (ret, 2); nih_free (ptr2); /* Check that the destructor on any children also gets called, which * is as good a indication as any that the children are being freed. */ TEST_FEATURE ("with destructor on child"); ptr1 = nih_alloc (NULL, 10); ptr2 = nih_alloc (ptr1, 10); nih_alloc_set_destructor (ptr2, child_destructor_called); child_destructor_was_called = 0; ret = nih_free (ptr1); TEST_TRUE (child_destructor_was_called); TEST_EQ (ret, 0); /* Check that both destructors on parent and children are called, * and that the return value from nih_free is that of the parent's. */ TEST_FEATURE ("with child and destructors"); ptr1 = nih_alloc (NULL, 10); ptr2 = nih_alloc (ptr1, 10); nih_alloc_set_destructor (ptr1, destructor_called); nih_alloc_set_destructor (ptr2, child_destructor_called); destructor_was_called = 0; child_destructor_was_called = 0; ret = nih_free (ptr1); TEST_TRUE (destructor_was_called); TEST_TRUE (child_destructor_was_called); TEST_EQ (ret, 2); /* Check that a child of an object may be included in a sibling * linked list allocated earlier. At the point the child destructor * is called, the sibling must not have been freed otherwise it * cannot cut itself out. */ TEST_FEATURE ("with child in older sibling list"); parent = nih_new (NULL, Parent); __nih_malloc = my_list_head_malloc; parent->list = nih_new (parent, NihList); nih_list_init (parent->list); __nih_malloc = malloc; parent->child = nih_new (parent, Child); nih_list_init (&parent->child->entry); nih_list_add (parent->list, &parent->child->entry); nih_alloc_set_destructor (parent->child, child_destructor_test); __nih_free = my_list_head_free; nih_free (parent); __nih_free = free; /* Check that a child of an object may be included in a sibling * linked list allocated later. At the point the child destructor * is called, the sibling must not have been freed otherwise it * cannot cut itself out. */ TEST_FEATURE ("with child in younger sibling list"); parent = nih_new (NULL, Parent); parent->child = nih_new (parent, Child); nih_list_init (&parent->child->entry); __nih_malloc = my_list_head_malloc; parent->list = nih_new (parent, NihList); nih_list_init (parent->list); __nih_malloc = malloc; nih_list_add (parent->list, &parent->child->entry); nih_alloc_set_destructor (parent->child, child_destructor_test); __nih_free = my_list_head_free; nih_free (parent); __nih_free = free; }
void test_realloc (void) { void *ptr1; void *ptr2; void *ptr3; TEST_FUNCTION ("nih_realloc"); /* Check that nih_realloc behaves like nih_alloc if the pointer is * NULL (it should, in fact, just call it) */ TEST_FEATURE ("as nih_alloc"); ptr1 = nih_realloc (NULL, NULL, 4096); memset (ptr1, 'x', 4096); TEST_ALLOC_SIZE (ptr1, 4096); TEST_ALLOC_PARENT (ptr1, NULL); nih_free (ptr1); /* Check that nih_realloc works if the block doesn't have a parent. */ TEST_FEATURE ("with no parent"); ptr1 = nih_alloc (NULL, 4096); memset (ptr1, 'x', 4096); ptr1 = nih_realloc (ptr1, NULL, 8096); memset (ptr1, 'x', 8096); TEST_ALLOC_SIZE (ptr1, 8096); TEST_ALLOC_PARENT (ptr1, NULL); /* Check that nih_realloc works if the block has a parent, the size * should change but the parent should remain the same. */ TEST_FEATURE ("with a parent"); ptr2 = nih_alloc (ptr1, 5); memset (ptr2, 'x', 5); ptr2 = nih_realloc (ptr2, ptr1, 10); memset (ptr2, 'x', 10); TEST_ALLOC_SIZE (ptr2, 10); TEST_ALLOC_PARENT (ptr2, ptr1); nih_free (ptr1); /* Check that nih_realloc works if the block being reallocated has * a child. This is fiddly as they need their parent pointers * adjusted. */ TEST_FEATURE ("with a child"); ptr1 = nih_alloc (NULL, 128); memset (ptr1, 'x', 128); ptr2 = nih_alloc (ptr1, 512); memset (ptr2, 'x', 512); ptr3 = nih_realloc (ptr1, NULL, 1024); memset (ptr3, 'x', 1024); TEST_ALLOC_PARENT (ptr2, ptr3); nih_free (ptr3); /* Check that nih_realloc returns NULL and doesn't alter the block * if the allocator fails. */ TEST_FEATURE ("with failing realloc"); ptr1 = nih_alloc (NULL, 10); assert (ptr1); memset (ptr1, 'x', 10); __nih_realloc = realloc_null; ptr2 = nih_realloc (ptr1, NULL, 200); __nih_realloc = realloc; TEST_EQ_P (ptr2, NULL); TEST_ALLOC_SIZE (ptr1, 10); nih_free (ptr1); }
int list_children_main (void *parent, char *controller, const char *cgroup, struct ucred p, struct ucred r, char ***output) { DBusMessage *message; DBusMessageIter iter; int sv[2], ret = -1; uint32_t len; int32_t nrkids; nih_local char * paths = NULL; char *s; int i; *output = NULL; if (memcmp(&p, &r, sizeof(struct ucred)) != 0) { nih_error("%s: proxy != requestor", __func__); return -1; } if (!sane_cgroup(cgroup)) { nih_error("%s: unsafe cgroup", __func__); return -1; } if (!(message = start_dbus_request("ListChildrenScm", sv))) { nih_error("%s: error starting dbus request", __func__); return -1; } dbus_message_iter_init_append(message, &iter); if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &controller)) { nih_error("%s: out of memory", __func__); dbus_message_unref(message); goto out; } if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &cgroup)) { nih_error("%s: out of memory", __func__); dbus_message_unref(message); goto out; } if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_UNIX_FD, &sv[1])) { nih_error("%s: out of memory", __func__); dbus_message_unref(message); goto out; } if (!complete_dbus_request(message, sv, &r, NULL)) { nih_error("%s: error completing dbus request", __func__); goto out; } if (proxyrecv(sv[0], &nrkids, sizeof(int32_t)) != sizeof(int32_t)) goto out; if (nrkids == 0) { ret = 0; goto out; } if (nrkids < 0) { nih_error("%s: Server encountered an error: bad cgroup?", __func__); ret = -1; goto out; } if (proxyrecv(sv[0], &len, sizeof(uint32_t)) != sizeof(uint32_t)) goto out; paths = nih_alloc(NULL, len+1); paths[len] = '\0'; if (read(sv[0], paths, len) != len) { nih_error("%s: Failed getting paths from server", __func__); goto out; } *output = NIH_MUST( nih_alloc(parent, sizeof( char*)*(nrkids+1)) ); memset(*output, 0, (nrkids + 1) * sizeof(char *)); s = paths; for (i=0; i<nrkids; i++) { if (s > paths + len) { ret = -1; nih_error("%s: corrupted result from cgmanager", __func__); goto out; } (*output)[i] = NIH_MUST( nih_strdup(parent, s) ); s += strlen(s) + 1; } ret = nrkids; out: close(sv[0]); close(sv[1]); return ret; }
int get_tasks_recursive_main (void *parent, const char *controller, const char *cgroup, struct ucred p, struct ucred r, int32_t **pids) { DBusMessage *message; DBusMessageIter iter; int sv[2], ret = -1; uint32_t nrpids; struct ucred tcred; int i; if (memcmp(&p, &r, sizeof(struct ucred)) != 0) { nih_error("%s: proxy != requestor", __func__); return -1; } if (!sane_cgroup(cgroup)) { nih_error("%s: unsafe cgroup", __func__); return -1; } if (!(message = start_dbus_request("GetTasksRecursiveScm", sv))) { nih_error("%s: error starting dbus request", __func__); return -1; } dbus_message_iter_init_append(message, &iter); if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &controller)) { nih_error("%s: out of memory", __func__); dbus_message_unref(message); goto out; } if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &cgroup)) { nih_error("%s: out of memory", __func__); dbus_message_unref(message); goto out; } if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_UNIX_FD, &sv[1])) { nih_error("%s: out of memory", __func__); dbus_message_unref(message); goto out; } if (!complete_dbus_request(message, sv, &r, NULL)) { nih_error("%s: error completing dbus request", __func__); goto out; } if (proxyrecv(sv[0], &nrpids, sizeof(uint32_t)) != sizeof(uint32_t)) goto out; if (nrpids == -1) { nih_error("%s: bad cgroup: %s:%s", __func__, controller, cgroup); ret = -1; goto out; } if (nrpids == 0) { ret = 0; goto out; } *pids = NIH_MUST( nih_alloc(parent, nrpids * sizeof(uint32_t)) ); for (i=0; i<nrpids; i++) { get_scm_creds_sync(sv[0], &tcred); if (tcred.pid == -1) { nih_warn("%s: Failed getting pid from server", __func__); goto out; } (*pids)[i] = tcred.pid; } ret = nrpids; out: close(sv[0]); close(sv[1]); return ret; }
int list_keys_main (void *parent, char *controller, const char *cgroup, struct ucred p, struct ucred r, struct keys_return_type ***output) { DBusMessage *message; DBusMessageIter iter; int sv[2], ret = -1; uint32_t len; int32_t nrkeys; nih_local char * results = NULL; char *s; int i; *output = NULL; if (memcmp(&p, &r, sizeof(struct ucred)) != 0) { nih_error("%s: proxy != requestor", __func__); return -1; } if (!sane_cgroup(cgroup)) { nih_error("%s: unsafe cgroup", __func__); return -1; } if (!(message = start_dbus_request("ListKeysScm", sv))) { nih_error("%s: error starting dbus request", __func__); return -1; } dbus_message_iter_init_append(message, &iter); if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &controller)) { nih_error("%s: out of memory", __func__); dbus_message_unref(message); goto out; } if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &cgroup)) { nih_error("%s: out of memory", __func__); dbus_message_unref(message); goto out; } if (! dbus_message_iter_append_basic (&iter, DBUS_TYPE_UNIX_FD, &sv[1])) { nih_error("%s: out of memory", __func__); dbus_message_unref(message); goto out; } if (!complete_dbus_request(message, sv, &r, NULL)) { nih_error("%s: error completing dbus request", __func__); goto out; } if (proxyrecv(sv[0], &nrkeys, sizeof(int32_t)) != sizeof(int32_t)) goto out; if (nrkeys == 0) { ret = 0; goto out; } if (nrkeys < 0) { nih_error("%s: Server encountered an error: bad cgroup?", __func__); ret = -1; goto out; } if (proxyrecv(sv[0], &len, sizeof(uint32_t)) != sizeof(uint32_t)) goto out; results = nih_alloc(NULL, len+1); results[len] = '\0'; if (read(sv[0], results, len) != len) { nih_error("%s: Failed getting results from server", __func__); goto out; } *output = NIH_MUST( nih_alloc(parent, sizeof(**output)*(nrkeys+1)) ); memset(*output, 0, (nrkeys + 1) * sizeof(**output)); s = results; for (i=0; i<nrkeys; i++) { struct keys_return_type *tmp; char *s2 = find_eol(s); if (s2 > results + len) goto bad; *s2 = '\0'; (*output)[i] = tmp = NIH_MUST( nih_new(*output, struct keys_return_type) ); tmp->name = NIH_MUST( nih_strdup(tmp, s) ); s = s2 + 1; s2 = find_eol(s); if (s2 > results + len) goto bad; if (sscanf(s, "%u\n", &tmp->uid) != 1) goto bad; s = s2 + 1; s2 = find_eol(s); if (sscanf(s, "%u\n", &tmp->gid) != 1) goto bad; s = s2 + 1; s2 = find_eol(s); if (sscanf(s, "%u\n", &tmp->perms) != 1) goto bad; s = s2 + 1; } ret = nrkeys; out: close(sv[0]); close(sv[1]); return ret; bad: ret = -1; nih_error("%s: corrupted result from cgmanager", __func__); goto out; }
int list_controllers_main (void *parent, char ***output) { DBusMessage *message = NULL, *reply = NULL; char ** output_local = NULL; DBusError error; DBusMessageIter iter; int ret = -1; DBusMessageIter output_local_iter; size_t output_local_size; *output = NULL; message = dbus_message_new_method_call(dbus_bus_get_unique_name(server_conn), "/org/linuxcontainers/cgmanager", "org.linuxcontainers.cgmanager0_0", "ListControllers"); dbus_error_init (&error); reply = dbus_connection_send_with_reply_and_block (server_conn, message, -1, &error); if (! reply) { dbus_message_unref (message); nih_error("%s: error completing dbus request: %s %s", __func__, error.name, error.message); dbus_error_free (&error); return -1; } dbus_message_unref (message); dbus_message_iter_init (reply, &iter); if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY) goto out; dbus_message_iter_recurse (&iter, &output_local_iter); output_local_size = 0; output_local = NULL; output_local = NIH_MUST( nih_alloc (parent, sizeof (char *)) ); output_local[output_local_size] = NULL; while (dbus_message_iter_get_arg_type (&output_local_iter) != DBUS_TYPE_INVALID) { const char *output_local_element_dbus; char ** output_local_tmp; char * output_local_element; if (dbus_message_iter_get_arg_type (&output_local_iter) != DBUS_TYPE_STRING) goto out; dbus_message_iter_get_basic (&output_local_iter, &output_local_element_dbus); output_local_element = NIH_MUST( nih_strdup (output_local, output_local_element_dbus) ); dbus_message_iter_next (&output_local_iter); output_local_tmp = NIH_MUST( nih_realloc (output_local, parent, sizeof (char *) * (output_local_size + 2)) ); output_local = output_local_tmp; output_local[output_local_size] = output_local_element; output_local[output_local_size + 1] = NULL; output_local_size++; } dbus_message_iter_next (&iter); if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID) goto out; *output = output_local; ret = 0; out: if (reply) dbus_message_unref (reply); if (ret) nih_free (output_local); return ret; }
static int handle_login(const char *user) { int idx = 0, ret; int existed = 1; size_t ulen = strlen("user/") + strlen(user); size_t len = ulen + 50; // Just make sure there's room for "user/$user or an <integer>" uid_t uid = 0; gid_t gid = 0; nih_local char *cg = NIH_MUST( nih_alloc(NULL, len) ); if (!get_uid_gid(user, &uid, &gid)) { mysyslog(LOG_ERR, "failed to get uid and gid for %s\n", user); return PAM_SESSION_ERR; } memset(cg, 0, len); strcpy(cg, user); ret = snprintf(cg, len, "user/%s", user); if (ret < 0 || ret >= len) return PAM_SESSION_ERR; if (!cgm_create(cg, &existed)) { mysyslog(LOG_ERR, "failed to create cgroup %s\n", cg); return PAM_SESSION_ERR; } if (existed == 0) { if (!cgm_autoremove(cg)) { mysyslog(LOG_ERR, "Warning: failed to set autoremove on %s\n", cg); } } if (!cgm_enter(cg)) { mysyslog(LOG_ERR, "failed to enter cgroup %s\n", cg); return PAM_SESSION_ERR; } while (idx >= 0) { sprintf(cg, "%d", idx); if (!cgm_create(cg, &existed)) { mysyslog(LOG_ERR, "failed to create a user cgroup\n"); return PAM_SESSION_ERR; } if (existed == 1) { idx++; continue; } if (!cgm_chown(cg, uid, gid)) { mysyslog(LOG_ERR, "Warning: failed to chown %s\n", cg); } if (!cgm_autoremove(cg)) { mysyslog(LOG_ERR, "Warning: failed to set autoremove on %s\n", cg); } if (!cgm_enter(cg)) { mysyslog(LOG_ERR, "failed to enter user cgroup %s\n", cg); return PAM_SESSION_ERR; } break; } return PAM_SUCCESS; }
void test_array_addp (void) { char **array, **ret; char *ptr1 = NULL; char *ptr2 = NULL; size_t len; TEST_FUNCTION ("nih_str_array_addn"); /* Check that we can call the function with a NULL array pointer, * and get one allocated automatically. */ TEST_FEATURE ("with no array given"); TEST_ALLOC_FAIL { TEST_ALLOC_SAFE { ptr1 = nih_alloc (NULL, 1024); memset (ptr1, ' ', 1024); } array = NULL; len = 0; ret = nih_str_array_addp (&array, NULL, &len, ptr1); if (test_alloc_failed) { TEST_EQ_P (ret, NULL); TEST_EQ_P (array, NULL); TEST_EQ (len, 0); nih_free (ptr1); continue; } TEST_NE_P (ret, NULL); TEST_EQ (len, 1); TEST_EQ_P (array[0], ptr1); TEST_ALLOC_PARENT (array[0], array); TEST_EQ_P (array[1], NULL); nih_free (array); nih_free (ptr1); } /* Check that we can append allocated blocks to a * NULL-terminated array, and that the blocks are automatically * reparented. */ TEST_FEATURE ("with length given"); TEST_ALLOC_FAIL { TEST_ALLOC_SAFE { array = nih_str_array_new (NULL); len = 0; ptr1 = nih_alloc (NULL, 1024); memset (ptr1, ' ', 1024); } ret = nih_str_array_addp (&array, NULL, &len, ptr1); if (test_alloc_failed) { TEST_EQ_P (ret, NULL); TEST_EQ (len, 0); TEST_EQ_P (array[0], NULL); nih_free (array); nih_free (ptr1); continue; } TEST_NE_P (ret, NULL); TEST_EQ (len, 1); TEST_EQ_P (array[0], ptr1); TEST_ALLOC_PARENT (array[0], array); TEST_EQ_P (array[1], NULL); nih_free (array); nih_free (ptr1); } /* Check that we can omit the length, and have it calculated. */ TEST_FEATURE ("with no length given"); TEST_ALLOC_FAIL { TEST_ALLOC_SAFE { array = nih_str_array_new (NULL); len = 0; ptr1 = nih_alloc (NULL, 1024); memset (ptr1, ' ', 1024); assert (nih_str_array_addp (&array, NULL, NULL, ptr1)); ptr2 = nih_alloc (NULL, 512); memset (ptr2, ' ', 512); } ret = nih_str_array_addp (&array, NULL, NULL, ptr2); if (test_alloc_failed) { TEST_EQ_P (ret, NULL); TEST_EQ_P (array[0], ptr1); TEST_EQ_P (array[1], NULL); nih_free (array); nih_free (ptr1); nih_free (ptr2); continue; } TEST_NE_P (ret, NULL); TEST_EQ_P (array[0], ptr1); TEST_ALLOC_PARENT (array[0], array); TEST_EQ_P (array[1], ptr2); TEST_ALLOC_PARENT (array[0], array); TEST_EQ_P (array[2], NULL); nih_free (array); nih_free (ptr1); nih_free (ptr2); } }