#include <sys/stat.h>
#include <sys/time.h>
#include <linux/unistd.h>
-#include <linux/memfd.h>
#ifndef __NR_memfd_create
#ifdef __x86_64__
#include "kdbus-api.h"
#include "kdbus-util.h"
#include "kdbus-enum.h"
+#include "kdbus-test.h"
#ifndef F_ADD_SEALS
#define F_LINUX_SPECIFIC_BASE 1024
#define F_SEAL_WRITE 0x0008 /* prevent writes */
#endif
+/* maximum number of well-known names per connection */
+#define KDBUS_CONN_MAX_NAMES 256
+
int kdbus_util_verbose = true;
-int kdbus_sysfs_get_parameter_mask(const char *path, uint64_t *mask)
+wur int kdbus_sysfs_get_parameter_mask(const char *path, uint64_t *mask)
{
int ret;
FILE *file;
return 0;
}
-int kdbus_sysfs_set_parameter_mask(const char *path, uint64_t mask)
+wur int kdbus_sysfs_set_parameter_mask(const char *path, uint64_t mask)
{
int ret;
FILE *file;
return ret > 0 ? 0 : ret;
}
-int kdbus_create_bus(int control_fd, const char *name,
- uint64_t req_meta, uint64_t owner_meta,
- char **path)
+wur int kdbus_create_bus(int control_fd, const char *name,
+ uint64_t owner_meta, char **path)
{
struct {
struct kdbus_cmd cmd;
struct kdbus_bloom_parameter bloom;
} bp;
- /* required and owner metadata items */
+ /* owner metadata items */
struct {
uint64_t size;
uint64_t type;
uint64_t flags;
- } attach[2];
+ } attach;
/* name item */
struct {
char str[64];
} name;
} bus_make;
- int ret = 0;
+ int ret;
memset(&bus_make, 0, sizeof(bus_make));
bus_make.bp.size = sizeof(bus_make.bp);
snprintf(bus_make.name.str, sizeof(bus_make.name.str),
"%u-%s", getuid(), name);
- bus_make.attach[0].type = KDBUS_ITEM_ATTACH_FLAGS_RECV;
- bus_make.attach[0].size = sizeof(bus_make.attach[0]);
- bus_make.attach[0].flags = req_meta;
-
- bus_make.attach[1].type = KDBUS_ITEM_ATTACH_FLAGS_SEND;
- bus_make.attach[1].size = sizeof(bus_make.attach[0]);
- bus_make.attach[1].flags = owner_meta;
+ bus_make.attach.type = KDBUS_ITEM_ATTACH_FLAGS_SEND;
+ bus_make.attach.size = sizeof(bus_make.attach);
+ bus_make.attach.flags = owner_meta;
bus_make.name.type = KDBUS_ITEM_MAKE_NAME;
bus_make.name.size = KDBUS_ITEM_HEADER_SIZE +
bus_make.cmd.flags = KDBUS_MAKE_ACCESS_WORLD;
bus_make.cmd.size = sizeof(bus_make.cmd) +
bus_make.bp.size +
- bus_make.attach[0].size +
- bus_make.attach[1].size +
+ bus_make.attach.size +
bus_make.name.size;
- if (control_fd != -1) {
- kdbus_printf(
- "Creating bus with name >%s< on control fd %d ...\n",
- name, control_fd);
+ kdbus_printf("Creating bus with name >%s< on control fd %d ...\n",
+ name, control_fd);
- ret = kdbus_cmd_bus_make(control_fd, &bus_make.cmd);
- if (ret < 0) {
- kdbus_printf("--- error when making bus: %d (%m)\n",
- ret);
- return ret;
- }
+ ret = kdbus_cmd_bus_make(control_fd, &bus_make.cmd);
+ if (ret < 0) {
+ kdbus_printf("--- error when making bus: %d (%m)\n", ret);
+ return ret;
}
if (ret == 0 && path)
return ret;
}
-struct kdbus_conn *
+wur struct kdbus_conn *
kdbus_hello(const char *path, uint64_t flags,
const struct kdbus_item *item, size_t item_size)
{
cmd_free.size = sizeof(cmd_free);
cmd_free.offset = h.hello.offset;
- kdbus_cmd_free(fd, &cmd_free);
+ ret = kdbus_cmd_free(fd, &cmd_free);
+ if (ret < 0 && !(flags & KDBUS_HELLO_POLICY_HOLDER && -EOPNOTSUPP == ret)) { /* free not supported for policy holders */
+ print("hello: KDBUS_CMD_FREE err(%d)\n", ret);
+ return NULL;
+ }
- conn = malloc(sizeof(*conn));
+ conn = alloc(sizeof(*conn));
if (!conn) {
- kdbus_printf("unable to malloc()!?\n");
+ kdbus_printf("unable to alloc()!?\n");
return NULL;
}
conn->buf = mmap(NULL, POOL_SIZE, PROT_READ, MAP_SHARED, fd, 0);
if (conn->buf == MAP_FAILED) {
free(conn);
- close(fd);
+ CLOSE(fd);
kdbus_printf("--- error mmap (%m)\n");
return NULL;
}
conn->fd = fd;
conn->id = h.hello.id;
+ _Static_assert((typeof(conn->attach_flags_recv))_KDBUS_ATTACH_ALL == _KDBUS_ATTACH_ALL, "kdbus_conn::attach_flags_recv too narrow for _KDBUS_ATTACH_ALL");
+ conn->attach_flags_recv = _KDBUS_ATTACH_ALL;
return conn;
}
-struct kdbus_conn *
+wur struct kdbus_conn *
kdbus_hello_registrar(const char *path, const char *name,
const struct kdbus_policy_access *access,
size_t num_access, uint64_t flags)
return kdbus_hello(path, flags, items, size);
}
-struct kdbus_conn *kdbus_hello_activator(const char *path, const char *name,
+wur struct kdbus_conn *kdbus_hello_activator(const char *path, const char *name,
const struct kdbus_policy_access *access,
size_t num_access)
{
KDBUS_HELLO_ACTIVATOR);
}
-bool kdbus_item_in_message(struct kdbus_msg *msg, uint64_t type)
+wur bool kdbus_item_in_message(struct kdbus_msg *msg, uint64_t type)
{
const struct kdbus_item *item;
return false;
}
-int kdbus_bus_creator_info(struct kdbus_conn *conn,
+wur int kdbus_bus_creator_info(struct kdbus_conn *conn,
uint64_t flags,
uint64_t *offset)
{
if (offset)
*offset = cmd->offset;
else
- kdbus_free(conn, cmd->offset);
+ ret = kdbus_free(conn, cmd->offset);
- return 0;
+ return ret;
}
-int kdbus_conn_info(struct kdbus_conn *conn, uint64_t id,
+wur static int kdbus_info_verify(struct kdbus_info *info, unsigned attach_flags);
+
+wur int kdbus_conn_info(struct kdbus_conn *conn, uint64_t id,
const char *name, uint64_t flags,
uint64_t *offset)
{
struct kdbus_cmd_info *cmd;
size_t size = sizeof(*cmd);
+ size_t full_size;
struct kdbus_info *info;
int ret;
+ /*print("call prepared 0\n");*/
+
if (name)
size += KDBUS_ITEM_HEADER_SIZE + strlen(name) + 1;
- cmd = alloca(size);
- memset(cmd, 0, size);
+ /*print("call prepared 1\n");*/
+
+ full_size = KDBUS_ALIGN8(size) + 1000;
+
+ /*print("call prepared 2\n");*/
+
+ cmd = malloc(full_size);
+ if (!cmd)
+ return -ENOMEM;
+ /*print("call prepared 3\n");*/
+ memset(cmd, 0, full_size);
+ /*print("call prepared 4\n");*/
cmd->size = size;
+ /*print("call prepared 5\n");*/
cmd->attach_flags = flags;
+ /*print("call prepared 6\n");*/
if (name) {
+ /*print("call prepared 7\n");*/
cmd->items[0].size = KDBUS_ITEM_HEADER_SIZE + strlen(name) + 1;
+ /*print("call prepared 8\n");*/
cmd->items[0].type = KDBUS_ITEM_NAME;
- strcpy(cmd->items[0].str, name);
+ /*print("call prepared 9 cmd(%p) cmd->items[0].str(%p) full_size(%u) len(%u) name(%s)\n", cmd, cmd->items[0].str, (unsigned)full_size, (unsigned)strlen(name), name);*/
+
+ /* tizen 3.0 strcpy reports buffer overflow for no apparent reason - memcpy doesn't */
+ memcpy(cmd->items[0].str, name, strlen(name));
+ /*strcpy(cmd->items[0].str, name);*/
} else {
+ /*print("call prepared 10\n");*/
cmd->id = id;
}
+ /*print("call prepared 11\n");*/
+
ret = kdbus_cmd_conn_info(conn->fd, cmd);
if (ret < 0) {
kdbus_printf("--- error when requesting info: %d (%m)\n", ret);
+ free(cmd);
return ret;
}
info = (struct kdbus_info *) (conn->buf + cmd->offset);
- if (info->size != cmd->info_size) {
+ if (KDBUS_ALIGN8(info->size) != cmd->info_size) {
kdbus_printf("%s(): size mismatch: %d != %d\n", __func__,
(int) info->size, (int) cmd->info_size);
+ free(cmd);
return -EIO;
}
- if (offset)
+ if (offset) {
*offset = cmd->offset;
- else
- kdbus_free(conn, cmd->offset);
+ ASSERT_ZERO(kdbus_info_verify(info, flags));
+ } else
+ ret = kdbus_free(conn, cmd->offset);
- return 0;
+ free(cmd);
+ return ret;
}
void kdbus_conn_free(struct kdbus_conn *conn)
if (!conn)
return;
- if (conn->buf)
- munmap(conn->buf, POOL_SIZE);
+ if (conn->buf && munmap(conn->buf, POOL_SIZE))
+ fail("munmap(%p) err(%d)", conn->buf, errno);
- if (conn->fd >= 0)
- close(conn->fd);
+ if (conn->fd >= 0 && close(conn->fd))
+ fail("close(%d) err(%d)", conn->fd, errno);
free(conn);
}
-int sys_memfd_create(const char *name, __u64 size)
+wur int sys_memfd_create(const char *name, __u64 size)
{
int ret, fd;
- ret = syscall(__NR_memfd_create, name, MFD_ALLOW_SEALING);
- if (ret < 0)
- return ret;
-
- fd = ret;
+ fd = syscall(__NR_memfd_create, name, 2/*MFD_ALLOW_SEALING*/);
+ if (fd < 0)
+ return fd;
ret = ftruncate(fd, size);
if (ret < 0) {
- close(fd);
+ CLOSE(fd);
return ret;
}
return fd;
}
-int sys_memfd_seal_set(int fd)
+wur int sys_memfd_seal_set(int fd)
{
return fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK |
F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL);
}
-off_t sys_memfd_get_size(int fd, off_t *size)
+wur off_t sys_memfd_get_size(int fd, off_t *size)
{
struct stat stat;
int ret;
return 0;
}
-static int __kdbus_msg_send(const struct kdbus_conn *conn,
+static wur int __kdbus_msg_send(const struct kdbus_conn *conn,
const char *name,
uint64_t cookie,
uint64_t flags,
int64_t priority,
uint64_t dst_id,
uint64_t cmd_flags,
- int cancel_fd,
- int fds_count,
- int fds[])
+ int cancel_fd)
{
- struct kdbus_cmd_send *cmd;
- struct kdbus_msg *msg;
+ struct kdbus_cmd_send *cmd = NULL;
+ struct kdbus_msg *msg = NULL;
const char ref1[1024 * 128 + 3] = "0123456789_0";
const char ref2[] = "0123456789_1";
struct kdbus_item *item;
int memfd = -1;
int ret;
- size = sizeof(*msg);
- size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec));
- size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec));
- size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec));
- size += fds_count > 0 ? KDBUS_ITEM_SIZE(sizeof(int) * fds_count) : 0;
+ size = sizeof(*msg) + 3 * KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec));
if (dst_id == KDBUS_DST_ID_BROADCAST)
size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_bloom_filter)) + 64;
if (write(memfd, "kdbus memfd 1234567", 19) != 19) {
ret = -errno;
kdbus_printf("writing to memfd failed: %m\n");
- return ret;
+ goto out;
}
ret = sys_memfd_seal_set(memfd);
if (ret < 0) {
ret = -errno;
kdbus_printf("memfd sealing failed: %m\n");
- return ret;
+ goto out;
}
size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_memfd));
if (name)
size += KDBUS_ITEM_SIZE(strlen(name) + 1);
- msg = malloc(size);
+ msg = alloc(size);
if (!msg) {
ret = -errno;
- kdbus_printf("unable to malloc()!?\n");
- return ret;
+ kdbus_printf("unable to alloc()!?\n");
+ goto out;
}
if (dst_id == KDBUS_DST_ID_BROADCAST)
if (timeout) {
ret = clock_gettime(CLOCK_MONOTONIC_COARSE, &now);
if (ret < 0)
- return ret;
+ goto out;
msg->timeout_ns = now.tv_sec * 1000000000ULL +
now.tv_nsec + timeout;
}
item = KDBUS_ITEM_NEXT(item);
- if (fds_count > 0) {
- item->type = KDBUS_ITEM_FDS;
- item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(int) * fds_count;
- memcpy(&item->fds, fds, sizeof(int) * fds_count);
- item = KDBUS_ITEM_NEXT(item);
- }
-
size = sizeof(*cmd);
if (cancel_fd != -1)
size += KDBUS_ITEM_SIZE(sizeof(cancel_fd));
- cmd = malloc(size);
+ cmd = alloc(size);
if (!cmd) {
ret = -errno;
- kdbus_printf("unable to malloc(%ld)!?\n", (long)size);
- return ret;
+ kdbus_printf("unable to alloc()!?\n");
+ goto out;
}
+
cmd->size = size;
cmd->flags = cmd_flags;
cmd->msg_address = (uintptr_t)msg;
item = KDBUS_ITEM_NEXT(item);
}
-
ret = kdbus_cmd_send(conn->fd, cmd);
- if (memfd >= 0)
- close(memfd);
-
if (ret < 0) {
kdbus_printf("error sending message: %d (%m)\n", ret);
- return ret;
+ goto out;
}
if (cmd_flags & KDBUS_SEND_SYNC_REPLY) {
struct kdbus_msg *reply;
+ int dumpret;
kdbus_printf("SYNC REPLY @offset %llu:\n", cmd->reply.offset);
reply = (struct kdbus_msg *)(conn->buf + cmd->reply.offset);
- kdbus_msg_dump(conn, reply);
+ dumpret = kdbus_msg_dump(reply);
kdbus_msg_free(reply);
ret = kdbus_free(conn, cmd->reply.offset);
- if (ret < 0)
- return ret;
+ if (!ret)
+ ret = dumpret;
}
+out:
free(msg);
free(cmd);
- return 0;
+ if (memfd >= 0)
+ CLOSE(memfd);
+
+ return ret < 0 ? ret : 0;
}
-int kdbus_msg_send(const struct kdbus_conn *conn, const char *name,
+wur int kdbus_msg_send(const struct kdbus_conn *conn, const char *name,
uint64_t cookie, uint64_t flags, uint64_t timeout,
- int64_t priority, uint64_t dst_id, int fds_count, int fds[])
+ int64_t priority, uint64_t dst_id)
{
return __kdbus_msg_send(conn, name, cookie, flags, timeout, priority,
- dst_id, 0, -1, fds_count, fds);
+ dst_id, 0, -1);
}
-int kdbus_msg_send_sync(const struct kdbus_conn *conn, const char *name,
+wur int kdbus_msg_send_sync(const struct kdbus_conn *conn, const char *name,
uint64_t cookie, uint64_t flags, uint64_t timeout,
int64_t priority, uint64_t dst_id, int cancel_fd)
{
return __kdbus_msg_send(conn, name, cookie, flags, timeout, priority,
- dst_id, KDBUS_SEND_SYNC_REPLY, cancel_fd,
- 0, NULL);
+ dst_id, KDBUS_SEND_SYNC_REPLY, cancel_fd);
}
-int kdbus_msg_send_reply(const struct kdbus_conn *conn,
+wur int kdbus_msg_send_reply(const struct kdbus_conn *conn,
uint64_t reply_cookie,
uint64_t dst_id)
{
size = sizeof(struct kdbus_msg);
size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec));
- msg = malloc(size);
+ msg = alloc(size);
if (!msg) {
- kdbus_printf("unable to malloc()!?\n");
+ kdbus_printf("unable to alloc()!?\n");
return -ENOMEM;
}
return ret;
}
-static char *msg_id(uint64_t id, char *buf)
+static wur char *msg_id(uint64_t id, char *buf)
{
if (id == 0)
return "KERNEL";
return buf;
}
-int kdbus_msg_dump(const struct kdbus_conn *conn, const struct kdbus_msg *msg)
-{
+wur int kdbus_msg_dump(const struct kdbus_msg *msg) {
const struct kdbus_item *item = msg->items;
char buf_src[32];
char buf_dst[32];
else
cookie_reply = msg->cookie_reply;
- kdbus_printf("MESSAGE: %s (%llu bytes) flags=0x%08llx, %s → %s, "
+ kdbus_printf("MESSAGE(%p): %s (%llu bytes) flags=0x%08llx, %s → %s, "
"cookie=%llu, timeout=%llu cookie_reply=%llu priority=%lli\n",
+ msg,
enum_PAYLOAD(msg->payload_type), (unsigned long long)msg->size,
(unsigned long long)msg->flags,
msg_id(msg->src_id, buf_src), msg_id(msg->dst_id, buf_dst),
if (item->size < KDBUS_ITEM_HEADER_SIZE) {
kdbus_printf(" +%s (%llu bytes) invalid data record\n",
enum_MSG(item->type), item->size);
- ret = -EINVAL;
- break;
+ return -EINVAL;
}
switch (item->type) {
break;
}
- kdbus_printf(" +%s (%llu bytes) fd=%i size=%llu filesize=%llu '%s'\n",
+ kdbus_printf(" +%s (%llu bytes) fd=%i size=%llu filesize=%llu '0x%llx'\n",
enum_MSG(item->type), item->size, item->memfd.fd,
(unsigned long long)item->memfd.size,
- (unsigned long long)size, buf);
+ (unsigned long long)size, (unsigned long long)(size >= 8 ? *(unsigned long long *)buf : size >= 4 ? *(unsigned *)buf : *buf));
munmap(buf, item->memfd.size);
break;
}
switch (item->type) {
/* close all memfds */
case KDBUS_ITEM_PAYLOAD_MEMFD:
- close(item->memfd.fd);
+ if (-1 != item->memfd.fd)
+ CLOSE(item->memfd.fd);
break;
case KDBUS_ITEM_FDS:
nfds = (item->size - KDBUS_ITEM_HEADER_SIZE) /
sizeof(int);
for (i = 0; i < nfds; i++)
- close(item->fds[i]);
+ if (-1 != item->fds[i])
+ CLOSE(item->fds[i]);
break;
}
}
}
-int kdbus_msg_recv(struct kdbus_conn *conn,
+wur static int verify_padding(char const *b, unsigned off)
+{
+ while (off%8) {
+ ASSERT_ZERO((unsigned)b[off]);
+ ++off;
+ }
+ return 0;
+}
+
+wur static int verify_string(unsigned size, char const *s)
+{
+ unsigned len;
+ ASSERT_NONZERO(size);
+ len = strlen(s)+1;
+ ASSERT_RETURN(len,==,size);
+ ASSERT_ZERO(verify_padding(s, len));
+ return 0;
+}
+wur static int verify_string_array(unsigned size, char const *s)
+{
+ unsigned off=0;
+ ASSERT_NONZERO(size);
+ while (size) {
+ unsigned len = strlen(s+off);
+ if (!len)
+ break;
+ ++len;
+ ASSERT_RETURN(len,<=,size);
+ size -= len;
+ off += len;
+ }
+ ASSERT_ZERO(verify_padding(s, off));
+ return 0;
+}
+
+#define VERIFY_DECL\
+ const struct kdbus_item *item;\
+ unsigned item_count[14];\
+ unsigned i;\
+ memset(item_count, 0, sizeof(item_count));
+#define VERIFY_DECL_INLOOP\
+ unsigned idx;\
+ unsigned size;\
+ ASSERT_RETURN(item->size,>=,2*sizeof(uint64_t));\
+ ASSERT_RETURN((unsigned)item->size,==,item->size);\
+ size = item->size - 2*sizeof(uint64_t);
+#define VERIFY_META_CASES\
+ /* metadata */\
+ case KDBUS_ITEM_CREDS:\
+ ASSERT_RETURN(size,==,sizeof(struct kdbus_creds));\
+ break;\
+ case KDBUS_ITEM_PIDS:\
+ ASSERT_RETURN(size,==,sizeof(struct kdbus_pids));\
+ break;\
+ case KDBUS_ITEM_AUDIT:\
+ ASSERT_RETURN(size,==,sizeof(struct kdbus_audit));\
+ break;\
+ case KDBUS_ITEM_AUXGROUPS:\
+ case KDBUS_ITEM_CAPS:\
+ ASSERT_ZERO(size%sizeof(uint32_t));\
+ break;\
+ case KDBUS_ITEM_OWNED_NAME:\
+ ASSERT_ZERO(verify_string(size-offsetof(typeof(item->name), name), item->name.name));\
+ break;\
+ case KDBUS_ITEM_TID_COMM:\
+ case KDBUS_ITEM_PID_COMM:\
+ case KDBUS_ITEM_EXE:\
+ case KDBUS_ITEM_CGROUP:\
+ case KDBUS_ITEM_SECLABEL:\
+ case KDBUS_ITEM_CONN_DESCRIPTION:\
+ ASSERT_ZERO(verify_string(size, item->str));\
+ break;\
+ case KDBUS_ITEM_CMDLINE:\
+ ASSERT_ZERO(verify_string_array(size, item->str));\
+ break;
+#define VERIFY_META do {\
+ ASSERT_RETURN(item->type,>=,(uint64_t)_KDBUS_ITEM_ATTACH_BASE);\
+ idx = item->type - _KDBUS_ITEM_ATTACH_BASE;\
+ ASSERT_RETURN(idx,<,sizeof(item_count)/sizeof(*item_count));\
+ ASSERT_NONZERO(attach_flags & 1<<idx);\
+ if (KDBUS_ITEM_OWNED_NAME != item->type)\
+ ASSERT_ZERO(item_count[idx]);\
+ else\
+ ASSERT_RETURN(item_count[idx],<,(uint64_t)KDBUS_CONN_MAX_NAMES);\
+ ++item_count[idx];\
+} while (0)
+#define VERIFY_FINAL_ASSERT do {\
+ for (i=0; i<TABSIZE(item_count); ++i) {\
+ if (attach_flags & 1<<i &&\
+ KDBUS_ITEM_TIMESTAMP-_KDBUS_ITEM_ATTACH_BASE != i && /* nameless connections happen */\
+ KDBUS_ITEM_OWNED_NAME-_KDBUS_ITEM_ATTACH_BASE != i && /* nameless connections happen */\
+ KDBUS_ITEM_CONN_DESCRIPTION-_KDBUS_ITEM_ATTACH_BASE != i && /* defining a connection description is optional */\
+ KDBUS_ITEM_AUDIT-_KDBUS_ITEM_ATTACH_BASE != i) /* missing if CONFIG_AUDITSYSCALL not defined */\
+ if (!item_count[i]) ASSERT_ZERO(i+1); /*hack to make i visible*/\
+ }\
+} while (0)
+
+wur static int kdbus_info_verify(struct kdbus_info *info, unsigned attach_flags)
+{
+ VERIFY_DECL;
+
+ KDBUS_ITEM_FOREACH(item, info, items) {
+ VERIFY_DECL_INLOOP;
+ switch(item->type) {
+ VERIFY_META_CASES;
+ default: ASSERT_ZERO(item->type ?: (uint64_t)-1);
+ }
+ VERIFY_META;
+ }
+
+ VERIFY_FINAL_ASSERT;
+
+ return 0;
+}
+
+wur static int kdbus_msg_verify(struct kdbus_msg *msg, unsigned attach_flags)
+{
+ bool user = false;
+
+ VERIFY_DECL;
+
+ if (msg->payload_type != KDBUS_PAYLOAD_KERNEL) {
+ ASSERT_RETURN(msg->payload_type,==,KDBUS_PAYLOAD_DBUS);
+ user = true;
+ }
+
+ KDBUS_ITEM_FOREACH(item, msg, items) {
+ VERIFY_DECL_INLOOP;
+
+ switch(item->type) {
+ case KDBUS_ITEM_TIMESTAMP:
+ ASSERT_RETURN(size,==,sizeof(struct kdbus_timestamp));
+ break;
+ VERIFY_META_CASES;
+
+ /* user items */
+ case KDBUS_ITEM_PAYLOAD_OFF:
+ ASSERT_NONZERO(user);
+ ASSERT_RETURN(size,==,sizeof(struct kdbus_vec));
+ continue;
+ case KDBUS_ITEM_PAYLOAD_MEMFD:
+ ASSERT_NONZERO(user);
+ ASSERT_RETURN(size,==,sizeof(struct kdbus_memfd));
+ continue;
+ case KDBUS_ITEM_FDS:
+ ASSERT_NONZERO(user);
+ ASSERT_ZERO(size%sizeof(int));
+ continue;
+ case KDBUS_ITEM_DST_NAME:
+ ASSERT_NONZERO(user);
+ ASSERT_ZERO(verify_string(size, item->str));
+ continue;
+
+ /* kernel items */
+ case KDBUS_ITEM_NAME_ADD:
+ case KDBUS_ITEM_NAME_REMOVE:
+ case KDBUS_ITEM_NAME_CHANGE:
+ ASSERT_ZERO(user);
+ ASSERT_RETURN(size,>=,sizeof(struct kdbus_notify_name_change));
+ ASSERT_ZERO(verify_string(size-sizeof(struct kdbus_notify_name_change), item->name_change.name));
+ continue;
+ case KDBUS_ITEM_ID_ADD:
+ case KDBUS_ITEM_ID_REMOVE:
+ ASSERT_ZERO(user);
+ ASSERT_RETURN(size,==,sizeof(struct kdbus_notify_id_change));
+ continue;
+ case KDBUS_ITEM_REPLY_TIMEOUT:
+ case KDBUS_ITEM_REPLY_DEAD:
+ ASSERT_ZERO(user);
+ ASSERT_ZERO(size);
+ continue;
+
+ case KDBUS_ITEM_BLOOM_FILTER:
+ kdbus_printf("WARNING! KDBUS_ITEM_BLOOM_FILTER passed from the kernel\n");
+ continue;
+
+ default:
+ ASSERT_ZERO(item->type ?: (uint64_t)-1);
+ }
+ if (KDBUS_ITEM_TIMESTAMP != item->type)
+ ASSERT_NONZERO(user);
+ VERIFY_META;
+ }
+
+ /* we're requesting all metadata and that's what we mandate */
+ if (user) {
+ VERIFY_FINAL_ASSERT;
+ if (attach_flags & 1 << (KDBUS_ITEM_TIMESTAMP-_KDBUS_ITEM_ATTACH_BASE))
+ ASSERT_NONZERO(item_count[KDBUS_ITEM_TIMESTAMP-_KDBUS_ITEM_ATTACH_BASE]);
+ } else if (attach_flags & 1 << (KDBUS_ITEM_TIMESTAMP-_KDBUS_ITEM_ATTACH_BASE))
+ ASSERT_NONZERO(item_count[KDBUS_ITEM_TIMESTAMP-_KDBUS_ITEM_ATTACH_BASE]);
+
+ return 0;
+}
+
+wur int kdbus_msg_recv(struct kdbus_conn *conn,
struct kdbus_msg **msg_out,
uint64_t *offset)
{
return ret;
msg = (struct kdbus_msg *)(conn->buf + recv.msg.offset);
- ret = kdbus_msg_dump(conn, msg);
+ ret = kdbus_msg_dump(msg);
+ ASSERT_ZERO(kdbus_msg_verify(msg, conn->attach_flags_recv));
if (ret < 0) {
kdbus_msg_free(msg);
return ret;
* We must return -ETIMEDOUT, -ECONNREST, -EAGAIN and other errors.
* We must return the result of kdbus_msg_recv()
*/
-int kdbus_msg_recv_poll(struct kdbus_conn *conn,
+wur int kdbus_msg_recv_poll(struct kdbus_conn *conn,
int timeout_ms,
struct kdbus_msg **msg_out,
uint64_t *offset)
return ret;
}
-int kdbus_free(const struct kdbus_conn *conn, uint64_t offset)
+wur int kdbus_free(const struct kdbus_conn *conn, uint64_t offset)
{
struct kdbus_cmd_free cmd_free = {};
int ret;
return 0;
}
-int kdbus_name_acquire(struct kdbus_conn *conn,
+wur int kdbus_free_msg(struct kdbus_conn const *conn, struct kdbus_msg *msg)
+{
+ return kdbus_free(conn, (uintptr_t)msg - (uintptr_t)conn->buf);
+}
+
+wur int kdbus_name_acquire(struct kdbus_conn *conn,
const char *name, uint64_t *flags)
{
struct kdbus_cmd *cmd_name;
ret = kdbus_cmd_name_acquire(conn->fd, cmd_name);
if (ret < 0) {
- kdbus_printf("error aquiring name: %s\n", strerror(-ret));
+ kdbus_printf("error acquiring name: %s\n", strerror(-ret));
return ret;
}
return 0;
}
-int kdbus_name_release(struct kdbus_conn *conn, const char *name)
+wur int kdbus_name_release(struct kdbus_conn *conn, const char *name)
{
struct kdbus_cmd *cmd_name;
size_t name_len = strlen(name) + 1;
return 0;
}
-int kdbus_list(struct kdbus_conn *conn, uint64_t flags)
+wur int kdbus_list(struct kdbus_conn *conn, uint64_t flags)
{
struct kdbus_cmd_list cmd_list = {};
struct kdbus_info *list, *name;
if (item->type == KDBUS_ITEM_OWNED_NAME) {
n = item->name.name;
flags = item->name.flags;
- }
- kdbus_printf("%8llu flags=0x%08llx conn=0x%08llx '%s'\n",
- name->id, (unsigned long long) flags,
- name->flags, n);
+ kdbus_printf("%8llu flags=0x%08llx conn=0x%08llx '%s'\n",
+ name->id,
+ (unsigned long long) flags,
+ name->flags, n);
+ }
}
kdbus_printf("\n");
return ret;
}
-int kdbus_conn_update_attach_flags(struct kdbus_conn *conn,
+wur int kdbus_conn_update_attach_flags(struct kdbus_conn *conn,
uint64_t attach_flags_send,
uint64_t attach_flags_recv)
{
size = sizeof(struct kdbus_cmd);
size += KDBUS_ITEM_SIZE(sizeof(uint64_t)) * 2;
- update = malloc(size);
+ update = alloc(size);
if (!update) {
- kdbus_printf("error malloc: %m\n");
+ kdbus_printf("error alloc: %m\n");
return -ENOMEM;
}
kdbus_printf("error conn update: %d (%m)\n", ret);
free(update);
+ conn->attach_flags_recv = attach_flags_recv;
return ret;
}
-int kdbus_conn_update_policy(struct kdbus_conn *conn, const char *name,
+wur int kdbus_conn_update_policy(struct kdbus_conn *conn, const char *name,
const struct kdbus_policy_access *access,
size_t num_access)
{
size += KDBUS_ITEM_SIZE(strlen(name) + 1);
size += num_access * KDBUS_ITEM_SIZE(sizeof(struct kdbus_policy_access));
- update = malloc(size);
+ update = alloc(size);
if (!update) {
- kdbus_printf("error malloc: %m\n");
+ kdbus_printf("error alloc: %m\n");
return -ENOMEM;
}
return ret;
}
-int kdbus_add_match_id(struct kdbus_conn *conn, uint64_t cookie,
+wur int kdbus_add_match_id(struct kdbus_conn *conn, uint64_t cookie,
uint64_t type, uint64_t id)
{
struct {
return ret;
}
-int kdbus_add_match_empty(struct kdbus_conn *conn)
+wur int kdbus_add_match_empty(struct kdbus_conn *conn)
{
struct {
struct kdbus_cmd_match cmd;
return ret;
}
-static int all_ids_are_mapped(const char *path)
+static wur int all_ids_are_mapped(const char *path)
{
int ret;
FILE *file;
return 0;
}
-int all_uids_gids_are_mapped()
+wur int all_uids_gids_are_mapped(void)
{
int ret;
return 1;
}
-int drop_privileges(uid_t uid, gid_t gid)
+wur int drop_privileges(uid_t uid, gid_t gid)
{
int ret;
return ret;
}
-uint64_t now(clockid_t clock)
+wur uint64_t now(clockid_t clock)
{
struct timespec spec;
return spec.tv_sec * 1000ULL * 1000ULL * 1000ULL + spec.tv_nsec;
}
-char *unique_name(const char *prefix)
+wur char *unique_name(const char *prefix)
{
unsigned int i;
uint64_t u_now;
return str;
}
-static int do_userns_map_id(pid_t pid,
- const char *map_file,
+static wur int do_userns_map_id(const char *map_file,
const char *map_id)
{
int ret;
ret = 0;
out:
- close(fd);
+ CLOSE(fd);
return ret;
}
-int userns_map_uid_gid(pid_t pid,
+wur int userns_map_uid_gid(pid_t pid,
const char *map_uid,
const char *map_gid)
{
snprintf(file_id, sizeof(file_id), "/proc/%ld/uid_map",
(long) pid);
- ret = do_userns_map_id(pid, file_id, map_uid);
+ ret = do_userns_map_id(file_id, map_uid);
if (ret < 0)
return ret;
fd = open(file_id, O_WRONLY);
if (fd >= 0) {
- write(fd, "deny\n", 5);
- close(fd);
+ ret = write(fd, "deny\n", 5);
+ CLOSE(fd);
+ if (ret != 5)
+ return ret<0 ? ret : -EIO;
}
snprintf(file_id, sizeof(file_id), "/proc/%ld/gid_map",
(long) pid);
- return do_userns_map_id(pid, file_id, map_gid);
+ return do_userns_map_id(file_id, map_gid);
}
-static int do_cap_get_flag(cap_t caps, cap_value_t cap)
+static wur int do_cap_get_flag(cap_t caps, cap_value_t cap)
{
int ret;
cap_flag_value_t flag_set;
*
* Terminate args with a negative value.
*/
-int test_is_capable(int cap, ...)
+wur int test_is_capable(int cap, ...)
{
int ret;
va_list ap;
cap_t caps;
caps = cap_get_proc();
- if (!cap) {
+ if (!caps) {
ret = -errno;
kdbus_printf("error cap_get_proc(): %d (%m)\n", ret);
return ret;
return ret;
}
-int config_user_ns_is_enabled(void)
+wur int config_user_ns_is_enabled(void)
{
return (access("/proc/self/uid_map", F_OK) == 0);
}
-int config_auditsyscall_is_enabled(void)
+wur int config_auditsyscall_is_enabled(void)
{
return (access("/proc/self/loginuid", F_OK) == 0);
}
-int config_cgroups_is_enabled(void)
+wur int config_cgroups_is_enabled(void)
{
return (access("/proc/self/cgroup", F_OK) == 0);
}
-int config_security_is_enabled(void)
+wur int config_security_is_enabled(void)
{
int fd;
int ret;
else
ret = 1;
- close(fd);
+ CLOSE(fd);
return ret;
}