mirror of
https://git.proxmox.com/git/fwupd
synced 2025-08-15 11:59:02 +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_DBUS_CALL_FLAGS_NONE,
|
||||
-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;
|
||||
}
|
||||
devices = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
|
||||
g_variant_get (output, "(ao)", &iter);
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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:
|
||||
* @error: A #GError or NULL
|
||||
|
@ -238,6 +238,10 @@ gboolean fu_common_is_cpu_intel (void);
|
||||
gboolean fu_common_is_live_media (void);
|
||||
GPtrArray *fu_common_get_volumes_by_kind (const gchar *kind,
|
||||
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,
|
||||
GError **error);
|
||||
FuVolume *fu_common_get_esp_default (GError **error);
|
||||
|
@ -672,6 +672,8 @@ LIBFWUPDPLUGIN_1.5.0 {
|
||||
|
||||
LIBFWUPDPLUGIN_1.5.1 {
|
||||
global:
|
||||
fu_common_get_volume_by_device;
|
||||
fu_common_get_volume_by_devnum;
|
||||
fu_device_add_possible_plugin;
|
||||
fu_efivar_space_used;
|
||||
fu_volume_is_encrypted;
|
||||
|
@ -13,46 +13,134 @@
|
||||
|
||||
struct _FuLinuxSwap {
|
||||
GObject parent_instance;
|
||||
gboolean encrypted;
|
||||
gboolean enabled;
|
||||
guint encrypted_cnt;
|
||||
guint enabled_cnt;
|
||||
};
|
||||
|
||||
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 *
|
||||
fu_linux_swap_new (const gchar *buf, gsize bufsz, GError **error)
|
||||
{
|
||||
FuLinuxSwap *self = g_object_new (FU_TYPE_LINUX_SWAP, NULL);
|
||||
g_auto(GStrv) lines = NULL;
|
||||
|
||||
/* look at each line in /proc/swaps */
|
||||
if (bufsz == 0)
|
||||
bufsz = strlen (buf);
|
||||
lines = fu_common_strnsplit (buf, bufsz, "\n", -1);
|
||||
if (g_strv_length (lines) > 2) {
|
||||
self->enabled = TRUE;
|
||||
for (guint i = 1; lines[i] != NULL && lines[i][0] != '\0'; i++) {
|
||||
if (g_str_has_prefix (lines[i], "/dev/dm-") ||
|
||||
g_str_has_prefix (lines[i], "/dev/mapper")) {
|
||||
self->encrypted = TRUE;
|
||||
break;
|
||||
g_autofree gchar *fn = NULL;
|
||||
g_autofree gchar *ty = NULL;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* success if *all* the swap devices are encrypted */
|
||||
gboolean
|
||||
fu_linux_swap_get_encrypted (FuLinuxSwap *self)
|
||||
{
|
||||
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
|
||||
fu_linux_swap_get_enabled (FuLinuxSwap *self)
|
||||
{
|
||||
g_return_val_if_fail (FU_IS_LINUX_SWAP (self), FALSE);
|
||||
return self->enabled;
|
||||
return self->enabled_cnt > 0;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -34,6 +34,14 @@ fu_linux_swap_plain_func (void)
|
||||
swap = fu_linux_swap_new ("Filename\t\t\t\tType\t\tSize\tUsed\tPriority\n"
|
||||
"/dev/nvme0n1p4 partition\t5962748\t0\t-2\n",
|
||||
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_nonnull (swap);
|
||||
g_assert_true (fu_linux_swap_get_enabled (swap));
|
||||
@ -49,6 +57,11 @@ fu_linux_swap_encrypted_func (void)
|
||||
swap = fu_linux_swap_new ("Filename\t\t\t\tType\t\tSize\tUsed\tPriority\n"
|
||||
"/dev/dm-1 partition\t5962748\t0\t-2\n",
|
||||
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_nonnull (swap);
|
||||
g_assert_true (fu_linux_swap_get_enabled (swap));
|
||||
|
Loading…
Reference in New Issue
Block a user