A new configuration file called secret.conf is introduced to
let the user configure the path to the secrets encryption key.
This key will be used to encrypt/decrypt the secrets in libvirt.
By default the path is set to the runtime directory
/run/libvirt/secrets, and it is commented in the config file.
After parsing the file, the virtsecretd driver checks if an
encryption key is present in the path and is valid.
If no encryption key is present in the path, then
the service will by default use the encryption key stored in the
CREDENTIALS_DIRECTORY.
Add logic to parse the encryption key file and store the key.
It also checks for the encrypt_data attribute in the config file.
The encryption and decryption logic will be added in the subsequent patches.
Signed-off-by: Arun Menon <armenon@redhat.com>
---
include/libvirt/virterror.h | 1 +
libvirt.spec.in | 3 +
po/POTFILES | 1 +
src/secret/libvirt_secrets.aug | 40 ++++++
src/secret/meson.build | 19 +++
src/secret/secret.conf.in | 14 ++
src/secret/secret_config.c | 171 +++++++++++++++++++++++++
src/secret/secret_config.h | 40 ++++++
src/secret/secret_driver.c | 9 ++
src/secret/test_libvirt_secrets.aug.in | 6 +
src/util/virerror.c | 3 +
11 files changed, 307 insertions(+)
create mode 100644 src/secret/libvirt_secrets.aug
create mode 100644 src/secret/secret.conf.in
create mode 100644 src/secret/secret_config.c
create mode 100644 src/secret/secret_config.h
create mode 100644 src/secret/test_libvirt_secrets.aug.in
diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h
index f02da046a3..5d9e06b4bb 100644
--- a/include/libvirt/virterror.h
+++ b/include/libvirt/virterror.h
@@ -353,6 +353,7 @@ typedef enum {
command within timeout (Since: 11.2.0) */
VIR_ERR_AGENT_COMMAND_FAILED = 113, /* guest agent responded with failure
to a command (Since: 11.2.0) */
+ VIR_ERR_INVALID_ENCR_KEY_SECRET = 114, /* encrypion key is invalid (Since: 12.0.0) */
# ifdef VIR_ENUM_SENTINELS
VIR_ERR_NUMBER_LAST /* (Since: 5.0.0) */
diff --git a/libvirt.spec.in b/libvirt.spec.in
index 8505a220c7..bb1dcc367f 100644
--- a/libvirt.spec.in
+++ b/libvirt.spec.in
@@ -2250,6 +2250,9 @@ exit 0
%config(noreplace) %{_sysconfdir}/libvirt/virtsecretd.conf
%{_datadir}/augeas/lenses/virtsecretd.aug
%{_datadir}/augeas/lenses/tests/test_virtsecretd.aug
+%{_datadir}/augeas/lenses/libvirt_secrets.aug
+%{_datadir}/augeas/lenses/tests/test_libvirt_secrets.aug
+%config(noreplace) %{_sysconfdir}/libvirt/secret.conf
%{_unitdir}/virtsecretd.service
%{_unitdir}/virt-secret-init-encryption.service
%{_unitdir}/virtsecretd.socket
diff --git a/po/POTFILES b/po/POTFILES
index f0aad35c8c..045981a9ac 100644
--- a/po/POTFILES
+++ b/po/POTFILES
@@ -233,6 +233,7 @@ src/rpc/virnettlscert.c
src/rpc/virnettlsconfig.c
src/rpc/virnettlscontext.c
src/secret/secret_driver.c
+src/secret/secret_config.c
src/security/security_apparmor.c
src/security/security_dac.c
src/security/security_driver.c
diff --git a/src/secret/libvirt_secrets.aug b/src/secret/libvirt_secrets.aug
new file mode 100644
index 0000000000..8dda373e62
--- /dev/null
+++ b/src/secret/libvirt_secrets.aug
@@ -0,0 +1,40 @@
+(* /etc/libvirt/secret.conf *)
+
+module Libvirt_secrets =
+ autoload xfm
+
+ let eol = del /[ \t]*\n/ "\n"
+ let value_sep = del /[ \t]*=[ \t]*/ " = "
+ let indent = del /[ \t]*/ ""
+
+ let array_sep = del /,[ \t\n]*/ ", "
+ let array_start = del /\[[ \t\n]*/ "[ "
+ let array_end = del /\]/ "]"
+
+ let str_val = del /\"/ "\"" . store /[^\"]*/ . del /\"/ "\""
+ let bool_val = store /0|1/
+ let int_val = store /[0-9]+/
+ let str_array_element = [ seq "el" . str_val ] . del /[ \t\n]*/ ""
+ let str_array_val = counter "el" . array_start . ( str_array_element . ( array_sep . str_array_element ) * ) ? . array_end
+
+ let str_entry (kw:string) = [ key kw . value_sep . str_val ]
+ let bool_entry (kw:string) = [ key kw . value_sep . bool_val ]
+ let int_entry (kw:string) = [ key kw . value_sep . int_val ]
+ let str_array_entry (kw:string) = [ key kw . value_sep . str_array_val ]
+
+ let secrets_entry = str_entry "secrets_encryption_key"
+ | bool_entry "encrypt_data"
+
+ (* Each entry in the config is one of the following three ... *)
+ let entry = secrets_entry
+ let comment = [ label "#comment" . del /#[ \t]*/ "# " . store /([^ \t\n][^\n]*)?/ . del /\n/ "\n" ]
+ let empty = [ label "#empty" . eol ]
+
+ let record = indent . entry . eol
+
+ let lns = ( record | comment | empty ) *
+
+ let filter = incl "/etc/libvirt/secret.conf"
+ . Util.stdexcl
+
+ let xfm = transform lns filter
diff --git a/src/secret/meson.build b/src/secret/meson.build
index b0977eadc8..c29b992190 100644
--- a/src/secret/meson.build
+++ b/src/secret/meson.build
@@ -1,5 +1,6 @@
secret_driver_sources = [
'secret_driver.c',
+ 'secret_config.c',
]
driver_source_files += files(secret_driver_sources)
@@ -27,6 +28,24 @@ if conf.has('WITH_SECRETS')
],
}
+ secret_conf = configure_file(
+ input: 'secret.conf.in',
+ output: 'secret.conf',
+ copy: true
+ )
+ virt_conf_files += secret_conf
+
+ virt_aug_files += files('libvirt_secrets.aug')
+
+ virt_test_aug_files += {
+ 'name': 'test_libvirt_secrets.aug',
+ 'aug': files('test_libvirt_secrets.aug.in'),
+ 'conf': files('secret.conf.in'),
+ 'test_name': 'libvirt_secrets',
+ 'test_srcdir': meson.current_source_dir(),
+ 'test_builddir': meson.current_build_dir(),
+ }
+
virt_daemon_confs += {
'name': 'virtsecretd',
}
diff --git a/src/secret/secret.conf.in b/src/secret/secret.conf.in
new file mode 100644
index 0000000000..a231c48f8d
--- /dev/null
+++ b/src/secret/secret.conf.in
@@ -0,0 +1,14 @@
+#
+# Configuration file for the secrets driver.
+#
+# The secret encryption key is used to override default encryption
+# key path. The user can create an encryption key and set the secret_encryption_key
+# to the path on which it resides.
+# The key must be 32-bytes long.
+#secrets_encryption_key = "/run/libvirt/secrets/secret-encryption-key"
+
+# The encrypt_data setting is used to indicate if the encryption is on or off.
+# 0 indicates off and 1 indicates on. By default it is on
+# if secrets_encryption_key is set to a non-NULL
+# path, or if a systemd credential named "secrets-encryption-key" exists.
+#encrypt_data = 1
diff --git a/src/secret/secret_config.c b/src/secret/secret_config.c
new file mode 100644
index 0000000000..b63567944e
--- /dev/null
+++ b/src/secret/secret_config.c
@@ -0,0 +1,171 @@
+/*
+ * secret_config.c: secret.conf config file handling
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include <config.h>
+#include <fcntl.h>
+#include "configmake.h"
+#include "datatypes.h"
+#include "virlog.h"
+#include "virerror.h"
+#include "virfile.h"
+#include "virutil.h"
+#include "virsecureerase.h"
+#include "secret_config.h"
+
+
+#define VIR_FROM_THIS VIR_FROM_SECRET
+
+VIR_LOG_INIT("secret.secret_config");
+
+static virClass *virSecretDaemonConfigClass;
+static void virSecretDaemonConfigDispose(void *obj);
+
+static int
+virSecretConfigOnceInit(void)
+{
+ if (!VIR_CLASS_NEW(virSecretDaemonConfig, virClassForObject()))
+ return -1;
+
+ return 0;
+}
+
+
+VIR_ONCE_GLOBAL_INIT(virSecretConfig);
+
+
+int
+virSecretDaemonConfigFilePath(bool privileged, char **configfile)
+{
+ if (privileged) {
+ *configfile = g_strdup(SYSCONFDIR "/libvirt/secret.conf");
+ } else {
+ g_autofree char *configdir = NULL;
+
+ configdir = virGetUserConfigDirectory();
+
+ *configfile = g_strdup_printf("%s/secret.conf", configdir);
+ }
+
+ return 0;
+}
+
+
+static int
+virSecretLoadDaemonConfig(virSecretDaemonConfig *cfg,
+ const char *filename)
+{
+ g_autoptr(virConf) conf = NULL;
+ int res;
+
+ if (virFileExists(filename)) {
+ conf = virConfReadFile(filename, 0);
+ if (!conf)
+ return -1;
+ res = virConfGetValueBool(conf, "encrypt_data", &cfg->encryptData);
+ if (res < 0) {
+ return -1;
+ } else if (res == 1) {
+ cfg->encryptDataWasSet = true;
+ } else {
+ cfg->encryptDataWasSet = false;
+ }
+
+ if (virConfGetValueString(conf, "secrets_encryption_key",
+ &cfg->secretsEncryptionKeyPath) < 0) {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+
+static int virGetSecretsEncryptionKey(virSecretDaemonConfig *cfg,
+ uint8_t **secretsEncryptionKey,
+ size_t *secretsKeyLen)
+{
+ VIR_AUTOCLOSE fd = -1;
+ int encryption_key_length;
+
+ if ((encryption_key_length = virFileReadAll(cfg->secretsEncryptionKeyPath, VIR_SECRETS_ENCRYPTION_KEY_LEN, (char**)secretsEncryptionKey)) < 0) {
+ return -1;
+ }
+ if (encryption_key_length != VIR_SECRETS_ENCRYPTION_KEY_LEN) {
+ virReportError(VIR_ERR_INVALID_ENCR_KEY_SECRET,
+ _("Encryption key length must be '%1$d' '%2$s'"),
+ VIR_SECRETS_ENCRYPTION_KEY_LEN, cfg->secretsEncryptionKeyPath);
+ }
+
+ *secretsKeyLen = (size_t)encryption_key_length;
+ return 0;
+}
+
+
+virSecretDaemonConfig *
+virSecretDaemonConfigNew(bool privileged)
+{
+ g_autoptr(virSecretDaemonConfig) cfg = NULL;
+ g_autofree char *configdir = NULL;
+ g_autofree char *configfile = NULL;
+ const char *credentials_directory;
+
+ if (virSecretConfigInitialize() < 0)
+ return NULL;
+
+ if (!(cfg = virObjectNew(virSecretDaemonConfigClass)))
+ return NULL;
+
+ cfg->secretsEncryptionKeyPath = NULL;
+
+ if (virSecretDaemonConfigFilePath(privileged, &configfile) < 0)
+ return NULL;
+
+ if (virSecretLoadDaemonConfig(cfg, configfile) < 0)
+ return NULL;
+
+ credentials_directory = getenv("CREDENTIALS_DIRECTORY");
+
+ if (!cfg->secretsEncryptionKeyPath && credentials_directory) {
+ cfg->secretsEncryptionKeyPath = g_strdup_printf("%s/secrets-encryption-key",
+ credentials_directory);
+ if (!virFileExists(cfg->secretsEncryptionKeyPath)) {
+ g_clear_pointer(&cfg->secretsEncryptionKeyPath, g_free);
+ }
+ }
+
+ if (!cfg->encryptDataWasSet) {
+ if (!cfg->secretsEncryptionKeyPath) {
+ /* No path specified by user or environment, disable encryption */
+ cfg->encryptData = false;
+ } else {
+ cfg->encryptData = true;
+ }
+ } else {
+ if (cfg->encryptData) {
+ if (!cfg->secretsEncryptionKeyPath) {
+ /* Built-in default path must be used */
+ cfg->secretsEncryptionKeyPath = g_strdup("/run/libvirt/secrets/encryption-key");
+ }
+ }
+ }
+ VIR_DEBUG("Secrets encryption key path: %s", NULLSTR(cfg->secretsEncryptionKeyPath));
+
+ if (cfg->encryptData) {
+ if (virGetSecretsEncryptionKey(cfg, &cfg->secretsEncryptionKey, &cfg->secretsKeyLen) < 0) {
+ return NULL;
+ }
+ }
+ return g_steal_pointer(&cfg);
+}
+
+
+static void
+virSecretDaemonConfigDispose(void *obj)
+{
+ virSecretDaemonConfig *cfg = obj;
+
+ virSecureErase(cfg->secretsEncryptionKey, cfg->secretsKeyLen);
+ g_free(cfg->secretsEncryptionKeyPath);
+}
diff --git a/src/secret/secret_config.h b/src/secret/secret_config.h
new file mode 100644
index 0000000000..888acf272b
--- /dev/null
+++ b/src/secret/secret_config.h
@@ -0,0 +1,40 @@
+/*
+ * secret_config.h: secret.conf config file handling
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#pragma once
+
+#include "internal.h"
+#include "virinhibitor.h"
+#include "secret_event.h"
+#define VIR_SECRETS_ENCRYPTION_KEY_LEN 32
+
+typedef struct _virSecretDaemonConfig virSecretDaemonConfig;
+struct _virSecretDaemonConfig {
+ virObject parent;
+ /* secrets encryption key path from secret.conf file */
+ char *secretsEncryptionKeyPath;
+
+ /* Store the key to encrypt secrets on the disk */
+ unsigned char *secretsEncryptionKey;
+
+ size_t secretsKeyLen;
+
+ /* Indicates if the newly written secrets are encrypted or not.
+ */
+ bool encryptData;
+
+ /* Indicates if the config file has encrypt_data set or not.
+ */
+ bool encryptDataWasSet;
+};
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(virSecretDaemonConfig, virObjectUnref);
+
+int virSecretDaemonConfigFilePath(bool privileged, char **configfile);
+virSecretDaemonConfig *virSecretDaemonConfigNew(bool privileged);
+int virSecretDaemonConfigLoadFile(virSecretDaemonConfig *data,
+ const char *filename,
+ bool allow_missing);
diff --git a/src/secret/secret_driver.c b/src/secret/secret_driver.c
index 04c3ca49f1..408a629ea0 100644
--- a/src/secret/secret_driver.c
+++ b/src/secret/secret_driver.c
@@ -70,6 +70,9 @@ struct _virSecretDriverState {
/* Immutable pointer, self-locking APIs */
virInhibitor *inhibitor;
+
+ /* Settings from secret.conf file */
+ virSecretDaemonConfig *config;
};
static virSecretDriverState *driver;
@@ -454,6 +457,7 @@ secretStateCleanupLocked(void)
VIR_FREE(driver->configDir);
virObjectUnref(driver->secretEventState);
+ virObjectUnref(driver->config);
virInhibitorFree(driver->inhibitor);
if (driver->lockFD != -1)
@@ -518,6 +522,8 @@ secretStateInitialize(bool privileged,
driver->stateDir);
goto error;
}
+ if (!(driver->config = virSecretDaemonConfigNew(driver->privileged)))
+ goto error;
driver->inhibitor = virInhibitorNew(
VIR_INHIBITOR_WHAT_NONE,
@@ -553,6 +559,9 @@ secretStateReload(void)
if (!driver)
return -1;
+ if (!(driver->config = virSecretDaemonConfigNew(driver->privileged)))
+ return -1;
+
ignore_value(virSecretLoadAllConfigs(driver->secrets, driver->configDir));
return 0;
diff --git a/src/secret/test_libvirt_secrets.aug.in b/src/secret/test_libvirt_secrets.aug.in
new file mode 100644
index 0000000000..1bb205e0f2
--- /dev/null
+++ b/src/secret/test_libvirt_secrets.aug.in
@@ -0,0 +1,6 @@
+module Test_libvirt_secrets =
+ @CONFIG@
+
+ test Libvirt_secrets.lns get conf =
+{ "secrets_encryption_key" = "/run/libvirt/secrets/secret-encryption-key" }
+{ "encrypt_data" = "1" }
diff --git a/src/util/virerror.c b/src/util/virerror.c
index abb014b522..b7d23f81c7 100644
--- a/src/util/virerror.c
+++ b/src/util/virerror.c
@@ -1296,6 +1296,9 @@ static const virErrorMsgTuple virErrorMsgStrings[] = {
[VIR_ERR_AGENT_COMMAND_FAILED] = {
N_("guest agent command failed"),
N_("guest agent command failed: %1$s") },
+ [VIR_ERR_INVALID_ENCR_KEY_SECRET] = {
+ N_("Invalid encryption key for the secret"),
+ N_("Invalid encryption key for the secret: %1$s") },
};
G_STATIC_ASSERT(G_N_ELEMENTS(virErrorMsgStrings) == VIR_ERR_NUMBER_LAST);
--
2.51.1
On Tue, Dec 09, 2025 at 01:22:29 +0530, Arun Menon via Devel wrote:
> A new configuration file called secret.conf is introduced to
> let the user configure the path to the secrets encryption key.
> This key will be used to encrypt/decrypt the secrets in libvirt.
>
> By default the path is set to the runtime directory
> /run/libvirt/secrets, and it is commented in the config file.
> After parsing the file, the virtsecretd driver checks if an
> encryption key is present in the path and is valid.
>
> If no encryption key is present in the path, then
> the service will by default use the encryption key stored in the
> CREDENTIALS_DIRECTORY.
>
> Add logic to parse the encryption key file and store the key.
> It also checks for the encrypt_data attribute in the config file.
> The encryption and decryption logic will be added in the subsequent patches.
>
> Signed-off-by: Arun Menon <armenon@redhat.com>
> ---
> include/libvirt/virterror.h | 1 +
> libvirt.spec.in | 3 +
> po/POTFILES | 1 +
> src/secret/libvirt_secrets.aug | 40 ++++++
> src/secret/meson.build | 19 +++
> src/secret/secret.conf.in | 14 ++
> src/secret/secret_config.c | 171 +++++++++++++++++++++++++
> src/secret/secret_config.h | 40 ++++++
> src/secret/secret_driver.c | 9 ++
> src/secret/test_libvirt_secrets.aug.in | 6 +
> src/util/virerror.c | 3 +
> 11 files changed, 307 insertions(+)
> create mode 100644 src/secret/libvirt_secrets.aug
> create mode 100644 src/secret/secret.conf.in
> create mode 100644 src/secret/secret_config.c
> create mode 100644 src/secret/secret_config.h
> create mode 100644 src/secret/test_libvirt_secrets.aug.in
Build fails after this patch with:
' '-Dabs_top_srcdir="/home/pipo/libvirt"' -MD -MQ src/libvirt_driver_secret.so.p/secret_secret_driver.c.o -MF src/libvirt_driver_secret.so.p/secret_secret_driver.c.o.d -o src/libvirt_driver_secret.so.p/secret_secret_driver.c.o -c ../../../libvirt/src/secret/secret_driver.c
../../../libvirt/src/secret/secret_driver.c:75:5: error: unknown type name ‘virSecretDaemonConfig’
75 | virSecretDaemonConfig *config;
| ^~~~~~~~~~~~~~~~~~~~~
../../../libvirt/src/secret/secret_driver.c: In function ‘secretStateInitialize’:
../../../libvirt/src/secret/secret_driver.c:525:28: error: implicit declaration of function ‘virSecretDaemonConfigNew’ [-Wimplicit-function-declaration]
525 | if (!(driver->config = virSecretDaemonConfigNew(driver->privileged)))
| ^~~~~~~~~~~~~~~~~~~~~~~~
../../../libvirt/src/secret/secret_driver.c:525:28: error: nested extern declaration of ‘virSecretDaemonConfigNew’ [-Werror=nested-externs]
../../../libvirt/src/secret/secret_driver.c:525:26: error: assignment to ‘int *’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
525 | if (!(driver->config = virSecretDaemonConfigNew(driver->privileged)))
| ^
../../../libvirt/src/secret/secret_driver.c: In function ‘secretStateReload’:
../../../libvirt/src/secret/secret_driver.c:562:26: error: assignment to ‘int *’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
562 | if (!(driver->config = virSecretDaemonConfigNew(driver->privileged)))
| ^
Since it succeeds after the last patch you likely misplaced some header
inclusion into the wrong patch.
[...]
> diff --git a/src/secret/secret_config.c b/src/secret/secret_config.c
> new file mode 100644
> index 0000000000..b63567944e
> --- /dev/null
> +++ b/src/secret/secret_config.c
[...]
> +
> +
> +static int virGetSecretsEncryptionKey(virSecretDaemonConfig *cfg,
> + uint8_t **secretsEncryptionKey,
> + size_t *secretsKeyLen)
inconsistent function header formatting
> +{
> + VIR_AUTOCLOSE fd = -1;
> + int encryption_key_length;
> +
> + if ((encryption_key_length = virFileReadAll(cfg->secretsEncryptionKeyPath, VIR_SECRETS_ENCRYPTION_KEY_LEN, (char**)secretsEncryptionKey)) < 0) {
break the very long line on argument boundaries
> + return -1;
> + }
> + if (encryption_key_length != VIR_SECRETS_ENCRYPTION_KEY_LEN) {
> + virReportError(VIR_ERR_INVALID_ENCR_KEY_SECRET,
> + _("Encryption key length must be '%1$d' '%2$s'"),
> + VIR_SECRETS_ENCRYPTION_KEY_LEN, cfg->secretsEncryptionKeyPath);
> + }
> +
> + *secretsKeyLen = (size_t)encryption_key_length;
> + return 0;
> +}
> +
> +
> +virSecretDaemonConfig *
> +virSecretDaemonConfigNew(bool privileged)
> +{
> + g_autoptr(virSecretDaemonConfig) cfg = NULL;
> + g_autofree char *configdir = NULL;
> + g_autofree char *configfile = NULL;
> + const char *credentials_directory;
> +
> + if (virSecretConfigInitialize() < 0)
> + return NULL;
> +
> + if (!(cfg = virObjectNew(virSecretDaemonConfigClass)))
> + return NULL;
> +
> + cfg->secretsEncryptionKeyPath = NULL;
all of 'cfg' ought to be initialized to NULL at this point so this isn't
needed.
> +
> + if (virSecretDaemonConfigFilePath(privileged, &configfile) < 0)
> + return NULL;
> +
> + if (virSecretLoadDaemonConfig(cfg, configfile) < 0)
> + return NULL;
> +
> + credentials_directory = getenv("CREDENTIALS_DIRECTORY");
> +
> + if (!cfg->secretsEncryptionKeyPath && credentials_directory) {
> + cfg->secretsEncryptionKeyPath = g_strdup_printf("%s/secrets-encryption-key",
> + credentials_directory);
> + if (!virFileExists(cfg->secretsEncryptionKeyPath)) {
> + g_clear_pointer(&cfg->secretsEncryptionKeyPath, g_free);
> + }
> + }
> +
> + if (!cfg->encryptDataWasSet) {
> + if (!cfg->secretsEncryptionKeyPath) {
> + /* No path specified by user or environment, disable encryption */
> + cfg->encryptData = false;
> + } else {
> + cfg->encryptData = true;
> + }
> + } else {
> + if (cfg->encryptData) {
> + if (!cfg->secretsEncryptionKeyPath) {
> + /* Built-in default path must be used */
> + cfg->secretsEncryptionKeyPath = g_strdup("/run/libvirt/secrets/encryption-key");
This ought to use some form of config-time variable to place it
correctly, otherwise it won't respect users' build-time options.
> + }
> + }
> + }
> + VIR_DEBUG("Secrets encryption key path: %s", NULLSTR(cfg->secretsEncryptionKeyPath));
> +
> + if (cfg->encryptData) {
> + if (virGetSecretsEncryptionKey(cfg, &cfg->secretsEncryptionKey, &cfg->secretsKeyLen) < 0) {
> + return NULL;
> + }
> + }
> + return g_steal_pointer(&cfg);
> +}
[...]
> diff --git a/src/secret/secret_driver.c b/src/secret/secret_driver.c
> index 04c3ca49f1..408a629ea0 100644
> --- a/src/secret/secret_driver.c
> +++ b/src/secret/secret_driver.c
> @@ -70,6 +70,9 @@ struct _virSecretDriverState {
>
> /* Immutable pointer, self-locking APIs */
> virInhibitor *inhibitor;
> +
> + /* Settings from secret.conf file */
> + virSecretDaemonConfig *config;
> };
Please use the annotation about how to access the data (as all other
values above have).
In this case I expect that the correct annotation is:
/* Require lock to get reference on 'config',
* then lockless thereafter */
same as the 'config' member of struct _virQEMUDriver.
© 2016 - 2025 Red Hat, Inc.