Skip to content

Commit

Permalink
get pidfd for Containers1 kinds
Browse files Browse the repository at this point in the history
  • Loading branch information
swick committed Jan 19, 2024
1 parent 4573cc0 commit 99f7894
Showing 1 changed file with 137 additions and 48 deletions.
185 changes: 137 additions & 48 deletions src/xdp-utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ struct _XdpAppInfo {
{
char *container_type;
char *instance_id;
int pidfd;
char *desktop_file;
gboolean has_network;
} containers1;
Expand Down Expand Up @@ -265,6 +266,7 @@ xdp_app_info_free (XdpAppInfo *app_info)
g_clear_pointer (&app_info->u.containers1.container_type, g_free);
g_clear_pointer (&app_info->u.containers1.instance_id, g_free);
g_clear_pointer (&app_info->u.containers1.desktop_file, g_free);
xdp_close_fd (&app_info->u.containers1.pidfd);
break;

case XDP_APP_INFO_KIND_HOST:
Expand Down Expand Up @@ -869,12 +871,57 @@ parse_app_info_from_snap (pid_t pid, GError **error)
return g_steal_pointer (&app_info);
}

static gboolean
xdp_get_app_info_get_pid (GDBusConnection *connection,
const char *sender,
GCancellable *cancellable,
guint32 *out_pid,
GError **error)
{
g_autoptr(GDBusMessage) msg = NULL;
g_autoptr(GDBusMessage) reply = NULL;
g_autoptr(XdpAppInfo) app_info = NULL;
GVariant *body;

msg = g_dbus_message_new_method_call (DBUS_NAME_DBUS,
DBUS_PATH_DBUS,
DBUS_INTERFACE_DBUS,
"GetConnectionUnixProcessID");
g_dbus_message_set_body (msg, g_variant_new ("(s)", sender));

reply = g_dbus_connection_send_message_with_reply_sync (connection, msg,
G_DBUS_SEND_MESSAGE_FLAGS_NONE,
30000,
NULL,
cancellable,
error);
if (reply == NULL)
return FALSE;

if (g_dbus_message_get_message_type (reply) == G_DBUS_MESSAGE_TYPE_ERROR)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Can't find peer pid");
return FALSE;
}

body = g_dbus_message_get_body (reply);
g_variant_get (body, "(u)", out_pid);

return TRUE;
}

static XdpAppInfo *
xdp_get_app_info_from_pid (pid_t pid,
GError **error)
xdp_get_app_info_from_pid (GDBusConnection *connection,
const char *sender,
GCancellable *cancellable,
GError **error)
{
g_autoptr(XdpAppInfo) app_info = NULL;
g_autoptr(GError) local_error = NULL;
guint32 pid;

if (!xdp_get_app_info_get_pid (connection, sender, cancellable, &pid, error))
return NULL;

app_info = parse_app_info_from_flatpak_info (pid, &local_error);
if (app_info == NULL && local_error)
Expand All @@ -901,6 +948,7 @@ xdp_get_app_info_from_pid (pid_t pid,

static XdpAppInfo *
xdp_get_app_info_from_connection_info (GVariant *connection_info,
int pidfd,
GError **error)
{
XdpAppInfo *app_info = NULL;
Expand Down Expand Up @@ -929,6 +977,7 @@ xdp_get_app_info_from_connection_info (GVariant *connection_info,
app_info->id = g_strdup (app_id);
app_info->u.containers1.container_type = g_strdup (container_type);
app_info->u.containers1.instance_id = g_strdup (instance_id);
app_info->u.containers1.pidfd = pidfd;

desktop_file = g_variant_lookup_value (metadata, "DesktopFile", G_VARIANT_TYPE_STRING);
if (desktop_file)
Expand All @@ -941,16 +990,98 @@ xdp_get_app_info_from_connection_info (GVariant *connection_info,
return app_info;
}

static gboolean
xdp_get_app_info_get_pidfd (GDBusConnection *connection,
const char *sender,
GCancellable *cancellable,
int *out_pidfd,
guint32 *out_pid,
GError **error)
{
g_autoptr(GDBusMessage) msg = NULL;
g_autoptr(GDBusMessage) reply = NULL;
GVariant *body;
g_autoptr(GVariant) dict;
g_autoptr(GVariant) process_fd;
g_autoptr(GVariant) process_id;
int fd_index;
GUnixFDList *fd_list;
gint fds_len = 0;
const gint *fds;
guint32 pid;

msg = g_dbus_message_new_method_call (DBUS_NAME_DBUS,
DBUS_PATH_DBUS,
DBUS_INTERFACE_DBUS,
"GetConnectionCredentials");
g_dbus_message_set_body (msg, g_variant_new ("(s)", sender));

reply = g_dbus_connection_send_message_with_reply_sync (connection, msg,
G_DBUS_SEND_MESSAGE_FLAGS_NONE,
30000,
NULL,
cancellable,
error);

if (reply == NULL)
return FALSE;

if (g_dbus_message_get_message_type (reply) == G_DBUS_MESSAGE_TYPE_ERROR)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Can't find peer pidfd");
return FALSE;
}

body = g_dbus_message_get_body (reply);
g_variant_get (body, "(@a{sv})", &dict);

process_fd = g_variant_lookup_value (dict, "ProcessFD", G_VARIANT_TYPE_HANDLE);
process_id = g_variant_lookup_value (dict, "ProcessID", G_VARIANT_TYPE_UINT32);
if (!process_fd || !process_id)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
"org.freedesktop.DBus.GetConnectionCredentials doesn't support ProcessFD");
return FALSE;
}

fd_index = g_variant_get_handle (process_fd);
pid = g_variant_get_uint32 (process_id);

fd_list = g_dbus_message_get_unix_fd_list (reply);
if (fd_list == NULL)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Can't find feed pidfd");
return FALSE;
}

fds = g_unix_fd_list_peek_fds (fd_list, &fds_len);
if (fds_len <= fd_index)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Can't find feed pidfd");
return FALSE;
}

