Ejemplo n.º 1
0
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);
}
Ejemplo n.º 2
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);
}
Ejemplo n.º 3
0
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);
}
Ejemplo n.º 4
0
/**
 * 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;
}
Ejemplo n.º 5
0
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);
}
Ejemplo n.º 6
0
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);
}
Ejemplo n.º 7
0
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);
}
Ejemplo n.º 8
0
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;
}
Ejemplo n.º 9
0
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);
}
Ejemplo n.º 10
0
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;
}
Ejemplo n.º 11
0
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;
}
Ejemplo n.º 12
0
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;
}
Ejemplo n.º 13
0
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;
}
Ejemplo n.º 14
0
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;
}
Ejemplo n.º 15
0
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);
    }
}