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