kdbus: test suite changed to common format
[platform/kernel/linux-rpi.git] / tools / testing / selftests / kdbus / test-metadata-ns.c
index 395a3fa..6b02ba7 100644 (file)
@@ -55,35 +55,25 @@ static struct kdbus_item *kdbus_get_item(struct kdbus_msg *msg,
        return NULL;
 }
 
-static int kdbus_match_kdbus_creds(struct kdbus_msg *msg,
+static wur int kdbus_match_kdbus_creds(struct kdbus_msg *msg,
                                   const struct kdbus_creds *expected_creds)
 {
        struct kdbus_item *item;
-
-       item = kdbus_get_item(msg, KDBUS_ITEM_CREDS);
-       ASSERT_RETURN(item);
-
-       ASSERT_RETURN(memcmp(&item->creds, expected_creds,
-                            sizeof(struct kdbus_creds)) == 0);
-
+       ASSERT_NONZERO(item = kdbus_get_item(msg, KDBUS_ITEM_CREDS));
+       ASSERT_ZERO(memcmp(&item->creds, expected_creds, sizeof(struct kdbus_creds)));
        return 0;
 }
 
-static int kdbus_match_kdbus_pids(struct kdbus_msg *msg,
+static wur int kdbus_match_kdbus_pids(struct kdbus_msg *msg,
                                  const struct kdbus_pids *expected_pids)
 {
        struct kdbus_item *item;
-
-       item = kdbus_get_item(msg, KDBUS_ITEM_PIDS);
-       ASSERT_RETURN(item);
-
-       ASSERT_RETURN(memcmp(&item->pids, expected_pids,
-                            sizeof(struct kdbus_pids)) == 0);
-
+       ASSERT_NONZERO(item = kdbus_get_item(msg, KDBUS_ITEM_PIDS));
+       ASSERT_ZERO(memcmp(&item->pids, expected_pids, sizeof(struct kdbus_pids)));
        return 0;
 }
 
-static int __kdbus_clone_userns_test(const char *bus,
+static wur int __kdbus_clone_userns_test(const char *bus,
                                     struct kdbus_conn *conn,
                                     uint64_t grandpa_pid,
                                     int signal_fd)
@@ -100,23 +90,18 @@ static int __kdbus_clone_userns_test(const char *bus,
                .ppid = grandpa_pid,
        };
 
-       ret = drop_privileges(UNPRIV_UID, UNPRIV_GID);
-       ASSERT_EXIT(ret == 0);
+       ASSERT_EXIT_ZERO(drop_privileges(UNPRIV_UID, UNPRIV_GID));
 
-       unpriv_conn = kdbus_hello(bus, 0, NULL, 0);
-       ASSERT_EXIT(unpriv_conn);
+       ASSERT_EXIT_NONZERO(unpriv_conn = kdbus_hello(bus, 0, NULL, 0));
 
-       ret = kdbus_add_match_empty(unpriv_conn);
-       ASSERT_EXIT(ret == 0);
+       ASSERT_EXIT_ZERO(kdbus_add_match_empty(unpriv_conn));
 
        /*
         * ping privileged connection from this new unprivileged
         * one
         */
 
-       ret = kdbus_msg_send(unpriv_conn, NULL, cookie, 0, 0,
-                            0, conn->id, 0, NULL);
-       ASSERT_EXIT(ret == 0);
+       ASSERT_EXIT_ZERO(kdbus_msg_send(unpriv_conn, NULL, cookie, 0, 0, 0, conn->id));
 
        /*
         * Since we just dropped privileges, the dumpable flag
@@ -130,8 +115,7 @@ static int __kdbus_clone_userns_test(const char *bus,
         * Using this we will be able write to /proc/$clone_child/uid_map
         * as uid 65534 and map the uid 65534 to 0 inside the user namespace.
         */
-       ret = prctl(PR_SET_DUMPABLE, SUID_DUMP_USER);
-       ASSERT_EXIT(ret == 0);
+       ASSERT_EXIT_ZERO(prctl(PR_SET_DUMPABLE, SUID_DUMP_USER));
 
        /* Make child privileged in its new userns and run tests */
 
@@ -143,20 +127,16 @@ static int __kdbus_clone_userns_test(const char *bus,
                struct kdbus_conn *userns_conn;
 
                /* ping connection from the new user namespace */
-               userns_conn = kdbus_hello(bus, 0, NULL, 0);
-               ASSERT_EXIT(userns_conn);
+               ASSERT_EXIT_NONZERO(userns_conn = kdbus_hello(bus, 0, NULL, 0));
 
-               ret = kdbus_add_match_empty(userns_conn);
-               ASSERT_EXIT(ret == 0);
+               ASSERT_EXIT_ZERO(kdbus_add_match_empty(userns_conn));
 
                cookie++;
-               ret = kdbus_msg_send(userns_conn, NULL, cookie,
-                                    0, 0, 0, conn->id, 0, NULL);
-               ASSERT_EXIT(ret == 0);
+               ASSERT_EXIT_ZERO(kdbus_msg_send(userns_conn, NULL, cookie, 0, 0, 0, conn->id));
 
                /* Parent did send */
-               ret = eventfd_read(signal_fd, &event_status);
-               ASSERT_RETURN(ret >= 0 && event_status == 1);
+               ASSERT_RETURN(0,<=,eventfd_read(signal_fd, &event_status));
+               ASSERT_RETURN(event_status,==,(eventfd_t)1);
 
                /*
                 * Receive from privileged connection
@@ -164,24 +144,19 @@ static int __kdbus_clone_userns_test(const char *bus,
                kdbus_printf("Privileged → unprivileged/privileged "
                             "in its userns "
                             "(different userns and pidns):\n");
-               ret = kdbus_msg_recv_poll(userns_conn, 300, &msg, NULL);
-               ASSERT_EXIT(ret == 0);
-               ASSERT_EXIT(msg->dst_id == userns_conn->id);
+               ASSERT_EXIT_ZERO(kdbus_msg_recv_poll(userns_conn, 300, &msg, NULL));
+               ASSERT_EXIT(msg->dst_id,==,userns_conn->id);
 
-               /* Different namespaces no CAPS */
-               item = kdbus_get_item(msg, KDBUS_ITEM_CAPS);
-               ASSERT_EXIT(item == NULL);
+               ASSERT_EXIT_NONZERO(item = kdbus_get_item(msg, KDBUS_ITEM_CAPS));
 
                /* uid/gid not mapped, so we have unpriv cached creds */
-               ret = kdbus_match_kdbus_creds(msg, &unmapped_creds);
-               ASSERT_EXIT(ret == 0);
+               ASSERT_EXIT_ZERO(kdbus_match_kdbus_creds(msg, &unmapped_creds));
 
                /*
                 * Diffent pid namepsaces. This is the child pidns
                 * so it should not see its parent kdbus_pids
                 */
-               ret = kdbus_match_kdbus_pids(msg, &unmapped_pids);
-               ASSERT_EXIT(ret == 0);
+               ASSERT_EXIT_ZERO(kdbus_match_kdbus_pids(msg, &unmapped_pids));
 
                kdbus_msg_free(msg);
 
@@ -192,24 +167,19 @@ static int __kdbus_clone_userns_test(const char *bus,
                kdbus_printf("Privileged → unprivileged/privileged "
                             "in its userns "
                             "(different userns and pidns):\n");
-               ret = kdbus_msg_recv_poll(userns_conn, 300, &msg, NULL);
-               ASSERT_EXIT(ret == 0);
-               ASSERT_EXIT(msg->dst_id == KDBUS_DST_ID_BROADCAST);
+               ASSERT_EXIT_ZERO(kdbus_msg_recv_poll(userns_conn, 300, &msg, NULL));
+               ASSERT_EXIT(msg->dst_id,==,KDBUS_DST_ID_BROADCAST);
 
-               /* Different namespaces no CAPS */
-               item = kdbus_get_item(msg, KDBUS_ITEM_CAPS);
-               ASSERT_EXIT(item == NULL);
+               ASSERT_EXIT_NONZERO(item = kdbus_get_item(msg, KDBUS_ITEM_CAPS));
 
                /* uid/gid not mapped, so we have unpriv cached creds */
-               ret = kdbus_match_kdbus_creds(msg, &unmapped_creds);
-               ASSERT_EXIT(ret == 0);
+               ASSERT_EXIT_ZERO(kdbus_match_kdbus_creds(msg, &unmapped_creds));
 
                /*
                 * Diffent pid namepsaces. This is the child pidns
                 * so it should not see its parent kdbus_pids
                 */
-               ret = kdbus_match_kdbus_pids(msg, &unmapped_pids);
-               ASSERT_EXIT(ret == 0);
+               ASSERT_EXIT_ZERO(kdbus_match_kdbus_pids(msg, &unmapped_pids));
 
                kdbus_msg_free(msg);
 
@@ -217,8 +187,7 @@ static int __kdbus_clone_userns_test(const char *bus,
        }),
        ({
                /* Parent setup map child uid/gid */
-               ret = userns_map_uid_gid(pid, "0 65534 1", "0 65534 1");
-               ASSERT_EXIT(ret == 0);
+               ASSERT_EXIT_ZERO(userns_map_uid_gid(pid, "0 65534 1", "0 65534 1"));
        }),
        ({ 0; }));
        /* Unprivileged was not able to create user namespace */
@@ -231,25 +200,21 @@ static int __kdbus_clone_userns_test(const char *bus,
                goto out;
        }
 
-       ASSERT_EXIT(ret == 0);
+       ASSERT_EXIT_ZERO(ret);
 
 
        /*
         * Receive from privileged connection
         */
        kdbus_printf("\nPrivileged → unprivileged (same namespaces):\n");
-       ret = kdbus_msg_recv_poll(unpriv_conn, 300, &msg, NULL);
-
-       ASSERT_EXIT(ret == 0);
-       ASSERT_EXIT(msg->dst_id == unpriv_conn->id);
+       ASSERT_EXIT_ZERO(kdbus_msg_recv_poll(unpriv_conn, 300, &msg, NULL));
+       ASSERT_EXIT(msg->dst_id,==,unpriv_conn->id);
 
        /* will get the privileged creds */
-       ret = kdbus_match_kdbus_creds(msg, &privileged_creds);
-       ASSERT_EXIT(ret == 0);
+       ASSERT_EXIT_ZERO(kdbus_match_kdbus_creds(msg, &privileged_creds));
 
        /* Same pidns so will get the kdbus_pids */
-       ret = kdbus_match_kdbus_pids(msg, &parent_pids);
-       ASSERT_RETURN(ret == 0);
+       ASSERT_ZERO(kdbus_match_kdbus_pids(msg, &parent_pids));
 
        kdbus_msg_free(msg);
 
@@ -258,17 +223,13 @@ static int __kdbus_clone_userns_test(const char *bus,
         * Receive broadcast from privileged connection
         */
        kdbus_printf("\nPrivileged → unprivileged (same namespaces):\n");
-       ret = kdbus_msg_recv_poll(unpriv_conn, 300, &msg, NULL);
-
-       ASSERT_EXIT(ret == 0);
-       ASSERT_EXIT(msg->dst_id == KDBUS_DST_ID_BROADCAST);
+       ASSERT_EXIT_ZERO(kdbus_msg_recv_poll(unpriv_conn, 300, &msg, NULL));
+       ASSERT_EXIT(msg->dst_id,==,KDBUS_DST_ID_BROADCAST);
 
        /* will get the privileged creds */
-       ret = kdbus_match_kdbus_creds(msg, &privileged_creds);
-       ASSERT_EXIT(ret == 0);
+       ASSERT_EXIT_ZERO(kdbus_match_kdbus_creds(msg, &privileged_creds));
 
-       ret = kdbus_match_kdbus_pids(msg, &parent_pids);
-       ASSERT_RETURN(ret == 0);
+       ASSERT_ZERO(kdbus_match_kdbus_pids(msg, &parent_pids));
 
        kdbus_msg_free(msg);
 
@@ -278,43 +239,39 @@ out:
        return ret;
 }
 
-static int kdbus_clone_userns_test(const char *bus,
+static wur int kdbus_clone_userns_test(const char *bus,
                                   struct kdbus_conn *conn)
 {
-       int ret;
-       int status;
-       int efd = -1;
+       int ret, status, efd;
        pid_t pid, ppid;
-       uint64_t unpriv_conn_id = 0;
-       uint64_t userns_conn_id = 0;
+       uint64_t unpriv_conn_id, userns_conn_id;
        struct kdbus_msg *msg;
        const struct kdbus_item *item;
        struct kdbus_pids expected_pids;
-       struct kdbus_conn *monitor = NULL;
+       struct kdbus_conn *monitor;
 
        kdbus_printf("STARTING TEST 'metadata-ns'.\n");
 
-       monitor = kdbus_hello(bus, KDBUS_HELLO_MONITOR, NULL, 0);
-       ASSERT_EXIT(monitor);
+       ASSERT_EXIT_NONZERO(monitor = kdbus_hello(bus, KDBUS_HELLO_MONITOR, NULL, 0));
 
        /*
         * parent will signal to child that is in its
         * userns to read its queue
         */
        efd = eventfd(0, EFD_CLOEXEC);
-       ASSERT_RETURN_VAL(efd >= 0, efd);
+       ASSERT_RETURN_VAL(efd,>=,0, efd);
 
        ppid = getppid();
 
        pid = fork();
-       ASSERT_RETURN_VAL(pid >= 0, -errno);
+       ASSERT_RETURN_VAL(pid,>=,0, -errno);
 
        if (pid == 0) {
                ret = prctl(PR_SET_PDEATHSIG, SIGKILL);
-               ASSERT_EXIT_VAL(ret == 0, -errno);
+               ASSERT_EXIT_VAL(ret,==,0, -errno);
 
                ret = __kdbus_clone_userns_test(bus, conn, ppid, efd);
-               _exit(ret);
+               exit(ret);
        }
 
 
@@ -324,14 +281,12 @@ static int kdbus_clone_userns_test(const char *bus,
         * Receive from the unprivileged child
         */
        kdbus_printf("\nUnprivileged → privileged (same namespaces):\n");
-       ret = kdbus_msg_recv_poll(conn, 300, &msg, NULL);
-       ASSERT_RETURN(ret == 0);
+       ASSERT_ZERO(kdbus_msg_recv_poll(conn, 300, &msg, NULL));
 
        unpriv_conn_id = msg->src_id;
 
        /* Unprivileged user */
-       ret = kdbus_match_kdbus_creds(msg, &unmapped_creds);
-       ASSERT_RETURN(ret == 0);
+       ASSERT_ZERO(kdbus_match_kdbus_creds(msg, &unmapped_creds));
 
        /* Set the expected creds_pids */
        expected_pids = (struct kdbus_pids) {
@@ -339,8 +294,7 @@ static int kdbus_clone_userns_test(const char *bus,
                .tid = pid,
                .ppid = getpid(),
        };
-       ret = kdbus_match_kdbus_pids(msg, &expected_pids);
-       ASSERT_RETURN(ret == 0);
+       ASSERT_ZERO(kdbus_match_kdbus_pids(msg, &expected_pids));
 
        kdbus_msg_free(msg);
 
@@ -357,36 +311,31 @@ static int kdbus_clone_userns_test(const char *bus,
                /* perhaps unprivileged userns is not allowed */
                goto wait;
 
-       ASSERT_RETURN(ret == 0);
+       ASSERT_ZERO(ret);
 
        userns_conn_id = msg->src_id;
 
-       /* We do not share the userns, os no KDBUS_ITEM_CAPS */
-       item = kdbus_get_item(msg, KDBUS_ITEM_CAPS);
-       ASSERT_RETURN(item == NULL);
+       ASSERT_NONZERO(item = kdbus_get_item(msg, KDBUS_ITEM_CAPS));
 
        /*
         * Compare received items, creds must be translated into
         * the receiver user namespace, so the user is unprivileged
         */
-       ret = kdbus_match_kdbus_creds(msg, &unmapped_creds);
-       ASSERT_RETURN(ret == 0);
+       ASSERT_ZERO(kdbus_match_kdbus_creds(msg, &unmapped_creds));
 
        /*
         * We should have the kdbus_pids since we are the parent
         * pidns
         */
-       item = kdbus_get_item(msg, KDBUS_ITEM_PIDS);
-       ASSERT_RETURN(item);
+       ASSERT_NONZERO(item = kdbus_get_item(msg, KDBUS_ITEM_PIDS));
 
-       ASSERT_RETURN(memcmp(&item->pids, &unmapped_pids,
-                            sizeof(struct kdbus_pids)) != 0);
+       ASSERT_NONZERO(memcmp(&item->pids, &unmapped_pids, sizeof(struct kdbus_pids)));
 
        /*
         * Parent pid of the unprivileged/privileged in its userns
         * is the unprivileged child pid that was forked here.
         */
-       ASSERT_RETURN((uint64_t)pid == item->pids.ppid);
+       ASSERT_RETURN((uint64_t)pid,==,item->pids.ppid);
 
        kdbus_msg_free(msg);
 
@@ -396,36 +345,29 @@ static int kdbus_clone_userns_test(const char *bus,
        /*
         * Sending to unprivileged connections a unicast
         */
-       ret = kdbus_msg_send(conn, NULL, 0xdeadbeef, 0, 0,
-                            0, unpriv_conn_id, 0, NULL);
-       ASSERT_RETURN(ret == 0);
+       ASSERT_ZERO(kdbus_msg_send(conn, NULL, 0xdeadbeef, 0, 0, 0, unpriv_conn_id));
 
        /* signal to child that is in its userns */
-       ret = eventfd_write(efd, 1);
-       ASSERT_EXIT(ret == 0);
+       ASSERT_ZERO(eventfd_write(efd, 1));
 
        /*
         * Sending to unprivileged/privilged in its userns
         * connections a unicast
         */
-       ret = kdbus_msg_send(conn, NULL, 0xdeadbeef, 0, 0,
-                            0, userns_conn_id, 0, NULL);
-       ASSERT_RETURN(ret == 0);
+       ASSERT_ZERO(kdbus_msg_send(conn, NULL, 0xdeadbeef, 0, 0, 0, userns_conn_id));
 
        /*
         * Sending to unprivileged connections a broadcast
         */
-       ret = kdbus_msg_send(conn, NULL, 0xdeadbeef, 0, 0,
-                            0, KDBUS_DST_ID_BROADCAST, 0, NULL);
-       ASSERT_RETURN(ret == 0);
+       ASSERT_ZERO(kdbus_msg_send(conn, NULL, 0xdeadbeef, 0, 0, 0, KDBUS_DST_ID_BROADCAST));
 
 
 wait:
        ret = waitpid(pid, &status, 0);
-       ASSERT_RETURN(ret >= 0);
+       ASSERT_RETURN(ret,>=,0);
 
-       ASSERT_RETURN(WIFEXITED(status))
-       ASSERT_RETURN(!WEXITSTATUS(status));
+       ASSERT_NONZERO(WIFEXITED(status));
+       ASSERT_ZERO(WEXITSTATUS(status));
 
        /* Dump monitor queue */
        kdbus_printf("\n\nMonitor queue:\n");
@@ -439,24 +381,22 @@ wait:
                         * Parent pidns should see all the
                         * pids
                         */
-                       item = kdbus_get_item(msg, KDBUS_ITEM_PIDS);
-                       ASSERT_RETURN(item);
-
-                       ASSERT_RETURN(item->pids.pid != 0 &&
-                                     item->pids.tid != 0 &&
-                                     item->pids.ppid != 0);
+                       ASSERT_NONZERO(item = kdbus_get_item(msg, KDBUS_ITEM_PIDS));
+                       ASSERT_NONZERO(item->pids.pid);
+                       ASSERT_NONZERO(item->pids.tid != 0);
+                       ASSERT_NONZERO(item->pids.ppid != 0);
                }
 
                kdbus_msg_free(msg);
        }
 
        kdbus_conn_free(monitor);
-       close(efd);
+       CLOSE(efd);
 
        return 0;
 }
 
-int kdbus_test_metadata_ns(struct kdbus_test_env *env)
+wur int kdbus_test_metadata_ns(struct kdbus_test_env *env)
 {
        int ret;
        struct kdbus_conn *holder, *conn;
@@ -476,31 +416,104 @@ int kdbus_test_metadata_ns(struct kdbus_test_env *env)
                return TEST_SKIP;
 
        ret = test_is_capable(CAP_SETUID, CAP_SETGID, CAP_SYS_ADMIN, -1);
-       ASSERT_RETURN(ret >= 0);
+       ASSERT_RETURN(ret,>=,0);
 
        /* no enough privileges, SKIP test */
        if (!ret)
                return TEST_SKIP;
 
-       holder = kdbus_hello_registrar(env->buspath, "com.example.metadata",
-                                      &policy_access, 1,
-                                      KDBUS_HELLO_POLICY_HOLDER);
-       ASSERT_RETURN(holder);
+       ASSERT_NONZERO(holder = kdbus_hello_registrar(env->buspath, "com.example.metadata", &policy_access, 1, KDBUS_HELLO_POLICY_HOLDER));
 
-       conn = kdbus_hello(env->buspath, 0, NULL, 0);
-       ASSERT_RETURN(conn);
+       ASSERT_NONZERO(conn = kdbus_hello(env->buspath, 0, NULL, 0));
 
-       ret = kdbus_add_match_empty(conn);
-       ASSERT_RETURN(ret == 0);
+       ASSERT_ZERO(kdbus_add_match_empty(conn));
 
-       ret = kdbus_name_acquire(conn, "com.example.metadata", NULL);
-       ASSERT_EXIT(ret >= 0);
+       ASSERT_ZERO(kdbus_name_acquire(conn, "com.example.metadata", NULL));
 
-       ret = kdbus_clone_userns_test(env->buspath, conn);
-       ASSERT_RETURN(ret == 0);
+       ASSERT_ZERO(kdbus_clone_userns_test(env->buspath, conn));
 
        kdbus_conn_free(holder);
        kdbus_conn_free(conn);
 
        return TEST_OK;
 }
+
+#define TEST_METADATA_DECL\
+       int attach_flags_recv = _KDBUS_ATTACH_ALL;
+#define TEST_METADATA_DECL_INLOOP\
+       struct kdbus_item const *item;\
+       bool have_desc=false, have_name=false;\
+       if (attach_flags_recv & KDBUS_ATTACH_AUDIT) /* audit not generally supported - no reason to prolong the test by including it */\
+               attach_flags_recv &= ~KDBUS_ATTACH_AUDIT;
+#define TEST_METADATA(STRUCT) do {\
+       KDBUS_ITEM_FOREACH(item, (STRUCT), items) {\
+               if (KDBUS_ITEM_OWNED_NAME == item->type) {\
+                       ASSERT_ZERO(have_name);\
+                       have_name = true;\
+               } else if (KDBUS_ITEM_CONN_DESCRIPTION == item->type) {\
+                       ASSERT_ZERO(have_desc);\
+                       have_desc = true;\
+               }\
+       }\
+       if (attach_flags_recv & KDBUS_ATTACH_NAMES)\
+               ASSERT_NONZERO(have_name);\
+       else\
+               ASSERT_ZERO(have_name);\
+       if (attach_flags_recv & KDBUS_ATTACH_CONN_DESCRIPTION)\
+               ASSERT_NONZERO(have_desc);\
+       else\
+               ASSERT_ZERO(have_desc);\
+} while (0)
+
+wur int kdbus_test_metadata(struct kdbus_test_env *env)
+{
+       struct kdbus_conn *conn;
+       struct kdbus_msg *msg;
+       uint64_t cookie = 0x1234abcd5678eeff;
+
+       TEST_METADATA_DECL;
+
+       ASSERT_NONZERO(conn = kdbus_hello(env->buspath, 0, NULL, 0));
+       ASSERT_ZERO(kdbus_name_acquire(conn, "dummy.name.yeah", NULL));
+
+       do {
+               TEST_METADATA_DECL_INLOOP;
+
+               ASSERT_ZERO(kdbus_conn_update_attach_flags(env->conn, _KDBUS_ATTACH_ALL, attach_flags_recv));
+               ASSERT_ZERO(kdbus_msg_send(conn, NULL, ++cookie, 0, 0, 0, env->conn->id));
+               ASSERT_ZERO(kdbus_msg_recv(env->conn, &msg, NULL));
+
+               TEST_METADATA(msg);
+
+               kdbus_msg_free(msg);
+               ASSERT_ZERO(kdbus_free(env->conn, (uintptr_t)msg - (uintptr_t)env->conn->buf));
+       } while (--attach_flags_recv >= 0);
+
+       kdbus_conn_free(conn);
+
+       return TEST_OK;
+}
+
+wur int kdbus_test_metadata_conn_info(struct kdbus_test_env *env)
+{
+       TEST_METADATA_DECL;
+
+       ASSERT_ZERO(kdbus_name_acquire(env->conn, "dummy.name.yeah", NULL));
+
+       do {
+               struct kdbus_info *info;
+               uint64_t offset;
+
+               TEST_METADATA_DECL_INLOOP;
+
+               ASSERT_ZERO(kdbus_conn_info(env->conn, env->conn->id, NULL, attach_flags_recv, &offset));
+               info = (struct kdbus_info *)(env->conn->buf + offset);
+               ASSERT_RETURN(info->id,==,env->conn->id);
+
+               TEST_METADATA(info);
+
+               ASSERT_ZERO(kdbus_free(env->conn, (uintptr_t)info - (uintptr_t)env->conn->buf));
+       } while (--attach_flags_recv >= 0);
+
+       return TEST_OK;
+}