Blame SOURCES/0002-main-Allow-cache-files-to-be-marked-immutable.patch

1a6b7c
From 12127d9c04e8151c51bd14114dce424ff8448345 Mon Sep 17 00:00:00 2001
1a6b7c
From: Ray Strode <rstrode@redhat.com>
1a6b7c
Date: Thu, 9 Sep 2021 09:40:49 -0400
1a6b7c
Subject: [PATCH 2/2] main: Allow cache files to be marked immutable
1a6b7c
1a6b7c
At the moment, at start up we unconditionally reset permission of all
1a6b7c
cache files in /var/lib/AccountsService/users.  If the mode of the files
1a6b7c
can't be reset, accountsservice fails to start.
1a6b7c
1a6b7c
But there's a situation where we should proceed anyway: If the
1a6b7c
mode is already correct, and the file is read-only, there is no reason
1a6b7c
to refuse to proceed.
1a6b7c
1a6b7c
This commit changes the code to explicitly validate the permissions of
1a6b7c
the file before failing.
1a6b7c
---
1a6b7c
 src/main.c | 29 +++++++++++++++++++++++++----
1a6b7c
 1 file changed, 25 insertions(+), 4 deletions(-)
1a6b7c
1a6b7c
diff --git a/src/main.c b/src/main.c
1a6b7c
index 01cb617..36a2d7e 100644
1a6b7c
--- a/src/main.c
1a6b7c
+++ b/src/main.c
1a6b7c
@@ -16,143 +16,164 @@
1a6b7c
  * along with this program; if not, write to the Free Software
1a6b7c
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
1a6b7c
  *
1a6b7c
  * Written by: Matthias Clasen <mclasen@redhat.com>
1a6b7c
  */
1a6b7c
 
1a6b7c
 #include "config.h"
1a6b7c
 
1a6b7c
 #include <stdlib.h>
1a6b7c
 #include <stdarg.h>
1a6b7c
 #include <locale.h>
1a6b7c
 #include <libintl.h>
1a6b7c
 #include <syslog.h>
1a6b7c
 #include <sys/stat.h>
1a6b7c
 #include <errno.h>
1a6b7c
 
1a6b7c
 #include <glib.h>
1a6b7c
 #include <glib/gi18n.h>
1a6b7c
 #include <glib/gstdio.h>
1a6b7c
 #include <glib-unix.h>
1a6b7c
 
1a6b7c
 #include "daemon.h"
1a6b7c
 
1a6b7c
 #define NAME_TO_CLAIM "org.freedesktop.Accounts"
1a6b7c
 
1a6b7c
 static gboolean
1a6b7c
 ensure_directory (const char  *path,
1a6b7c
                   gint         mode,
1a6b7c
                   GError     **error)
