diff options
author | André Fabian Silva Delgado <emulatorman@parabola.nu> | 2016-02-22 01:12:47 -0300 |
---|---|---|
committer | André Fabian Silva Delgado <emulatorman@parabola.nu> | 2016-02-22 01:12:47 -0300 |
commit | 6d461a4fe7896faa1aec5a5417888cf179e46b9f (patch) | |
tree | 2e0f1a0b7a5418189c8d53592d33a44d0b356fc9 /tools/testing/selftests/kdbus/test-connection.c | |
parent | 5c545e1fb127a4b11ddc5f1a5ed066b853dd1a1a (diff) |
Linux-libre 4.4.2-gnupck-4.4.2-gnu
Diffstat (limited to 'tools/testing/selftests/kdbus/test-connection.c')
-rw-r--r-- | tools/testing/selftests/kdbus/test-connection.c | 597 |
1 files changed, 0 insertions, 597 deletions
diff --git a/tools/testing/selftests/kdbus/test-connection.c b/tools/testing/selftests/kdbus/test-connection.c deleted file mode 100644 index 4688ce8ec..000000000 --- a/tools/testing/selftests/kdbus/test-connection.c +++ /dev/null @@ -1,597 +0,0 @@ -#include <stdio.h> -#include <string.h> -#include <fcntl.h> -#include <stdlib.h> -#include <stddef.h> -#include <unistd.h> -#include <stdint.h> -#include <errno.h> -#include <assert.h> -#include <limits.h> -#include <sys/types.h> -#include <sys/capability.h> -#include <sys/mman.h> -#include <sys/syscall.h> -#include <sys/wait.h> -#include <stdbool.h> - -#include "kdbus-api.h" -#include "kdbus-util.h" -#include "kdbus-enum.h" -#include "kdbus-test.h" - -int kdbus_test_hello(struct kdbus_test_env *env) -{ - struct kdbus_cmd_free cmd_free = {}; - struct kdbus_cmd_hello hello; - int fd, ret; - - memset(&hello, 0, sizeof(hello)); - - fd = open(env->buspath, O_RDWR|O_CLOEXEC); - ASSERT_RETURN(fd >= 0); - - hello.flags = KDBUS_HELLO_ACCEPT_FD; - hello.attach_flags_send = _KDBUS_ATTACH_ALL; - hello.attach_flags_recv = _KDBUS_ATTACH_ALL; - hello.size = sizeof(struct kdbus_cmd_hello); - hello.pool_size = POOL_SIZE; - - /* an unaligned hello must result in -EFAULT */ - ret = kdbus_cmd_hello(fd, (struct kdbus_cmd_hello *) ((char *) &hello + 1)); - ASSERT_RETURN(ret == -EFAULT); - - /* a size of 0 must return EMSGSIZE */ - hello.size = 1; - hello.flags = KDBUS_HELLO_ACCEPT_FD; - hello.attach_flags_send = _KDBUS_ATTACH_ALL; - ret = kdbus_cmd_hello(fd, &hello); - ASSERT_RETURN(ret == -EINVAL); - - hello.size = sizeof(struct kdbus_cmd_hello); - - /* check faulty flags */ - hello.flags = 1ULL << 32; - hello.attach_flags_send = _KDBUS_ATTACH_ALL; - ret = kdbus_cmd_hello(fd, &hello); - ASSERT_RETURN(ret == -EINVAL); - - /* check for faulty pool sizes */ - hello.pool_size = 0; - hello.flags = KDBUS_HELLO_ACCEPT_FD; - hello.attach_flags_send = _KDBUS_ATTACH_ALL; - ret = kdbus_cmd_hello(fd, &hello); - ASSERT_RETURN(ret == -EINVAL); - - hello.pool_size = 4097; - hello.attach_flags_send = _KDBUS_ATTACH_ALL; - ret = kdbus_cmd_hello(fd, &hello); - ASSERT_RETURN(ret == -EINVAL); - - hello.pool_size = POOL_SIZE; - - hello.attach_flags_send = _KDBUS_ATTACH_ALL; - hello.offset = (__u64)-1; - - /* success test */ - ret = kdbus_cmd_hello(fd, &hello); - ASSERT_RETURN(ret == 0); - - /* The kernel should have returned some items */ - ASSERT_RETURN(hello.offset != (__u64)-1); - cmd_free.size = sizeof(cmd_free); - cmd_free.offset = hello.offset; - ret = kdbus_cmd_free(fd, &cmd_free); - ASSERT_RETURN(ret >= 0); - - close(fd); - - fd = open(env->buspath, O_RDWR|O_CLOEXEC); - ASSERT_RETURN(fd >= 0); - - /* no ACTIVATOR flag without a name */ - hello.flags = KDBUS_HELLO_ACTIVATOR; - ret = kdbus_cmd_hello(fd, &hello); - ASSERT_RETURN(ret == -EINVAL); - - close(fd); - - return TEST_OK; -} - -int kdbus_test_byebye(struct kdbus_test_env *env) -{ - struct kdbus_conn *conn; - struct kdbus_cmd_recv cmd_recv = { .size = sizeof(cmd_recv) }; - struct kdbus_cmd cmd_byebye = { .size = sizeof(cmd_byebye) }; - int ret; - - /* create a 2nd connection */ - conn = kdbus_hello(env->buspath, 0, NULL, 0); - ASSERT_RETURN(conn != NULL); - - ret = kdbus_add_match_empty(conn); - ASSERT_RETURN(ret == 0); - - ret = kdbus_add_match_empty(env->conn); - ASSERT_RETURN(ret == 0); - - /* send over 1st connection */ - ret = kdbus_msg_send(env->conn, NULL, 0, 0, 0, 0, - KDBUS_DST_ID_BROADCAST); - ASSERT_RETURN(ret == 0); - - /* say byebye on the 2nd, which must fail */ - ret = kdbus_cmd_byebye(conn->fd, &cmd_byebye); - ASSERT_RETURN(ret == -EBUSY); - - /* receive the message */ - ret = kdbus_cmd_recv(conn->fd, &cmd_recv); - ASSERT_RETURN(ret == 0); - - ret = kdbus_free(conn, cmd_recv.msg.offset); - ASSERT_RETURN(ret == 0); - - /* and try again */ - ret = kdbus_cmd_byebye(conn->fd, &cmd_byebye); - ASSERT_RETURN(ret == 0); - - /* a 2nd try should result in -ECONNRESET */ - ret = kdbus_cmd_byebye(conn->fd, &cmd_byebye); - ASSERT_RETURN(ret == -ECONNRESET); - - kdbus_conn_free(conn); - - return TEST_OK; -} - -/* Get only the first item */ -static struct kdbus_item *kdbus_get_item(struct kdbus_info *info, - uint64_t type) -{ - struct kdbus_item *item; - - KDBUS_ITEM_FOREACH(item, info, items) - if (item->type == type) - return item; - - return NULL; -} - -static unsigned int kdbus_count_item(struct kdbus_info *info, - uint64_t type) -{ - unsigned int i = 0; - const struct kdbus_item *item; - - KDBUS_ITEM_FOREACH(item, info, items) - if (item->type == type) - i++; - - return i; -} - -static int kdbus_fuzz_conn_info(struct kdbus_test_env *env, int capable) -{ - int ret; - unsigned int cnt = 0; - uint64_t offset = 0; - struct kdbus_info *info; - struct kdbus_conn *conn; - struct kdbus_conn *privileged; - const struct kdbus_item *item; - uint64_t valid_flags = KDBUS_ATTACH_NAMES | - KDBUS_ATTACH_CREDS | - KDBUS_ATTACH_PIDS | - KDBUS_ATTACH_CONN_DESCRIPTION; - - uint64_t invalid_flags = KDBUS_ATTACH_NAMES | - KDBUS_ATTACH_CREDS | - KDBUS_ATTACH_PIDS | - KDBUS_ATTACH_CAPS | - KDBUS_ATTACH_CGROUP | - KDBUS_ATTACH_CONN_DESCRIPTION; - - struct kdbus_creds cached_creds; - uid_t ruid, euid, suid; - gid_t rgid, egid, sgid; - - getresuid(&ruid, &euid, &suid); - getresgid(&rgid, &egid, &sgid); - - cached_creds.uid = ruid; - cached_creds.euid = euid; - cached_creds.suid = suid; - cached_creds.fsuid = ruid; - - cached_creds.gid = rgid; - cached_creds.egid = egid; - cached_creds.sgid = sgid; - cached_creds.fsgid = rgid; - - struct kdbus_pids cached_pids = { - .pid = getpid(), - .tid = syscall(SYS_gettid), - .ppid = getppid(), - }; - - ret = kdbus_conn_info(env->conn, env->conn->id, NULL, - valid_flags, &offset); - ASSERT_RETURN(ret == 0); - - info = (struct kdbus_info *)(env->conn->buf + offset); - ASSERT_RETURN(info->id == env->conn->id); - - /* We do not have any well-known name */ - item = kdbus_get_item(info, KDBUS_ITEM_NAME); - ASSERT_RETURN(item == NULL); - - item = kdbus_get_item(info, KDBUS_ITEM_CONN_DESCRIPTION); - if (valid_flags & KDBUS_ATTACH_CONN_DESCRIPTION) { - ASSERT_RETURN(item); - } else { - ASSERT_RETURN(item == NULL); - } - - kdbus_free(env->conn, offset); - - conn = kdbus_hello(env->buspath, 0, NULL, 0); - ASSERT_RETURN(conn); - - privileged = kdbus_hello(env->buspath, 0, NULL, 0); - ASSERT_RETURN(privileged); - - ret = kdbus_conn_info(conn, conn->id, NULL, valid_flags, &offset); - ASSERT_RETURN(ret == 0); - - info = (struct kdbus_info *)(conn->buf + offset); - ASSERT_RETURN(info->id == conn->id); - - /* We do not have any well-known name */ - item = kdbus_get_item(info, KDBUS_ITEM_NAME); - ASSERT_RETURN(item == NULL); - - cnt = kdbus_count_item(info, KDBUS_ITEM_CREDS); - if (valid_flags & KDBUS_ATTACH_CREDS) { - ASSERT_RETURN(cnt == 1); - - item = kdbus_get_item(info, KDBUS_ITEM_CREDS); - ASSERT_RETURN(item); - - /* Compare received items with cached creds */ - ASSERT_RETURN(memcmp(&item->creds, &cached_creds, - sizeof(struct kdbus_creds)) == 0); - } else { - ASSERT_RETURN(cnt == 0); - } - - item = kdbus_get_item(info, KDBUS_ITEM_PIDS); - if (valid_flags & KDBUS_ATTACH_PIDS) { - ASSERT_RETURN(item); - - /* Compare item->pids with cached PIDs */ - ASSERT_RETURN(item->pids.pid == cached_pids.pid && - item->pids.tid == cached_pids.tid && - item->pids.ppid == cached_pids.ppid); - } else { - ASSERT_RETURN(item == NULL); - } - - /* We did not request KDBUS_ITEM_CAPS */ - item = kdbus_get_item(info, KDBUS_ITEM_CAPS); - ASSERT_RETURN(item == NULL); - - kdbus_free(conn, offset); - - ret = kdbus_name_acquire(conn, "com.example.a", NULL); - ASSERT_RETURN(ret >= 0); - - ret = kdbus_conn_info(conn, conn->id, NULL, valid_flags, &offset); - ASSERT_RETURN(ret == 0); - - info = (struct kdbus_info *)(conn->buf + offset); - ASSERT_RETURN(info->id == conn->id); - - item = kdbus_get_item(info, KDBUS_ITEM_OWNED_NAME); - if (valid_flags & KDBUS_ATTACH_NAMES) { - ASSERT_RETURN(item && !strcmp(item->name.name, "com.example.a")); - } else { - ASSERT_RETURN(item == NULL); - } - - kdbus_free(conn, offset); - - ret = kdbus_conn_info(conn, 0, "com.example.a", valid_flags, &offset); - ASSERT_RETURN(ret == 0); - - info = (struct kdbus_info *)(conn->buf + offset); - ASSERT_RETURN(info->id == conn->id); - - kdbus_free(conn, offset); - - /* does not have the necessary caps to drop to unprivileged */ - if (!capable) - goto continue_test; - - ret = RUN_UNPRIVILEGED(UNPRIV_UID, UNPRIV_GID, ({ - ret = kdbus_conn_info(conn, conn->id, NULL, - valid_flags, &offset); - ASSERT_EXIT(ret == 0); - - info = (struct kdbus_info *)(conn->buf + offset); - ASSERT_EXIT(info->id == conn->id); - - if (valid_flags & KDBUS_ATTACH_NAMES) { - item = kdbus_get_item(info, KDBUS_ITEM_OWNED_NAME); - ASSERT_EXIT(item && - strcmp(item->name.name, - "com.example.a") == 0); - } - - if (valid_flags & KDBUS_ATTACH_CREDS) { - item = kdbus_get_item(info, KDBUS_ITEM_CREDS); - ASSERT_EXIT(item); - - /* Compare received items with cached creds */ - ASSERT_EXIT(memcmp(&item->creds, &cached_creds, - sizeof(struct kdbus_creds)) == 0); - } - - if (valid_flags & KDBUS_ATTACH_PIDS) { - item = kdbus_get_item(info, KDBUS_ITEM_PIDS); - ASSERT_EXIT(item); - - /* - * Compare item->pids with cached pids of - * privileged one. - * - * cmd_info will always return cached pids. - */ - ASSERT_EXIT(item->pids.pid == cached_pids.pid && - item->pids.tid == cached_pids.tid); - } - - kdbus_free(conn, offset); - - /* - * Use invalid_flags and make sure that userspace - * do not play with us. - */ - ret = kdbus_conn_info(conn, conn->id, NULL, - invalid_flags, &offset); - ASSERT_EXIT(ret == 0); - - /* - * Make sure that we return only one creds item and - * it points to the cached creds. - */ - cnt = kdbus_count_item(info, KDBUS_ITEM_CREDS); - if (invalid_flags & KDBUS_ATTACH_CREDS) { - ASSERT_EXIT(cnt == 1); - - item = kdbus_get_item(info, KDBUS_ITEM_CREDS); - ASSERT_EXIT(item); - - /* Compare received items with cached creds */ - ASSERT_EXIT(memcmp(&item->creds, &cached_creds, - sizeof(struct kdbus_creds)) == 0); - } else { - ASSERT_EXIT(cnt == 0); - } - - if (invalid_flags & KDBUS_ATTACH_PIDS) { - cnt = kdbus_count_item(info, KDBUS_ITEM_PIDS); - ASSERT_EXIT(cnt == 1); - - item = kdbus_get_item(info, KDBUS_ITEM_PIDS); - ASSERT_EXIT(item); - - /* Compare item->pids with cached pids */ - ASSERT_EXIT(item->pids.pid == cached_pids.pid && - item->pids.tid == cached_pids.tid); - } - - cnt = kdbus_count_item(info, KDBUS_ITEM_CGROUP); - if (invalid_flags & KDBUS_ATTACH_CGROUP) { - ASSERT_EXIT(cnt == 1); - } else { - ASSERT_EXIT(cnt == 0); - } - - cnt = kdbus_count_item(info, KDBUS_ITEM_CAPS); - if (invalid_flags & KDBUS_ATTACH_CAPS) { - ASSERT_EXIT(cnt == 1); - } else { - ASSERT_EXIT(cnt == 0); - } - - kdbus_free(conn, offset); - }), - ({ 0; })); - ASSERT_RETURN(ret == 0); - -continue_test: - - /* A second name */ - ret = kdbus_name_acquire(conn, "com.example.b", NULL); - ASSERT_RETURN(ret >= 0); - - ret = kdbus_conn_info(conn, conn->id, NULL, valid_flags, &offset); - ASSERT_RETURN(ret == 0); - - info = (struct kdbus_info *)(conn->buf + offset); - ASSERT_RETURN(info->id == conn->id); - - cnt = kdbus_count_item(info, KDBUS_ITEM_OWNED_NAME); - if (valid_flags & KDBUS_ATTACH_NAMES) { - ASSERT_RETURN(cnt == 2); - } else { - ASSERT_RETURN(cnt == 0); - } - - kdbus_free(conn, offset); - - ASSERT_RETURN(ret == 0); - - return 0; -} - -int kdbus_test_conn_info(struct kdbus_test_env *env) -{ - int ret; - int have_caps; - struct { - struct kdbus_cmd_info cmd_info; - - struct { - uint64_t size; - uint64_t type; - char str[64]; - } name; - } buf; - - buf.cmd_info.size = sizeof(struct kdbus_cmd_info); - buf.cmd_info.flags = 0; - buf.cmd_info.attach_flags = 0; - buf.cmd_info.id = env->conn->id; - - ret = kdbus_conn_info(env->conn, env->conn->id, NULL, 0, NULL); - ASSERT_RETURN(ret == 0); - - /* try to pass a name that is longer than the buffer's size */ - buf.name.size = KDBUS_ITEM_HEADER_SIZE + 1; - buf.name.type = KDBUS_ITEM_NAME; - strcpy(buf.name.str, "foo.bar.bla"); - - buf.cmd_info.id = 0; - buf.cmd_info.size = sizeof(buf.cmd_info) + buf.name.size; - ret = kdbus_cmd_conn_info(env->conn->fd, (struct kdbus_cmd_info *) &buf); - ASSERT_RETURN(ret == -EINVAL); - - /* Pass a non existent name */ - ret = kdbus_conn_info(env->conn, 0, "non.existent.name", 0, NULL); - ASSERT_RETURN(ret == -ESRCH); - - if (!all_uids_gids_are_mapped()) - return TEST_SKIP; - - /* Test for caps here, so we run the previous test */ - have_caps = test_is_capable(CAP_SETUID, CAP_SETGID, -1); - ASSERT_RETURN(have_caps >= 0); - - ret = kdbus_fuzz_conn_info(env, have_caps); - ASSERT_RETURN(ret == 0); - - /* Now if we have skipped some tests then let the user know */ - if (!have_caps) - return TEST_SKIP; - - return TEST_OK; -} - -int kdbus_test_conn_update(struct kdbus_test_env *env) -{ - struct kdbus_conn *conn; - struct kdbus_msg *msg; - int found = 0; - int ret; - - /* - * kdbus_hello() sets all attach flags. Receive a message by this - * connection, and make sure a timestamp item (just to pick one) is - * present. - */ - conn = kdbus_hello(env->buspath, 0, NULL, 0); - ASSERT_RETURN(conn); - - ret = kdbus_msg_send(env->conn, NULL, 0x12345678, 0, 0, 0, conn->id); - ASSERT_RETURN(ret == 0); - - ret = kdbus_msg_recv(conn, &msg, NULL); - ASSERT_RETURN(ret == 0); - - found = kdbus_item_in_message(msg, KDBUS_ITEM_TIMESTAMP); - ASSERT_RETURN(found == 1); - - kdbus_msg_free(msg); - - /* - * Now, modify the attach flags and repeat the action. The item must - * now be missing. - */ - found = 0; - - ret = kdbus_conn_update_attach_flags(conn, - _KDBUS_ATTACH_ALL, - _KDBUS_ATTACH_ALL & - ~KDBUS_ATTACH_TIMESTAMP); - ASSERT_RETURN(ret == 0); - - ret = kdbus_msg_send(env->conn, NULL, 0x12345678, 0, 0, 0, conn->id); - ASSERT_RETURN(ret == 0); - - ret = kdbus_msg_recv(conn, &msg, NULL); - ASSERT_RETURN(ret == 0); - - found = kdbus_item_in_message(msg, KDBUS_ITEM_TIMESTAMP); - ASSERT_RETURN(found == 0); - - /* Provide a bogus attach_flags value */ - ret = kdbus_conn_update_attach_flags(conn, - _KDBUS_ATTACH_ALL + 1, - _KDBUS_ATTACH_ALL); - ASSERT_RETURN(ret == -EINVAL); - - kdbus_msg_free(msg); - - kdbus_conn_free(conn); - - return TEST_OK; -} - -int kdbus_test_writable_pool(struct kdbus_test_env *env) -{ - struct kdbus_cmd_free cmd_free = {}; - struct kdbus_cmd_hello hello; - int fd, ret; - void *map; - - fd = open(env->buspath, O_RDWR | O_CLOEXEC); - ASSERT_RETURN(fd >= 0); - - memset(&hello, 0, sizeof(hello)); - hello.flags = KDBUS_HELLO_ACCEPT_FD; - hello.attach_flags_send = _KDBUS_ATTACH_ALL; - hello.attach_flags_recv = _KDBUS_ATTACH_ALL; - hello.size = sizeof(struct kdbus_cmd_hello); - hello.pool_size = POOL_SIZE; - hello.offset = (__u64)-1; - - /* success test */ - ret = kdbus_cmd_hello(fd, &hello); - ASSERT_RETURN(ret == 0); - - /* The kernel should have returned some items */ - ASSERT_RETURN(hello.offset != (__u64)-1); - cmd_free.size = sizeof(cmd_free); - cmd_free.offset = hello.offset; - ret = kdbus_cmd_free(fd, &cmd_free); - ASSERT_RETURN(ret >= 0); - - /* pools cannot be mapped writable */ - map = mmap(NULL, POOL_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - ASSERT_RETURN(map == MAP_FAILED); - - /* pools can always be mapped readable */ - map = mmap(NULL, POOL_SIZE, PROT_READ, MAP_SHARED, fd, 0); - ASSERT_RETURN(map != MAP_FAILED); - - /* make sure we cannot change protection masks to writable */ - ret = mprotect(map, POOL_SIZE, PROT_READ | PROT_WRITE); - ASSERT_RETURN(ret < 0); - - munmap(map, POOL_SIZE); - close(fd); - - return TEST_OK; -} |