*out_pidfd = dup (fds[fd_index]);
*out_pid = pid;

return TRUE;
}

static XdpAppInfo *
xdp_get_app_info_from_dbus_containers1 (GDBusConnection *connection,
const char *sender,
guint32 pid,
GCancellable *cancellable,
GError **error)
{
g_autoptr(GDBusMessage) msg = NULL;
g_autoptr(GDBusMessage) reply = NULL;
g_autoptr(GError) local_error = NULL;
int pidfd;
guint32 pid;

if (!xdp_get_app_info_get_pidfd (connection, sender, cancellable,
&pidfd, &pid, error))
return NULL;

msg = g_dbus_message_new_method_call (DBUS_NAME_DBUS,
DBUS_PATH_DBUS,
Expand Down Expand Up @@ -987,48 +1118,10 @@ xdp_get_app_info_from_dbus_containers1 (GDBusConnection *connection,
}

return xdp_get_app_info_from_connection_info (g_dbus_message_get_body (reply),
pidfd,
error);
}

static gboolean
xdp_get_app_info_get_pid (GDBusConnection *connection,
const char *sender,
GCancellable *cancellable,
GError **error,
guint32 *out_pid)
{
g_autoptr(GDBusMessage) msg = NULL;
g_autoptr(GDBusMessage) reply = NULL;
g_autoptr(XdpAppInfo) app_info = NULL;
GVariant *body;

msg = g_dbus_message_new_method_call (DBUS_NAME_DBUS,
DBUS_PATH_DBUS,
DBUS_INTERFACE_DBUS,
"GetConnectionUnixProcessID");
g_dbus_message_set_body (msg, g_variant_new ("(s)", sender));

reply = g_dbus_connection_send_message_with_reply_sync (connection, msg,
G_DBUS_SEND_MESSAGE_FLAGS_NONE,
30000,
NULL,
cancellable,
error);
if (reply == NULL)
return FALSE;

if (g_dbus_message_get_message_type (reply) == G_DBUS_MESSAGE_TYPE_ERROR)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Can't find peer pid");
return FALSE;
}

body = g_dbus_message_get_body (reply);
g_variant_get (body, "(u)", out_pid);

return TRUE;
}

static XdpAppInfo *
lookup_cached_app_info_by_sender (const char *sender)
{
Expand All @@ -1054,21 +1147,17 @@ xdp_invocation_lookup_app_info_sync (GDBusMethodInvocation *invocation,
GDBusConnection *connection = g_dbus_method_invocation_get_connection (invocation);
const gchar *sender = g_dbus_method_invocation_get_sender (invocation);
XdpAppInfo *app_info;
guint32 pid = 0;

app_info = lookup_cached_app_info_by_sender (sender);
if (app_info)
return app_info;

if (!xdp_get_app_info_get_pid (connection, sender, cancellable, error, &pid))
return NULL;

app_info = xdp_get_app_info_from_dbus_containers1 (connection, sender, pid, cancellable, error);
app_info = xdp_get_app_info_from_dbus_containers1 (connection, sender, cancellable, error);
if (!app_info && !g_error_matches (*error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED))
return NULL;

if (!app_info)
app_info = xdp_get_app_info_from_pid (pid, error);
app_info = xdp_get_app_info_from_pid (connection, sender, cancellable, error);

if (!app_info)
return NULL;
Expand Down

0 comments on commit 99f7894

Please sign in to comment.