mirror of
https://git.proxmox.com/git/fwupd
synced 2025-08-15 04:23:21 +00:00
Use UDisks to find out if swap devices are encrypted
Using a heuristic is certainly not awesome.
This commit is contained in:
parent
2b188c8488
commit
0bdf561035
@ -2196,8 +2196,14 @@ fu_common_get_block_devices (GError **error)
|
|||||||
g_variant_new ("(a{sv})", &builder),
|
g_variant_new ("(a{sv})", &builder),
|
||||||
G_DBUS_CALL_FLAGS_NONE,
|
G_DBUS_CALL_FLAGS_NONE,
|
||||||
-1, NULL, error);
|
-1, NULL, error);
|
||||||
if (output == NULL)
|
if (output == NULL) {
|
||||||
|
if (error != NULL)
|
||||||
|
g_dbus_error_strip_remote_error (*error);
|
||||||
|
g_prefix_error (error, "failed to call %s.%s(): ",
|
||||||
|
UDISKS_DBUS_SERVICE,
|
||||||
|
"GetBlockDevices");
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
devices = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
|
devices = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
|
||||||
g_variant_get (output, "(ao)", &iter);
|
g_variant_get (output, "(ao)", &iter);
|
||||||
while (g_variant_iter_next (iter, "&o", &obj)) {
|
while (g_variant_iter_next (iter, "&o", &obj)) {
|
||||||
@ -2294,6 +2300,90 @@ fu_common_get_volumes_by_kind (const gchar *kind, GError **error)
|
|||||||
return g_steal_pointer (&volumes);
|
return g_steal_pointer (&volumes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fu_common_get_volume_by_device:
|
||||||
|
* @device: A device string, typcically starting with `/dev/`
|
||||||
|
* @error: A #GError or NULL
|
||||||
|
*
|
||||||
|
* Finds the first volume from the specified device.
|
||||||
|
*
|
||||||
|
* Returns: (transfer full): a #GPtrArray, or %NULL if the kind was not found
|
||||||
|
*
|
||||||
|
* Since: 1.5.1
|
||||||
|
**/
|
||||||
|
FuVolume *
|
||||||
|
fu_common_get_volume_by_device (const gchar *device, GError **error)
|
||||||
|
{
|
||||||
|
g_autoptr(GPtrArray) devices = NULL;
|
||||||
|
|
||||||
|
/* find matching block device */
|
||||||
|
devices = fu_common_get_block_devices (error);
|
||||||
|
if (devices == NULL)
|
||||||
|
return NULL;
|
||||||
|
for (guint i = 0; i < devices->len; i++) {
|
||||||
|
GDBusProxy *proxy_blk = g_ptr_array_index (devices, i);
|
||||||
|
g_autoptr(GVariant) val = NULL;
|
||||||
|
val = g_dbus_proxy_get_cached_property (proxy_blk, "Device");
|
||||||
|
if (val == NULL)
|
||||||
|
continue;
|
||||||
|
if (g_strcmp0 (g_variant_get_bytestring (val), device) == 0) {
|
||||||
|
return g_object_new (FU_TYPE_VOLUME,
|
||||||
|
"proxy-block", proxy_blk,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* failed */
|
||||||
|
g_set_error (error,
|
||||||
|
G_IO_ERROR,
|
||||||
|
G_IO_ERROR_NOT_FOUND,
|
||||||
|
"no volumes for device %s",
|
||||||
|
device);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fu_common_get_volume_by_devnum:
|
||||||
|
* @devicenum: A device number
|
||||||
|
* @error: A #GError or NULL
|
||||||
|
*
|
||||||
|
* Finds the first volume from the specified device.
|
||||||
|
*
|
||||||
|
* Returns: (transfer full): a #GPtrArray, or %NULL if the kind was not found
|
||||||
|
*
|
||||||
|
* Since: 1.5.1
|
||||||
|
**/
|
||||||
|
FuVolume *
|
||||||
|
fu_common_get_volume_by_devnum (guint32 devnum, GError **error)
|
||||||
|
{
|
||||||
|
g_autoptr(GPtrArray) devices = NULL;
|
||||||
|
|
||||||
|
/* find matching block device */
|
||||||
|
devices = fu_common_get_block_devices (error);
|
||||||
|
if (devices == NULL)
|
||||||
|
return NULL;
|
||||||
|
for (guint i = 0; i < devices->len; i++) {
|
||||||
|
GDBusProxy *proxy_blk = g_ptr_array_index (devices, i);
|
||||||
|
g_autoptr(GVariant) val = NULL;
|
||||||
|
val = g_dbus_proxy_get_cached_property (proxy_blk, "DeviceNumber");
|
||||||
|
if (val == NULL)
|
||||||
|
continue;
|
||||||
|
if (devnum == g_variant_get_uint64 (val)) {
|
||||||
|
return g_object_new (FU_TYPE_VOLUME,
|
||||||
|
"proxy-block", proxy_blk,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* failed */
|
||||||
|
g_set_error (error,
|
||||||
|
G_IO_ERROR,
|
||||||
|
G_IO_ERROR_NOT_FOUND,
|
||||||
|
"no volumes for devnum %u",
|
||||||
|
devnum);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fu_common_get_esp_default:
|
* fu_common_get_esp_default:
|
||||||
* @error: A #GError or NULL
|
* @error: A #GError or NULL
|
||||||
|
@ -238,6 +238,10 @@ gboolean fu_common_is_cpu_intel (void);
|
|||||||
gboolean fu_common_is_live_media (void);
|
gboolean fu_common_is_live_media (void);
|
||||||
GPtrArray *fu_common_get_volumes_by_kind (const gchar *kind,
|
GPtrArray *fu_common_get_volumes_by_kind (const gchar *kind,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
FuVolume *fu_common_get_volume_by_device (const gchar *device,
|
||||||
|
GError **error);
|
||||||
|
FuVolume *fu_common_get_volume_by_devnum (guint32 devnum,
|
||||||
|
GError **error);
|
||||||
FuVolume *fu_common_get_esp_for_path (const gchar *esp_path,
|
FuVolume *fu_common_get_esp_for_path (const gchar *esp_path,
|
||||||
GError **error);
|
GError **error);
|
||||||
FuVolume *fu_common_get_esp_default (GError **error);
|
FuVolume *fu_common_get_esp_default (GError **error);
|
||||||
|
@ -672,6 +672,8 @@ LIBFWUPDPLUGIN_1.5.0 {
|
|||||||
|
|
||||||
LIBFWUPDPLUGIN_1.5.1 {
|
LIBFWUPDPLUGIN_1.5.1 {
|
||||||
global:
|
global:
|
||||||
|
fu_common_get_volume_by_device;
|
||||||
|
fu_common_get_volume_by_devnum;
|
||||||
fu_device_add_possible_plugin;
|
fu_device_add_possible_plugin;
|
||||||
fu_efivar_space_used;
|
fu_efivar_space_used;
|
||||||
fu_volume_is_encrypted;
|
fu_volume_is_encrypted;
|
||||||
|
@ -13,46 +13,134 @@
|
|||||||
|
|
||||||
struct _FuLinuxSwap {
|
struct _FuLinuxSwap {
|
||||||
GObject parent_instance;
|
GObject parent_instance;
|
||||||
gboolean encrypted;
|
guint encrypted_cnt;
|
||||||
gboolean enabled;
|
guint enabled_cnt;
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE (FuLinuxSwap, fu_linux_swap, G_TYPE_OBJECT)
|
G_DEFINE_TYPE (FuLinuxSwap, fu_linux_swap, G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
static gchar *
|
||||||
|
fu_strdup_nospaces (const gchar *line)
|
||||||
|
{
|
||||||
|
GString *str = g_string_new (NULL);
|
||||||
|
for (guint i = 0; line[i] != '\0' && !g_ascii_isspace (line[i]); i++)
|
||||||
|
g_string_append_c (str, line[i]);
|
||||||
|
return g_string_free (str, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
fu_linux_swap_verify_partition (FuLinuxSwap *self, const gchar *fn, GError **error)
|
||||||
|
{
|
||||||
|
g_autoptr(FuVolume) volume = NULL;
|
||||||
|
|
||||||
|
/* find the device */
|
||||||
|
volume = fu_common_get_volume_by_device (fn, error);
|
||||||
|
if (volume == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* this isn't technically encrypted, but isn't on disk in plaintext */
|
||||||
|
if (g_str_has_prefix (fn, "/dev/zram")) {
|
||||||
|
g_debug ("%s is zram, assuming encrypted", fn);
|
||||||
|
self->encrypted_cnt++;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* is this mount point encrypted */
|
||||||
|
if (fu_volume_is_encrypted (volume)) {
|
||||||
|
g_debug ("%s partition is encrypted", fn);
|
||||||
|
self->encrypted_cnt++;
|
||||||
|
} else {
|
||||||
|
g_debug ("%s partition is unencrypted", fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* success */
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
fu_linux_swap_verify_file (FuLinuxSwap *self, const gchar *fn, GError **error)
|
||||||
|
{
|
||||||
|
guint32 devnum;
|
||||||
|
g_autoptr(GFile) file = NULL;
|
||||||
|
g_autoptr(GFileInfo) info = NULL;
|
||||||
|
g_autoptr(FuVolume) volume = NULL;
|
||||||
|
|
||||||
|
/* get the device number for the file */
|
||||||
|
file = g_file_new_for_path (fn);
|
||||||
|
info = g_file_query_info (file, G_FILE_ATTRIBUTE_UNIX_DEVICE,
|
||||||
|
G_FILE_QUERY_INFO_NONE, NULL, error);
|
||||||
|
if (info == NULL)
|
||||||
|
return FALSE;
|
||||||
|
devnum = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_DEVICE);
|
||||||
|
|
||||||
|
/* find the device */
|
||||||
|
volume = fu_common_get_volume_by_devnum (devnum, error);
|
||||||
|
if (volume == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* is this mount point encrypted */
|
||||||
|
if (fu_volume_is_encrypted (volume)) {
|
||||||
|
g_debug ("%s file is encrypted", fn);
|
||||||
|
self->encrypted_cnt++;
|
||||||
|
} else {
|
||||||
|
g_debug ("%s file is unencrypted", fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* success */
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
FuLinuxSwap *
|
FuLinuxSwap *
|
||||||
fu_linux_swap_new (const gchar *buf, gsize bufsz, GError **error)
|
fu_linux_swap_new (const gchar *buf, gsize bufsz, GError **error)
|
||||||
{
|
{
|
||||||
FuLinuxSwap *self = g_object_new (FU_TYPE_LINUX_SWAP, NULL);
|
FuLinuxSwap *self = g_object_new (FU_TYPE_LINUX_SWAP, NULL);
|
||||||
g_auto(GStrv) lines = NULL;
|
g_auto(GStrv) lines = NULL;
|
||||||
|
|
||||||
|
/* look at each line in /proc/swaps */
|
||||||
if (bufsz == 0)
|
if (bufsz == 0)
|
||||||
bufsz = strlen (buf);
|
bufsz = strlen (buf);
|
||||||
lines = fu_common_strnsplit (buf, bufsz, "\n", -1);
|
lines = fu_common_strnsplit (buf, bufsz, "\n", -1);
|
||||||
if (g_strv_length (lines) > 2) {
|
if (g_strv_length (lines) > 2) {
|
||||||
self->enabled = TRUE;
|
|
||||||
for (guint i = 1; lines[i] != NULL && lines[i][0] != '\0'; i++) {
|
for (guint i = 1; lines[i] != NULL && lines[i][0] != '\0'; i++) {
|
||||||
if (g_str_has_prefix (lines[i], "/dev/dm-") ||
|
g_autofree gchar *fn = NULL;
|
||||||
g_str_has_prefix (lines[i], "/dev/mapper")) {
|
g_autofree gchar *ty = NULL;
|
||||||
self->encrypted = TRUE;
|
|
||||||
break;
|
/* split */
|
||||||
|
if (g_utf8_strlen (lines[i], -1) < 45)
|
||||||
|
continue;
|
||||||
|
fn = fu_strdup_nospaces (lines[i]);
|
||||||
|
ty = fu_strdup_nospaces (lines[i] + 40);
|
||||||
|
|
||||||
|
/* partition, so use UDisks to see if backed by crypto */
|
||||||
|
if (g_strcmp0 (ty, "partition") == 0) {
|
||||||
|
self->enabled_cnt++;
|
||||||
|
if (!fu_linux_swap_verify_partition (self, fn, error))
|
||||||
|
return NULL;
|
||||||
|
} else if (g_strcmp0 (ty, "file") == 0) {
|
||||||
|
self->enabled_cnt++;
|
||||||
|
if (!fu_linux_swap_verify_file (self, fn, error))
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
g_warning ("unknown swap type: %s [%s]", ty, fn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* success if *all* the swap devices are encrypted */
|
||||||
gboolean
|
gboolean
|
||||||
fu_linux_swap_get_encrypted (FuLinuxSwap *self)
|
fu_linux_swap_get_encrypted (FuLinuxSwap *self)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (FU_IS_LINUX_SWAP (self), FALSE);
|
g_return_val_if_fail (FU_IS_LINUX_SWAP (self), FALSE);
|
||||||
return self->encrypted;
|
return self->enabled_cnt > 0 && self->enabled_cnt == self->encrypted_cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
fu_linux_swap_get_enabled (FuLinuxSwap *self)
|
fu_linux_swap_get_enabled (FuLinuxSwap *self)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (FU_IS_LINUX_SWAP (self), FALSE);
|
g_return_val_if_fail (FU_IS_LINUX_SWAP (self), FALSE);
|
||||||
return self->enabled;
|
return self->enabled_cnt > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -32,8 +32,16 @@ fu_linux_swap_plain_func (void)
|
|||||||
g_autoptr(GError) error = NULL;
|
g_autoptr(GError) error = NULL;
|
||||||
|
|
||||||
swap = fu_linux_swap_new ("Filename\t\t\t\tType\t\tSize\tUsed\tPriority\n"
|
swap = fu_linux_swap_new ("Filename\t\t\t\tType\t\tSize\tUsed\tPriority\n"
|
||||||
"/dev/nvme0n1p4 partition\t5962748\t0\t-2\n",
|
"/dev/nvme0n1p4 partition\t5962748\t0\t-2\n",
|
||||||
0, &error);
|
0, &error);
|
||||||
|
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) {
|
||||||
|
g_test_skip (error->message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN)) {
|
||||||
|
g_test_skip (error->message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
g_assert_no_error (error);
|
g_assert_no_error (error);
|
||||||
g_assert_nonnull (swap);
|
g_assert_nonnull (swap);
|
||||||
g_assert_true (fu_linux_swap_get_enabled (swap));
|
g_assert_true (fu_linux_swap_get_enabled (swap));
|
||||||
@ -47,8 +55,13 @@ fu_linux_swap_encrypted_func (void)
|
|||||||
g_autoptr(GError) error = NULL;
|
g_autoptr(GError) error = NULL;
|
||||||
|
|
||||||
swap = fu_linux_swap_new ("Filename\t\t\t\tType\t\tSize\tUsed\tPriority\n"
|
swap = fu_linux_swap_new ("Filename\t\t\t\tType\t\tSize\tUsed\tPriority\n"
|
||||||
"/dev/dm-1 partition\t5962748\t0\t-2\n",
|
"/dev/dm-1 partition\t5962748\t0\t-2\n",
|
||||||
0, &error);
|
0, &error);
|
||||||
|
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND) ||
|
||||||
|
g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN)) {
|
||||||
|
g_test_skip (error->message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
g_assert_no_error (error);
|
g_assert_no_error (error);
|
||||||
g_assert_nonnull (swap);
|
g_assert_nonnull (swap);
|
||||||
g_assert_true (fu_linux_swap_get_enabled (swap));
|
g_assert_true (fu_linux_swap_get_enabled (swap));
|
||||||
|
Loading…
Reference in New Issue
Block a user