From 62a93c78500edd9c67b2300cba1134b373138258 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 16 Mar 2017 11:29:21 -0400 Subject: [PATCH] postprocess: Handle f26 /etc/nsswitch.conf configuration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit F26 put sss first, which broke our regexp. When we switch to sysusers, man it'll be nice to dump ♲ this. Closes: https://github.com/projectatomic/rpm-ostree/issues/685 Closes: #686 Approved by: jlebon --- Makefile-tests.am | 5 ++ src/libpriv/rpmostree-postprocess.c | 95 +++++++++++++++++++++++++++++-------- src/libpriv/rpmostree-postprocess.h | 5 ++ tests/check/postprocess.c | 93 ++++++++++++++++++++++++++++++++++++ 4 files changed, 179 insertions(+), 19 deletions(-) create mode 100644 tests/check/postprocess.c diff --git a/Makefile-tests.am b/Makefile-tests.am index ab9f9cc..b173877 100644 --- a/Makefile-tests.am +++ b/Makefile-tests.am @@ -75,6 +75,10 @@ tests_check_cache_branch_to_nevra_CPPFLAGS = $(AM_CPPFLAGS) -I $(srcdir)/src/lib tests_check_cache_branch_to_nevra_CFLAGS = $(AM_CFLAGS) $(PKGDEP_RPMOSTREE_CFLAGS) tests_check_cache_branch_to_nevra_LDADD = $(PKGDEP_RPMOSTREE_LIBS) librpmostreepriv.la +tests_check_postprocess_CPPFLAGS = $(AM_CPPFLAGS) -I $(srcdir)/src/libpriv -I $(srcdir)/libglnx +tests_check_postprocess_CFLAGS = $(AM_CFLAGS) $(PKGDEP_RPMOSTREE_CFLAGS) +tests_check_postprocess_LDADD = $(PKGDEP_RPMOSTREE_LIBS) librpmostreepriv.la + tests/check/test-compose.sh: tests/common/compose/test-repo.repo tests/check/test-ucontainer.sh: tests/common/compose/test-repo.repo @@ -82,6 +86,7 @@ tests/check/test-ucontainer.sh: tests/common/compose/test-repo.repo uninstalled_test_programs = \ tests/check/jsonutil \ tests/check/cache_branch_to_nevra \ + tests/check/postprocess \ $(NULL) uninstalled_test_scripts = \ diff --git a/src/libpriv/rpmostree-postprocess.c b/src/libpriv/rpmostree-postprocess.c index dce8ddc..cff6e8d 100644 --- a/src/libpriv/rpmostree-postprocess.c +++ b/src/libpriv/rpmostree-postprocess.c @@ -512,34 +512,91 @@ rpmostree_prepare_rootfs_get_sepolicy (int dfd, return ret; } -static gboolean -replace_nsswitch (int dfd, - GCancellable *cancellable, - GError **error) +static char * +replace_nsswitch_string (const char *buf, + GError **error) { - g_autofree char *nsswitch_contents = NULL; - g_autofree char *new_nsswitch_contents = NULL; + gboolean is_passwd; + gboolean is_group; + + is_passwd = g_str_has_prefix (buf, "passwd:"); + is_group = g_str_has_prefix (buf, "group:"); + + if (!(is_passwd || is_group)) + return g_strdup (buf); + + const char *colon = strchr (buf, ':'); + g_assert (colon); + + g_autoptr(GString) retbuf = g_string_new (""); + /* Insert the prefix */ + g_string_append_len (retbuf, buf, (colon - buf) + 1); + + /* Now parse the elements and try to insert `altfiles` + * after `files`. + */ + g_auto(GStrv) elts = g_strsplit_set (colon + 1, " \t", -1); + gboolean inserted = FALSE; + for (char **iter = elts; iter && *iter; iter++) + { + const char *v = *iter; + if (!*v) + continue; + /* Already have altfiles? We're done */ + if (strcmp (v, "altfiles") == 0) + return g_strdup (buf); + /* We prefer `files altfiles` */ + else if (!inserted && strcmp (v, "files") == 0) + { + g_string_append (retbuf, " files altfiles"); + inserted = TRUE; + } + else + { + g_string_append_c (retbuf, ' '); + g_string_append (retbuf, v); + } + } + /* Last ditch effort if we didn't find `files` */ + if (!inserted) + g_string_append (retbuf, " altfiles"); + return g_string_free (g_steal_pointer (&retbuf), FALSE); +} - static gsize regex_initialized; - static GRegex *passwd_regex; +char * +rpmostree_postprocess_replace_nsswitch (const char *buf, + GError **error) +{ + g_autoptr(GString) new_buf = g_string_new (""); - if (g_once_init_enter (®ex_initialized)) + g_auto(GStrv) lines = g_strsplit (buf, "\n", -1); + for (char **iter = lines; iter && *iter; iter++) { - passwd_regex = g_regex_new ("^(passwd|group):\\s+files(.*)$", - G_REGEX_MULTILINE, 0, NULL); - g_assert (passwd_regex); - g_once_init_leave (®ex_initialized, 1); + const char *line = *iter; + g_autofree char *replaced_line = replace_nsswitch_string (line, error); + if (!replaced_line) + return NULL; + g_string_append (new_buf, replaced_line); + if (*(iter+1)) + g_string_append_c (new_buf, '\n'); } + return g_string_free (g_steal_pointer (&new_buf), FALSE); +} + - nsswitch_contents = glnx_file_get_contents_utf8_at (dfd, "etc/nsswitch.conf", NULL, - cancellable, error); +static gboolean +replace_nsswitch (int dfd, + GCancellable *cancellable, + GError **error) +{ + g_autofree char *nsswitch_contents = + glnx_file_get_contents_utf8_at (dfd, "etc/nsswitch.conf", NULL, + cancellable, error); if (!nsswitch_contents) return FALSE; - new_nsswitch_contents = g_regex_replace (passwd_regex, - nsswitch_contents, -1, 0, - "\\1: files altfiles\\2", - 0, error); + g_autofree char *new_nsswitch_contents = + rpmostree_postprocess_replace_nsswitch (nsswitch_contents, error); if (!new_nsswitch_contents) return FALSE; diff --git a/src/libpriv/rpmostree-postprocess.h b/src/libpriv/rpmostree-postprocess.h index a270c98..1c972ac 100644 --- a/src/libpriv/rpmostree-postprocess.h +++ b/src/libpriv/rpmostree-postprocess.h @@ -23,6 +23,11 @@ #include #include "rpmostree-json-parsing.h" +/* "public" for unit tests */ +char * +rpmostree_postprocess_replace_nsswitch (const char *buf, + GError **error); + gboolean rpmostree_treefile_postprocessing (int rootfs_fd, GFile *context_directory, diff --git a/tests/check/postprocess.c b/tests/check/postprocess.c new file mode 100644 index 0000000..135be94 --- /dev/null +++ b/tests/check/postprocess.c @@ -0,0 +1,93 @@ +#include "config.h" + +#include +#include +#include + +#include +#include "libglnx.h" +#include "rpmostree-postprocess.h" + +typedef struct { + const char *input; + const char *output; +} AltfilesTest; + +static AltfilesTest altfiles_tests[] = { + { + /* F25 */ + .input = "# An nsswitch.conf\n" \ + "\npasswd: files sss\n" \ + "\ngroup: files sss\n" \ + "\nhosts: files mdns4_minimal [NOTFOUND=return] dns myhostname\n", + .output = "# An nsswitch.conf\n" \ + "\npasswd: files altfiles sss\n" \ + "\ngroup: files altfiles sss\n" \ + "\nhosts: files mdns4_minimal [NOTFOUND=return] dns myhostname\n" + }, + { + /* F26 */ + .input = "# An nsswitch.conf\n" \ + "\npasswd: sss files systemd\n" \ + "\ngroup: sss files systemd\n" \ + "\nhosts: files mdns4_minimal [NOTFOUND=return] dns myhostname\n", + .output = "# An nsswitch.conf\n" \ + "\npasswd: sss files altfiles systemd\n" \ + "\ngroup: sss files altfiles systemd\n" \ + "\nhosts: files mdns4_minimal [NOTFOUND=return] dns myhostname\n" + }, + { + /* Already have altfiles, input/output identical */ + .input = "# An nsswitch.conf\n" \ + "\npasswd: sss files altfiles systemd\n" \ + "\ngroup: sss files altfiles systemd\n" \ + "\nhosts: files mdns4_minimal [NOTFOUND=return] dns myhostname\n", + .output = "# An nsswitch.conf\n" \ + "\npasswd: sss files altfiles systemd\n" \ + "\ngroup: sss files altfiles systemd\n" \ + "\nhosts: files mdns4_minimal [NOTFOUND=return] dns myhostname\n", + }, + { + /* Test having `files` as a substring */ + .input = "# An nsswitch.conf\n" \ + "\npasswd: sss foofiles files systemd\n" \ + "\ngroup: sss foofiles files systemd\n" \ + "\nhosts: files mdns4_minimal [NOTFOUND=return] dns myhostname\n", + .output = "# An nsswitch.conf\n" \ + "\npasswd: sss foofiles files altfiles systemd\n" \ + "\ngroup: sss foofiles files altfiles systemd\n" \ + "\nhosts: files mdns4_minimal [NOTFOUND=return] dns myhostname\n", + } +}; + +static void +test_postprocess_altfiles (void) +{ + g_autoptr(GError) local_error = NULL; + GError **error = &local_error; + + for (guint i = 0; i < G_N_ELEMENTS(altfiles_tests); i++) + { + AltfilesTest *test = &altfiles_tests[i]; + g_autofree char *newbuf = rpmostree_postprocess_replace_nsswitch (test->input, error); + + if (!newbuf) + goto out; + + g_assert_cmpstr (newbuf, ==, test->output); + } + + out: + g_assert_no_error (local_error); +} + +int +main (int argc, + char *argv[]) +{ + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/altfiles", test_postprocess_altfiles); + + return g_test_run (); +} -- 2.9.3