diff --git a/Makefile.am b/Makefile.am
index d787fff8be..c3446446f7 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -130,7 +130,7 @@ dist-luarock: $(LUACRUN_ROCK)
endif
crun_CFLAGS = -I $(abs_top_builddir)/libocispec/src -I $(abs_top_srcdir)/libocispec/src -D CRUN_LIBDIR="\"$(CRUN_LIBDIR)\""
-crun_SOURCES = src/crun.c src/run.c src/delete.c src/kill.c src/pause.c src/unpause.c src/spec.c \
+crun_SOURCES = src/crun.c src/run.c src/delete.c src/kill.c src/pause.c src/unpause.c src/features.c src/spec.c \
src/exec.c src/list.c src/create.c src/start.c src/state.c src/update.c src/ps.c \
src/checkpoint.c src/restore.c src/libcrun/cloned_binary.c
@@ -143,7 +143,7 @@ endif
EXTRA_DIST = COPYING COPYING.libcrun README.md NEWS SECURITY.md rpm/crun.spec.in autogen.sh \
src/crun.h src/list.h src/run.h src/delete.h src/kill.h src/pause.h src/unpause.h \
- src/create.h src/start.h src/state.h src/exec.h src/spec.h src/update.h src/ps.h \
+ src/create.h src/start.h src/state.h src/exec.h src/features.h src/spec.h src/update.h src/ps.h \
src/checkpoint.h src/restore.h src/libcrun/seccomp_notify.h src/libcrun/seccomp_notify_plugin.h \
src/libcrun/container.h src/libcrun/seccomp.h src/libcrun/ebpf.h \
src/libcrun/cgroup.h src/libcrun/cgroup-cgroupfs.h \
diff --git a/src/crun.c b/src/crun.c
index d96b6a151c..ba9a7062d0 100644
--- a/src/crun.c
+++ b/src/crun.c
@@ -45,6 +45,7 @@
#include "spec.h"
#include "pause.h"
#include "unpause.h"
+#include "features.h"
#include "ps.h"
#include "checkpoint.h"
#include "restore.h"
@@ -137,6 +138,7 @@ enum
COMMAND_UPDATE,
COMMAND_PAUSE,
COMMAND_UNPAUSE,
+ COMMAND_FEATURES,
COMMAND_PS,
COMMAND_CHECKPOINT,
COMMAND_RESTORE,
@@ -155,6 +157,7 @@ struct commands_s commands[] = { { COMMAND_CREATE, "create", crun_command_create
{ COMMAND_UPDATE, "update", crun_command_update },
{ COMMAND_PAUSE, "pause", crun_command_pause },
{ COMMAND_UNPAUSE, "resume", crun_command_unpause },
+ { COMMAND_FEATURES, "features", crun_command_features },
#if HAVE_CRIU && HAVE_DLOPEN
{ COMMAND_CHECKPOINT, "checkpoint", crun_command_checkpoint },
{ COMMAND_RESTORE, "restore", crun_command_restore },
@@ -170,6 +173,7 @@ static char doc[] = "\nCOMMANDS:\n"
"\tcreate - create a container\n"
"\tdelete - remove definition for a container\n"
"\texec - exec a command in a running container\n"
+ "\tfeatures - show the enabled features\n"
"\tlist - list known containers\n"
"\tkill - send a signal to the container init process\n"
"\tps - show the processes in the container\n"
diff --git a/src/features.c b/src/features.c
new file mode 100644
index 0000000000..ade03805b8
--- /dev/null
+++ b/src/features.c
@@ -0,0 +1,314 @@
+/*
+ * crun - OCI runtime written in C
+ *
+ * crun is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * crun is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with crun. If not, see .
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include "crun.h"
+#include "libcrun/container.h"
+#include "libcrun/utils.h"
+
+#define cleanup_struct_features __attribute__ ((cleanup (cleanup_struct_features_free)))
+
+static char doc[] = "OCI runtime";
+
+static struct argp_option options[] = { { 0 } };
+
+static char args_doc[] = "features";
+
+const unsigned char *json_string;
+
+size_t json_length;
+
+static error_t
+parse_opt (int key, char *arg arg_unused, struct argp_state *state arg_unused)
+{
+ if (key != ARGP_KEY_NO_ARGS)
+ {
+ return ARGP_ERR_UNKNOWN;
+ }
+
+ return 0;
+}
+
+static struct argp run_argp = { options, parse_opt, args_doc, doc, NULL, NULL, NULL };
+
+void
+add_string_to_json (yajl_gen json_gen, const char *key, const char *value)
+{
+ yajl_gen_string (json_gen, (const unsigned char *) key, strlen (key));
+ yajl_gen_string (json_gen, (const unsigned char *) value, strlen (value));
+}
+
+void
+add_bool_to_json (yajl_gen json_gen, const char *key, int value)
+{
+ yajl_gen_string (json_gen, (const unsigned char *) key, strlen (key));
+ yajl_gen_bool (json_gen, value);
+}
+
+void
+add_array_to_json (yajl_gen json_gen, const char *key, const char **array)
+{
+ yajl_gen_string (json_gen, (const unsigned char *) key, strlen (key));
+ yajl_gen_array_open (json_gen);
+
+ for (size_t i = 0; array[i] != NULL; i++)
+ {
+ yajl_gen_string (json_gen, (const unsigned char *) array[i], strlen (array[i]));
+ }
+
+ yajl_gen_array_close (json_gen);
+}
+
+void
+crun_features_add_hooks (yajl_gen json_gen, const char **hooks)
+{
+ add_array_to_json (json_gen, "hooks", hooks);
+}
+
+void
+crun_features_add_mount_options (yajl_gen json_gen, const char **mount_options)
+{
+ add_array_to_json (json_gen, "mountOptions", mount_options);
+}
+
+void
+crun_features_add_namespaces (yajl_gen json_gen, const struct linux_info_s *linux)
+{
+ add_array_to_json (json_gen, "namespaces", linux->namespaces);
+}
+
+void
+crun_features_add_capabilities (yajl_gen json_gen, const struct linux_info_s *linux)
+{
+ add_array_to_json (json_gen, "capabilities", linux->capabilities);
+}
+
+void
+crun_features_add_cgroup_info (yajl_gen json_gen, const struct linux_info_s *linux)
+{
+ yajl_gen_string (json_gen, (const unsigned char *) "cgroup", strlen ("cgroup"));
+ yajl_gen_map_open (json_gen);
+
+ add_bool_to_json (json_gen, "v1", linux->cgroup.v1);
+ add_bool_to_json (json_gen, "v2", linux->cgroup.v2);
+ add_bool_to_json (json_gen, "systemd", linux->cgroup.systemd);
+ add_bool_to_json (json_gen, "systemdUser", linux->cgroup.systemdUser);
+
+ yajl_gen_map_close (json_gen);
+}
+
+void
+crun_features_add_seccomp_info (yajl_gen json_gen, const struct linux_info_s *linux)
+{
+ yajl_gen_string (json_gen, (const unsigned char *) "seccomp", strlen ("seccomp"));
+ yajl_gen_map_open (json_gen);
+
+ add_bool_to_json (json_gen, "enabled", linux->seccomp.enabled);
+ add_array_to_json (json_gen, "actions", linux->seccomp.actions);
+ add_array_to_json (json_gen, "operators", linux->seccomp.operators);
+ add_array_to_json (json_gen, "archs", linux->seccomp.archs);
+
+ yajl_gen_map_close (json_gen);
+}
+
+void
+crun_features_add_apparmor_info (yajl_gen json_gen, const struct linux_info_s *linux)
+{
+ yajl_gen_string (json_gen, (const unsigned char *) "apparmor", strlen ("apparmor"));
+ yajl_gen_map_open (json_gen);
+
+ add_bool_to_json (json_gen, "enabled", linux->apparmor.enabled);
+
+ // Close the map for apparmor
+ yajl_gen_map_close (json_gen);
+}
+
+void
+crun_features_add_selinux_info (yajl_gen json_gen, const struct linux_info_s *linux)
+{
+ yajl_gen_string (json_gen, (const unsigned char *) "selinux", strlen ("selinux"));
+ yajl_gen_map_open (json_gen);
+
+ add_bool_to_json (json_gen, "enabled", linux->selinux.enabled);
+
+ // Close the map for selinux
+ yajl_gen_map_close (json_gen);
+}
+
+void
+crun_features_add_linux_info (yajl_gen json_gen, const struct linux_info_s *linux)
+{
+ yajl_gen_string (json_gen, (const unsigned char *) "linux", strlen ("linux"));
+ yajl_gen_map_open (json_gen);
+
+ crun_features_add_namespaces (json_gen, linux);
+ crun_features_add_capabilities (json_gen, linux);
+ crun_features_add_cgroup_info (json_gen, linux);
+ crun_features_add_seccomp_info (json_gen, linux);
+ crun_features_add_apparmor_info (json_gen, linux);
+ crun_features_add_selinux_info (json_gen, linux);
+
+ yajl_gen_map_close (json_gen);
+}
+
+static inline void
+cleanup_struct_features_free (struct features_info_s **info)
+{
+ if (info == NULL || *info == NULL)
+ return;
+
+ struct features_info_s *ptr = *info;
+
+ // Free oci_version_min if it is not NULL
+ if (ptr->oci_version_min != NULL)
+ {
+ free ((void *) ptr->oci_version_min);
+ ptr->oci_version_min = NULL; // Set to NULL after freeing
+ }
+
+ // Free oci_version_max if it is not NULL
+ if (ptr->oci_version_max != NULL)
+ {
+ free ((void *) ptr->oci_version_max);
+ ptr->oci_version_max = NULL; // Set to NULL after freeing
+ }
+ if (ptr->hooks != NULL)
+ {
+ for (size_t i = 0; ptr->hooks[i] != NULL; i++)
+ {
+ free ((void *) ptr->hooks[i]);
+ }
+ free (ptr->hooks);
+ }
+ if (ptr->mount_options != NULL)
+ {
+ for (size_t i = 0; ptr->mount_options[i] != NULL; i++)
+ {
+ free ((void *) ptr->mount_options[i]);
+ }
+ free (ptr->mount_options);
+ }
+ if (ptr->linux.namespaces != NULL)
+ {
+ for (size_t i = 0; ptr->linux.namespaces[i] != NULL; i++)
+ {
+ free ((void *) ptr->linux.namespaces[i]);
+ }
+ free (ptr->linux.namespaces);
+ }
+
+ if (ptr->linux.capabilities != NULL)
+ {
+ for (size_t i = 0; ptr->linux.capabilities[i] != NULL; i++)
+ {
+ free ((void *) ptr->linux.capabilities[i]);
+ }
+ free (ptr->linux.capabilities);
+ }
+ if (ptr->linux.seccomp.actions != NULL)
+ {
+ for (size_t i = 0; ptr->linux.seccomp.actions[i] != NULL; i++)
+ {
+ free ((void *) ptr->linux.seccomp.actions[i]);
+ }
+ free (ptr->linux.seccomp.actions);
+ }
+ if (ptr->linux.seccomp.operators != NULL)
+ {
+ for (size_t i = 0; ptr->linux.seccomp.operators[i] != NULL; i++)
+ {
+ free ((void *) ptr->linux.seccomp.operators[i]);
+ }
+ free (ptr->linux.seccomp.operators);
+ }
+ if (ptr->linux.seccomp.archs != NULL)
+ {
+ for (size_t i = 0; ptr->linux.seccomp.archs[i] != NULL; i++)
+ {
+ free ((void *) ptr->linux.seccomp.archs[i]);
+ }
+ free (ptr->linux.seccomp.archs);
+ }
+
+ free (ptr);
+ *info = NULL;
+}
+
+int
+crun_command_features (struct crun_global_arguments *global_args, int argc, char **argv, libcrun_error_t *err)
+{
+ argp_parse (&run_argp, argc, argv, 0, 0, &options);
+
+ // Call the function in features.c to gather the feature information
+ cleanup_struct_features struct features_info_s *info = NULL;
+ int result = libcrun_container_get_features (&info);
+ if (result != 0)
+ {
+ libcrun_make_error (err, 0, "Failed to gather features information.");
+ return result;
+ }
+
+ // Prepare the JSON output
+ yajl_gen json_gen = yajl_gen_alloc (NULL);
+ if (json_gen == NULL)
+ {
+ libcrun_make_error (err, errno, "Failed to initialize json structure.");
+ return 0;
+ }
+ yajl_gen_status status;
+
+ yajl_gen_config (json_gen, yajl_gen_beautify, 1); // Optional: Enable pretty formatting
+
+ // Start building the JSON
+ yajl_gen_map_open (json_gen);
+
+ // Add ociVersionMin field
+ add_string_to_json (json_gen, "ociVersionMin", info->oci_version_min);
+
+ // Add ociVersionMax field
+ add_string_to_json (json_gen, "ociVersionMax", info->oci_version_max);
+
+ // Add hooks array
+ crun_features_add_hooks (json_gen, info->hooks);
+
+ // Add mountOptions array
+ crun_features_add_mount_options (json_gen, info->mount_options);
+
+ // Add linux struct info
+ crun_features_add_linux_info (json_gen, &info->linux);
+
+ // End building the JSON
+ yajl_gen_map_close (json_gen);
+
+ yajl_gen_get_buf (json_gen, &json_string, &json_length);
+
+ printf ("%s", (const char *) json_string);
+
+ yajl_gen_free (json_gen);
+
+ return 0;
+}
diff --git a/src/features.h b/src/features.h
new file mode 100644
index 0000000000..1c91ce9fcd
--- /dev/null
+++ b/src/features.h
@@ -0,0 +1,25 @@
+/*
+ * crun - OCI runtime written in C
+ *
+ * Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano
+ * crun is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * crun is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with crun. If not, see .
+ */
+#ifndef FEATURES_H
+#define FEATURES_H
+
+#include "crun.h"
+
+int crun_command_features (struct crun_global_arguments *global_args, int argc, char **argv, libcrun_error_t *error);
+
+#endif
diff --git a/src/libcrun/container.c b/src/libcrun/container.c
index ff621bbc56..160004b650 100644
--- a/src/libcrun/container.c
+++ b/src/libcrun/container.c
@@ -36,6 +36,7 @@
#include
#include
#include "status.h"
+#include "mount_flags.h"
#include "linux.h"
#include "terminal.h"
#include "io_priority.h"
@@ -45,6 +46,7 @@
#include
#include
#include
+#include
#include
#ifdef HAVE_SYSTEMD
@@ -92,6 +94,69 @@ struct sync_socket_message_s
typedef runtime_spec_schema_defs_hook hook;
+// linux hooks
+const char *hooks[] = {
+ "prestart",
+ "createRuntime",
+ "createContainer",
+ "startContainer",
+ "poststart",
+ "poststop"
+};
+
+// linux namespaces
+static const char *namespaces[] = {
+ "cgroup",
+ "ipc",
+ "mount",
+ "network",
+ "pid",
+ "user",
+ "uts"
+};
+
+static const char *actions[] = {
+ "SCMP_ACT_ALLOW",
+ "SCMP_ACT_ERRNO",
+ "SCMP_ACT_KILL",
+ "SCMP_ACT_KILL_PROCESS",
+ "SCMP_ACT_KILL_THREAD",
+ "SCMP_ACT_LOG",
+ "SCMP_ACT_NOTIFY",
+ "SCMP_ACT_TRACE",
+ "SCMP_ACT_TRAP"
+};
+
+const char *operators[] = {
+ "SCMP_CMP_NE",
+ "SCMP_CMP_LT",
+ "SCMP_CMP_LE",
+ "SCMP_CMP_EQ",
+ "SCMP_CMP_GE",
+ "SCMP_CMP_GT",
+ "SCMP_CMP_MASKED_EQ",
+};
+
+static const char *archs[] = {
+ "SCMP_ARCH_AARCH64",
+ "SCMP_ARCH_ARM",
+ "SCMP_ARCH_MIPS",
+ "SCMP_ARCH_MIPS64",
+ "SCMP_ARCH_MIPS64N32",
+ "SCMP_ARCH_MIPSEL",
+ "SCMP_ARCH_MIPSEL64",
+ "SCMP_ARCH_MIPSEL64N32",
+ "SCMP_ARCH_PPC",
+ "SCMP_ARCH_PPC64",
+ "SCMP_ARCH_PPC64LE",
+ "SCMP_ARCH_RISCV64",
+ "SCMP_ARCH_S390",
+ "SCMP_ARCH_S390X",
+ "SCMP_ARCH_X32",
+ "SCMP_ARCH_X86",
+ "SCMP_ARCH_X86_64"
+};
+
static const char spec_file[] = "\
{\n\
\"ociVersion\": \"1.0.0\",\n\
@@ -3706,6 +3771,143 @@ libcrun_container_update_from_values (libcrun_context_t *context, const char *id
return ret;
}
+void
+populate_array_field (const char ***field, const char *array[], size_t num_elements)
+{
+ *field = xmalloc0 ((num_elements + 1) * sizeof (char *));
+ size_t i;
+ for (i = 0; i < num_elements; i++)
+ {
+ (*field)[i] = xstrdup (array[i]);
+ }
+
+ (*field)[i] = NULL; // Terminate the array with NULL
+}
+
+void
+populate_capabilities (struct features_info_s *info, const char ***capabilities, size_t *num_capabilities)
+{
+ cap_value_t i;
+ *num_capabilities = 0;
+ for (i = 0;; i++)
+ {
+ char *v = cap_to_name (i);
+ if (v == NULL)
+ break;
+ char *endptr;
+ strtol (v, &endptr, 10);
+ if (endptr != v)
+ {
+ // Non-numeric or non-zero value encountered, break the loop
+ break;
+ }
+ (*num_capabilities)++;
+ }
+
+ *capabilities = xmalloc0 ((*num_capabilities + 1) * sizeof (const char *));
+ size_t index = 0;
+ for (i = 0;; i++)
+ {
+ char *v = cap_to_name (i);
+ if (v == NULL)
+ break;
+ char *endptr;
+ strtol (v, &endptr, 10);
+ if (endptr != v)
+ {
+ // Non-numeric or non-zero value encountered, break the loop
+ break;
+ }
+
+ // Convert capability name to uppercase
+ for (int j = 0; v[j] != '\0'; j++)
+ {
+ v[j] = toupper (v[j]);
+ }
+
+ (*capabilities)[index] = v;
+ index++;
+ }
+
+ (*capabilities)[index] = NULL; // Terminate the array with NULL
+ populate_array_field (&(info->linux.capabilities), *capabilities, *num_capabilities);
+}
+
+void
+retrieve_mount_options (struct features_info_s **info)
+{
+ // Retrieve mount options from wordlist
+ const struct propagation_flags_s *mount_options_list = get_mount_flags_from_wordlist ();
+
+ // Calculate the number of mount options
+ size_t num_mount_options = 0;
+ while (mount_options_list[num_mount_options].name != NULL)
+ {
+ num_mount_options++;
+ }
+
+ // Allocate memory for mount options in info struct
+ (*info)->mount_options = xmalloc0 (num_mount_options * sizeof (char *));
+
+ // Copy mount options to info struct
+ for (size_t i = 0; i < num_mount_options; i++)
+ {
+ (*info)->mount_options[i] = xstrdup (mount_options_list[i].name);
+ }
+}
+
+int
+libcrun_container_get_features (struct features_info_s **info)
+{
+ // Allocate memory for the features_info_s structure
+ *info = xmalloc0 (sizeof (struct features_info_s));
+ // Hardcoded feature information
+ (*info)->oci_version_min = xstrdup ("1.0.0");
+ (*info)->oci_version_max = xstrdup ("1.1.0-rc.3");
+
+ // Populate hooks
+ size_t num_hooks = sizeof (hooks) / sizeof (hooks[0]);
+ populate_array_field (&((*info)->hooks), hooks, num_hooks);
+
+ // Populate mount_options
+ retrieve_mount_options (info);
+
+ // Populate namespaces
+ size_t num_namspaces = sizeof (namespaces) / sizeof (namespaces[0]);
+ populate_array_field (&((*info)->linux.namespaces), namespaces, num_namspaces);
+
+ // Populate capabilities
+ size_t num_capabilities = 0;
+ const char **capabilities = NULL;
+ populate_capabilities (*info, &capabilities, &num_capabilities);
+
+ // Hardcode the values for cgroup
+ (*info)->linux.cgroup.v1 = true;
+ (*info)->linux.cgroup.v2 = true;
+#ifdef HAVE_SYSTEMD
+ (*info)->linux.cgroup.systemd = true;
+ (*info)->linux.cgroup.systemdUser = true;
+#endif
+
+ // Put seccomp values
+ (*info)->linux.seccomp.enabled = true;
+ // Populate actions
+ size_t num_actions = sizeof (actions) / sizeof (actions[0]);
+ populate_array_field (&((*info)->linux.seccomp.actions), actions, num_actions);
+ // Populate operators
+ size_t num_operators = sizeof (operators) / sizeof (operators[0]);
+ populate_array_field (&((*info)->linux.seccomp.operators), operators, num_operators);
+ // Populate archs
+ size_t num_archs = sizeof (archs) / sizeof (archs[0]);
+ populate_array_field (&((*info)->linux.seccomp.archs), archs, num_archs);
+
+ // Put values for apparmor and selinux
+ (*info)->linux.apparmor.enabled = true;
+ (*info)->linux.selinux.enabled = true;
+
+ return 0;
+}
+
int
libcrun_container_spec (bool root, FILE *out, libcrun_error_t *err arg_unused)
{
diff --git a/src/libcrun/container.h b/src/libcrun/container.h
index 9e4243e676..0c2349c115 100644
--- a/src/libcrun/container.h
+++ b/src/libcrun/container.h
@@ -95,6 +95,45 @@ typedef struct libcrun_container_s libcrun_container_t;
typedef struct libcrun_context_s libcrun_context_t;
struct container_entrypoint_s;
+struct cgroup_info_s
+{
+ bool v1;
+ bool v2;
+ bool systemd;
+ bool systemdUser;
+};
+struct seccomp_info_s
+{
+ bool enabled;
+ const char **actions;
+ const char **operators;
+ const char **archs;
+};
+struct apparmor_info_s
+{
+ bool enabled;
+};
+struct selinux_info_s
+{
+ bool enabled;
+};
+struct linux_info_s
+{
+ const char **namespaces;
+ const char **capabilities;
+ struct cgroup_info_s cgroup;
+ struct seccomp_info_s seccomp;
+ struct apparmor_info_s apparmor;
+ struct selinux_info_s selinux;
+};
+struct features_info_s
+{
+ const char *oci_version_min;
+ const char *oci_version_max;
+ const char **hooks;
+ const char **mount_options;
+ struct linux_info_s linux;
+};
struct libcrun_checkpoint_restore_s
{
@@ -184,6 +223,8 @@ LIBCRUN_PUBLIC int libcrun_container_update_from_values (libcrun_context_t *cont
struct libcrun_update_value_s *values, size_t len,
libcrun_error_t *err);
+LIBCRUN_PUBLIC int libcrun_container_get_features (struct features_info_s **info);
+
LIBCRUN_PUBLIC int libcrun_container_spec (bool root, FILE *out, libcrun_error_t *err);
LIBCRUN_PUBLIC int libcrun_container_pause (libcrun_context_t *context, const char *id, libcrun_error_t *err);
diff --git a/src/libcrun/mount_flags.c b/src/libcrun/mount_flags.c
index 41296a3d90..fd4dd9ff93 100644
--- a/src/libcrun/mount_flags.c
+++ b/src/libcrun/mount_flags.c
@@ -431,3 +431,17 @@ libcrun_str2mount_flags (const char *name)
{
return libcrun_mount_flag_in_word_set (name, strlen (name));
}
+
+const struct propagation_flags_s *
+get_mount_flags_from_wordlist(void) {
+ struct propagation_flags_s *flags;
+ size_t num_wordlist_flags = sizeof(wordlist) / sizeof(wordlist[0]);
+
+ flags = xmalloc0 (sizeof(struct propagation_flags_s) * num_wordlist_flags);
+
+ for (size_t i = 0; i < num_wordlist_flags; i++) {
+ flags[i].name = wordlist[i].name;
+ }
+
+ return flags;
+}
diff --git a/src/libcrun/mount_flags.h b/src/libcrun/mount_flags.h
index 726960901b..a93fce6cd0 100644
--- a/src/libcrun/mount_flags.h
+++ b/src/libcrun/mount_flags.h
@@ -35,5 +35,6 @@ struct propagation_flags_s
};
const struct propagation_flags_s *libcrun_str2mount_flags (const char *name);
+const struct propagation_flags_s *get_mount_flags_from_wordlist ();
#endif