diff --git a/contrib/fwupd.spec.in b/contrib/fwupd.spec.in index 22940d918..0bf4eb921 100644 --- a/contrib/fwupd.spec.in +++ b/contrib/fwupd.spec.in @@ -366,6 +366,7 @@ mkdir -p --mode=0700 $RPM_BUILD_ROOT%{_localstatedir}/lib/fwupd/gnupg %if 0%{?have_dell} %{_libdir}/fwupd-plugins-3/libfu_plugin_synaptics_mst.so %endif +%{_libdir}/fwupd-plugins-3/libfu_plugin_swap.so %{_libdir}/fwupd-plugins-3/libfu_plugin_synaptics_cxaudio.so %{_libdir}/fwupd-plugins-3/libfu_plugin_synaptics_prometheus.so %{_libdir}/fwupd-plugins-3/libfu_plugin_synaptics_rmi.so diff --git a/libfwupdplugin/fu-common.c b/libfwupdplugin/fu-common.c index 81dfa3296..19acec92f 100644 --- a/libfwupdplugin/fu-common.c +++ b/libfwupdplugin/fu-common.c @@ -1026,6 +1026,12 @@ fu_common_get_path (FuPathKind path_kind) if (tmp != NULL) return g_build_filename (tmp, FWUPD_LOCALSTATEDIR, NULL); return g_build_filename (FWUPD_LOCALSTATEDIR, NULL); + /* /proc */ + case FU_PATH_KIND_PROCFS: + tmp = g_getenv ("FWUPD_PROCFS"); + if (tmp != NULL) + return g_strdup (tmp); + return g_strdup ("/proc"); /* /sys/firmware */ case FU_PATH_KIND_SYSFSDIR_FW: tmp = g_getenv ("FWUPD_SYSFSFWDIR"); diff --git a/libfwupdplugin/fu-common.h b/libfwupdplugin/fu-common.h index 6ebc1a381..c61627285 100644 --- a/libfwupdplugin/fu-common.h +++ b/libfwupdplugin/fu-common.h @@ -53,6 +53,7 @@ typedef guint FuEndianType; * @FU_PATH_KIND_SYSFSDIR_FW: The sysfs firmware location (IE /sys/firmware) * @FU_PATH_KIND_SYSFSDIR_DRIVERS: The platform sysfs directory (IE /sys/bus/platform/drivers) * @FU_PATH_KIND_SYSFSDIR_TPM: The TPM sysfs directory (IE /sys/class/tpm) + * @FU_PATH_KIND_PROCFS: The procfs location (IE /proc) * @FU_PATH_KIND_POLKIT_ACTIONS: The directory for policy kit actions (IE /usr/share/polkit-1/actions/) * @FU_PATH_KIND_OFFLINE_TRIGGER: The file for the offline trigger (IE /system-update) * @FU_PATH_KIND_SYSFSDIR_SECURITY: The sysfs security location (IE /sys/kernel/security) @@ -71,6 +72,7 @@ typedef enum { FU_PATH_KIND_SYSFSDIR_FW, FU_PATH_KIND_SYSFSDIR_DRIVERS, FU_PATH_KIND_SYSFSDIR_TPM, + FU_PATH_KIND_PROCFS, FU_PATH_KIND_POLKIT_ACTIONS, FU_PATH_KIND_OFFLINE_TRIGGER, FU_PATH_KIND_SYSFSDIR_SECURITY, diff --git a/plugins/meson.build b/plugins/meson.build index 72de5661f..676ff5593 100644 --- a/plugins/meson.build +++ b/plugins/meson.build @@ -13,6 +13,7 @@ subdir('nitrokey') subdir('rts54hid') subdir('rts54hub') subdir('solokey') +subdir('swap') subdir('synaptics-cxaudio') subdir('synaptics-prometheus') subdir('test') diff --git a/plugins/swap/README.md b/plugins/swap/README.md new file mode 100644 index 000000000..6a963965b --- /dev/null +++ b/plugins/swap/README.md @@ -0,0 +1,8 @@ +Swap Support +============ + +Introduction +------------ + +This plugin checks if the currently available swap partitions and files are +all encrypted. diff --git a/plugins/swap/fu-plugin-swap.c b/plugins/swap/fu-plugin-swap.c new file mode 100644 index 000000000..697e9bb1d --- /dev/null +++ b/plugins/swap/fu-plugin-swap.c @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2020 Richard Hughes + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#include "config.h" + +#include "fu-plugin-vfuncs.h" +#include "fu-hash.h" +#include "fu-swap.h" + +struct FuPluginData { + GFileMonitor *monitor; +}; + +void +fu_plugin_init (FuPlugin *plugin) +{ + fu_plugin_alloc_data (plugin, sizeof (FuPluginData)); + fu_plugin_set_build_hash (plugin, FU_BUILD_HASH); +} + +void +fu_plugin_destroy (FuPlugin *plugin) +{ + FuPluginData *data = fu_plugin_get_data (plugin); + if (data->monitor != NULL) + g_object_unref (data->monitor); +} + +static void +fu_plugin_swap_changed_cb (GFileMonitor *monitor, + GFile *file, + GFile *other_file, + GFileMonitorEvent event_type, + gpointer user_data) +{ + g_debug ("swap changed"); +} + +gboolean +fu_plugin_startup (FuPlugin *plugin, GError **error) +{ + FuPluginData *data = fu_plugin_get_data (plugin); + gsize bufsz = 0; + g_autofree gchar *buf = NULL; + g_autofree gchar *fn = NULL; + g_autofree gchar *procfs = NULL; + g_autoptr(FuSwap) swap = NULL; + g_autoptr(GFile) file = NULL; + + procfs = fu_common_get_path (FU_PATH_KIND_PROCFS); + fn = g_build_filename (procfs, "swaps", NULL); + file = g_file_new_for_path (fn); + data->monitor = g_file_monitor (file, G_FILE_MONITOR_NONE, NULL, error); + if (data->monitor == NULL) + return FALSE; + g_signal_connect (data->monitor, "changed", + G_CALLBACK (fu_plugin_swap_changed_cb), plugin); + + /* load list of swaps */ + if (!g_file_get_contents (fn, &buf, &bufsz, error)) { + g_prefix_error (error, "could not open %s: ", fn); + return FALSE; + } + swap = fu_swap_new (buf, bufsz, error); + if (swap == NULL) { + g_prefix_error (error, "could not parse %s: ", fn); + return FALSE; + } + g_debug ("swap %s and %s", + fu_swap_get_enabled (swap) ? "enabled" : "disabled", + fu_swap_get_encrypted (swap) ? "encrypted" : "unencrypted"); + return TRUE; +} diff --git a/plugins/swap/fu-self-test.c b/plugins/swap/fu-self-test.c new file mode 100644 index 000000000..b07e699cd --- /dev/null +++ b/plugins/swap/fu-self-test.c @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2020 Richard Hughes + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#include "config.h" + +#include + +#include "fu-swap.h" + +#include "fwupd-error.h" + +static void +fu_swap_none_func (void) +{ + g_autoptr(FuSwap) swap = NULL; + g_autoptr(GError) error = NULL; + + swap = fu_swap_new ("Filename\t\t\t\tType\t\tSize\tUsed\tPriority\n", 0, &error); + g_assert_no_error (error); + g_assert_nonnull (swap); + g_assert_false (fu_swap_get_enabled (swap)); + g_assert_false (fu_swap_get_encrypted (swap)); +} + +static void +fu_swap_plain_func (void) +{ + g_autoptr(FuSwap) swap = NULL; + g_autoptr(GError) error = NULL; + + swap = fu_swap_new ("Filename\t\t\t\tType\t\tSize\tUsed\tPriority\n" + "/dev/nvme0n1p4 partition\t5962748\t0\t-2\n", + 0, &error); + g_assert_no_error (error); + g_assert_nonnull (swap); + g_assert_true (fu_swap_get_enabled (swap)); + g_assert_false (fu_swap_get_encrypted (swap)); +} + +static void +fu_swap_encrypted_func (void) +{ + g_autoptr(FuSwap) swap = NULL; + g_autoptr(GError) error = NULL; + + swap = fu_swap_new ("Filename\t\t\t\tType\t\tSize\tUsed\tPriority\n" + "/dev/dm-1 partition\t5962748\t0\t-2\n", + 0, &error); + g_assert_no_error (error); + g_assert_nonnull (swap); + g_assert_true (fu_swap_get_enabled (swap)); + g_assert_true (fu_swap_get_encrypted (swap)); +} + +int +main (int argc, char **argv) +{ + g_test_init (&argc, &argv, NULL); + + /* only critical and error are fatal */ + g_log_set_fatal_mask (NULL, G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL); + g_setenv ("G_MESSAGES_DEBUG", "all", TRUE); + + /* tests go here */ + g_test_add_func ("/swap/none", fu_swap_none_func); + g_test_add_func ("/swap/plain", fu_swap_plain_func); + g_test_add_func ("/swap/encrypted", fu_swap_encrypted_func); + return g_test_run (); +} diff --git a/plugins/swap/fu-swap.c b/plugins/swap/fu-swap.c new file mode 100644 index 000000000..e16a3c42d --- /dev/null +++ b/plugins/swap/fu-swap.c @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2020 Richard Hughes + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#include "config.h" + +#include + +#include "fu-common.h" +#include "fu-swap.h" + +struct _FuSwap { + GObject parent_instance; + gboolean encrypted; + gboolean enabled; +}; + +G_DEFINE_TYPE (FuSwap, fu_swap, G_TYPE_OBJECT) + +FuSwap * +fu_swap_new (const gchar *buf, gsize bufsz, GError **error) +{ + FuSwap *self = g_object_new (FU_TYPE_SWAP, NULL); + g_auto(GStrv) lines = NULL; + + 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; + } + } + } + return self; +} + +gboolean +fu_swap_get_encrypted (FuSwap *self) +{ + g_return_val_if_fail (FU_IS_SWAP (self), FALSE); + return self->encrypted; +} + +gboolean +fu_swap_get_enabled (FuSwap *self) +{ + g_return_val_if_fail (FU_IS_SWAP (self), FALSE); + return self->enabled; +} + +static void +fu_swap_class_init (FuSwapClass *klass) +{ +} + +static void +fu_swap_init (FuSwap *self) +{ +} diff --git a/plugins/swap/fu-swap.h b/plugins/swap/fu-swap.h new file mode 100644 index 000000000..006edb4be --- /dev/null +++ b/plugins/swap/fu-swap.h @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2020 Richard Hughes + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#pragma once + +#include + +#define FU_TYPE_SWAP (fu_swap_get_type ()) +G_DECLARE_FINAL_TYPE (FuSwap, fu_swap, FU, SWAP, GObject) + +FuSwap *fu_swap_new (const gchar *buf, + gsize bufsz, + GError **error); +gboolean fu_swap_get_enabled (FuSwap *self); +gboolean fu_swap_get_encrypted (FuSwap *self); diff --git a/plugins/swap/meson.build b/plugins/swap/meson.build new file mode 100644 index 000000000..7a13cdf81 --- /dev/null +++ b/plugins/swap/meson.build @@ -0,0 +1,48 @@ +cargs = ['-DG_LOG_DOMAIN="FuPluginSwap"'] + +shared_module('fu_plugin_swap', + fu_hash, + sources : [ + 'fu-plugin-swap.c', + 'fu-swap.c', + ], + include_directories : [ + root_incdir, + fwupd_incdir, + fwupdplugin_incdir, + ], + install : true, + install_dir: plugin_dir, + link_with : [ + fwupd, + fwupdplugin, + ], + c_args : cargs, + dependencies : [ + plugin_deps, + ], +) + +if get_option('tests') + e = executable( + 'swap-self-test', + fu_hash, + sources : [ + 'fu-self-test.c', + 'fu-swap.c', + ], + include_directories : [ + root_incdir, + fwupd_incdir, + fwupdplugin_incdir, + ], + dependencies : [ + plugin_deps, + ], + link_with : [ + fwupd, + fwupdplugin, + ], + ) + test('swap-self-test', e) +endif