diff options
Diffstat (limited to 'tools/testing/selftests/kdbus/test-monitor.c')
-rw-r--r-- | tools/testing/selftests/kdbus/test-monitor.c | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/tools/testing/selftests/kdbus/test-monitor.c b/tools/testing/selftests/kdbus/test-monitor.c new file mode 100644 index 000000000..e00d738a3 --- /dev/null +++ b/tools/testing/selftests/kdbus/test-monitor.c @@ -0,0 +1,176 @@ +#include <stdio.h> +#include <string.h> +#include <time.h> +#include <fcntl.h> +#include <stdlib.h> +#include <stddef.h> +#include <unistd.h> +#include <stdint.h> +#include <stdbool.h> +#include <errno.h> +#include <assert.h> +#include <signal.h> +#include <sys/time.h> +#include <sys/mman.h> +#include <sys/capability.h> +#include <sys/wait.h> + +#include "kdbus-util.h" +#include "kdbus-enum.h" + +#include "kdbus-util.h" +#include "kdbus-enum.h" +#include "kdbus-test.h" + +int kdbus_test_monitor(struct kdbus_test_env *env) +{ + struct kdbus_conn *monitor, *conn; + unsigned int cookie = 0xdeadbeef; + struct kdbus_msg *msg; + uint64_t offset = 0; + int ret; + + conn = kdbus_hello(env->buspath, 0, NULL, 0); + ASSERT_RETURN(conn); + + /* add matches to make sure the monitor do not trigger an item add or + * remove on connect and disconnect, respectively. + */ + ret = kdbus_add_match_id(conn, 0x1, KDBUS_ITEM_ID_ADD, + KDBUS_MATCH_ID_ANY); + ASSERT_RETURN(ret == 0); + + ret = kdbus_add_match_id(conn, 0x2, KDBUS_ITEM_ID_REMOVE, + KDBUS_MATCH_ID_ANY); + ASSERT_RETURN(ret == 0); + + /* register a monitor */ + monitor = kdbus_hello(env->buspath, KDBUS_HELLO_MONITOR, NULL, 0); + ASSERT_RETURN(monitor); + + /* make sure we did not receive a monitor connect notification */ + ret = kdbus_msg_recv(conn, &msg, &offset); + ASSERT_RETURN(ret == -EAGAIN); + + /* check that a monitor cannot acquire a name */ + ret = kdbus_name_acquire(monitor, "foo.bar.baz", NULL); + ASSERT_RETURN(ret == -EOPNOTSUPP); + + ret = kdbus_msg_send(env->conn, NULL, cookie, 0, 0, 0, conn->id); + ASSERT_RETURN(ret == 0); + + /* the recipient should have gotten the message */ + ret = kdbus_msg_recv(conn, &msg, &offset); + ASSERT_RETURN(ret == 0); + ASSERT_RETURN(msg->cookie == cookie); + kdbus_msg_free(msg); + kdbus_free(conn, offset); + + /* and so should the monitor */ + ret = kdbus_msg_recv(monitor, &msg, &offset); + ASSERT_RETURN(ret == 0); + ASSERT_RETURN(msg->cookie == cookie); + + kdbus_msg_free(msg); + kdbus_free(monitor, offset); + + /* Installing matches for monitors must fais must fail */ + ret = kdbus_add_match_empty(monitor); + ASSERT_RETURN(ret == -EOPNOTSUPP); + + cookie++; + ret = kdbus_msg_send(env->conn, NULL, cookie, 0, 0, 0, + KDBUS_DST_ID_BROADCAST); + ASSERT_RETURN(ret == 0); + + /* The monitor should get the message. */ + ret = kdbus_msg_recv_poll(monitor, 100, &msg, &offset); + ASSERT_RETURN(ret == 0); + ASSERT_RETURN(msg->cookie == cookie); + + kdbus_msg_free(msg); + kdbus_free(monitor, offset); + + /* + * Since we are the only monitor, update the attach flags + * and tell we are not interessted in attach flags recv + */ + + ret = kdbus_conn_update_attach_flags(monitor, + _KDBUS_ATTACH_ALL, + 0); + ASSERT_RETURN(ret == 0); + + cookie++; + ret = kdbus_msg_send(env->conn, NULL, cookie, 0, 0, 0, + KDBUS_DST_ID_BROADCAST); + ASSERT_RETURN(ret == 0); + + ret = kdbus_msg_recv_poll(monitor, 100, &msg, &offset); + ASSERT_RETURN(ret == 0); + ASSERT_RETURN(msg->cookie == cookie); + + ret = kdbus_item_in_message(msg, KDBUS_ITEM_TIMESTAMP); + ASSERT_RETURN(ret == 0); + + kdbus_msg_free(msg); + kdbus_free(monitor, offset); + + /* + * Now we are interested in KDBUS_ITEM_TIMESTAMP and + * KDBUS_ITEM_CREDS + */ + ret = kdbus_conn_update_attach_flags(monitor, + _KDBUS_ATTACH_ALL, + KDBUS_ATTACH_TIMESTAMP | + KDBUS_ATTACH_CREDS); + ASSERT_RETURN(ret == 0); + + cookie++; + ret = kdbus_msg_send(env->conn, NULL, cookie, 0, 0, 0, + KDBUS_DST_ID_BROADCAST); + ASSERT_RETURN(ret == 0); + + ret = kdbus_msg_recv_poll(monitor, 100, &msg, &offset); + ASSERT_RETURN(ret == 0); + ASSERT_RETURN(msg->cookie == cookie); + + ret = kdbus_item_in_message(msg, KDBUS_ITEM_TIMESTAMP); + ASSERT_RETURN(ret == 1); + + ret = kdbus_item_in_message(msg, KDBUS_ITEM_CREDS); + ASSERT_RETURN(ret == 1); + + /* the KDBUS_ITEM_PID_COMM was not requested */ + ret = kdbus_item_in_message(msg, KDBUS_ITEM_PID_COMM); + ASSERT_RETURN(ret == 0); + + kdbus_msg_free(msg); + kdbus_free(monitor, offset); + + kdbus_conn_free(monitor); + /* make sure we did not receive a monitor disconnect notification */ + ret = kdbus_msg_recv(conn, &msg, &offset); + ASSERT_RETURN(ret == -EAGAIN); + + kdbus_conn_free(conn); + + /* Make sure that monitor as unprivileged is not allowed */ + ret = test_is_capable(CAP_SETUID, CAP_SETGID, -1); + ASSERT_RETURN(ret >= 0); + + if (ret && all_uids_gids_are_mapped()) { + ret = RUN_UNPRIVILEGED(UNPRIV_UID, UNPRIV_UID, ({ + monitor = kdbus_hello(env->buspath, + KDBUS_HELLO_MONITOR, + NULL, 0); + ASSERT_EXIT(!monitor && errno == EPERM); + + _exit(EXIT_SUCCESS); + }), + ({ 0; })); + ASSERT_RETURN(ret == 0); + } + + return TEST_OK; +} |