1a6b7c
 {
1a6b7c
+        GStatBuf stat_buffer = { 0 };
1a6b7c
+
1a6b7c
         if (g_mkdir_with_parents (path, mode) < 0) {
1a6b7c
                 g_set_error (error,
1a6b7c
                              G_FILE_ERROR,
1a6b7c
                              g_file_error_from_errno (errno),
1a6b7c
                              "Failed to create directory %s: %m",
1a6b7c
                              path);
1a6b7c
                 return FALSE;
1a6b7c
         }
1a6b7c
 
1a6b7c
-        if (g_chmod (path, mode) < 0) {
1a6b7c
+        g_chmod (path, mode);
1a6b7c
+
1a6b7c
+        if (g_stat (path, &stat_buffer) < 0) {
1a6b7c
+                g_clear_error (error);
1a6b7c
+
1a6b7c
                 g_set_error (error,
1a6b7c
                              G_FILE_ERROR,
1a6b7c
                              g_file_error_from_errno (errno),
1a6b7c
-                             "Failed to change permissions of directory %s: %m",
1a6b7c
+                             "Failed to validate permissions of directory %s: %m",
1a6b7c
                              path);
1a6b7c
                 return FALSE;
1a6b7c
         }
1a6b7c
 
1a6b7c
+        if ((stat_buffer.st_mode & ~S_IFMT) != mode) {
1a6b7c
+                g_set_error (error,
1a6b7c
+                             G_FILE_ERROR,
1a6b7c
+                             g_file_error_from_errno (errno),
1a6b7c
+                             "Directory %s has wrong mode %o; it should be %o",
1a6b7c
+                             path, stat_buffer.st_mode, mode);
1a6b7c
+                return FALSE;
1a6b7c
+        }
1a6b7c
+
1a6b7c
         return TRUE;
1a6b7c
 }
1a6b7c
 
1a6b7c
 static gboolean
1a6b7c
 ensure_file_permissions (const char  *dir_path,
1a6b7c
                          gint         file_mode,
1a6b7c
                          GError     **error)
1a6b7c
 {
1a6b7c
         GDir *dir = NULL;
1a6b7c
         const gchar *filename;
1a6b7c
         gint errsv = 0;
1a6b7c
 
1a6b7c
         dir = g_dir_open (dir_path, 0, error);
1a6b7c
         if (dir == NULL)
1a6b7c
                 return FALSE;
1a6b7c
 
1a6b7c
         while ((filename = g_dir_read_name (dir)) != NULL) {
1a6b7c
+                GStatBuf stat_buffer = { 0 };
1a6b7c
+
1a6b7c
                 gchar *file_path = g_build_filename (dir_path, filename, NULL);
1a6b7c
 
1a6b7c
                 g_debug ("Changing permission of %s to %04o", file_path, file_mode);
1a6b7c
-                if (g_chmod (file_path, file_mode) < 0)
1a6b7c
+                g_chmod (file_path, file_mode);
1a6b7c
+
1a6b7c
+                if (g_stat (file_path, &stat_buffer) < 0)
1a6b7c
                         errsv = errno;
1a6b7c
 
1a6b7c
+                if ((stat_buffer.st_mode & ~S_IFMT) != file_mode)
1a6b7c
+                        errsv = EACCES;
1a6b7c
+
1a6b7c
                 g_free (file_path);
1a6b7c
         }
1a6b7c
 
1a6b7c
         g_dir_close (dir);
1a6b7c
 
1a6b7c
         /* Report any errors after all chmod()s have been attempted. */
1a6b7c
         if (errsv != 0) {
1a6b7c
                 g_set_error (error,
1a6b7c
                              G_FILE_ERROR,
1a6b7c
                              g_file_error_from_errno (errsv),
1a6b7c
                              "Failed to change permissions of files in directory %s: %m",
1a6b7c
                              dir_path);
1a6b7c
                 return FALSE;
1a6b7c
         }
1a6b7c
 
1a6b7c
         return TRUE;
1a6b7c
 }
1a6b7c
 
1a6b7c
 static void
1a6b7c
 on_bus_acquired (GDBusConnection  *connection,
1a6b7c
                  const gchar      *name,
1a6b7c
                  gpointer          user_data)
1a6b7c
 {
1a6b7c
         GMainLoop *loop = user_data;
1a6b7c
         Daemon *daemon;
1a6b7c
         g_autoptr(GError) error = NULL;
1a6b7c
 
1a6b7c
         if (!ensure_directory (ICONDIR, 0775, &error) ||
1a6b7c
             !ensure_directory (USERDIR, 0700, &error) ||
1a6b7c
             !ensure_file_permissions (USERDIR, 0600, &error)) {
1a6b7c
                 g_printerr ("%s\n", error->message);
1a6b7c
                 g_main_loop_quit (loop);
1a6b7c
                 return;
1a6b7c
         }
1a6b7c
 
1a6b7c
         daemon = daemon_new ();
1a6b7c
         if (daemon == NULL) {
1a6b7c
                 g_printerr ("Failed to initialize daemon\n");
1a6b7c
                 g_main_loop_quit (loop);
1a6b7c
                 return;
1a6b7c
         }
1a6b7c
-
1a6b7c
         openlog ("accounts-daemon", LOG_PID, LOG_DAEMON);
1a6b7c
         syslog (LOG_INFO, "started daemon version %s", VERSION);
1a6b7c
         closelog ();
1a6b7c
         openlog ("accounts-daemon", 0, LOG_AUTHPRIV);
1a6b7c
 }
1a6b7c
 
1a6b7c
 static void
1a6b7c
 on_name_lost (GDBusConnection  *connection,
1a6b7c
               const gchar      *name,
1a6b7c
               gpointer          user_data)
1a6b7c
 {
1a6b7c
         GMainLoop *loop = user_data;
1a6b7c
 
1a6b7c
         g_debug ("got NameLost, exiting");
1a6b7c
         g_main_loop_quit (loop);
1a6b7c
 }
1a6b7c
 
1a6b7c
 static gboolean debug;
1a6b7c
 
1a6b7c
 static void
1a6b7c
 on_log_debug (const gchar *log_domain,
1a6b7c
               GLogLevelFlags log_level,
1a6b7c
               const gchar *message,
1a6b7c
               gpointer user_data)
1a6b7c
 {
1a6b7c
         g_autoptr(GString) string = NULL;
1a6b7c
         const gchar *progname;
1a6b7c
         int ret G_GNUC_UNUSED;
1a6b7c
 
1a6b7c
         string = g_string_new (NULL);
1a6b7c
-- 
1a6b7c
2.31.1
1a6b7c