1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
|
From 12127d9c04e8151c51bd14114dce424ff8448345 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Thu, 9 Sep 2021 09:40:49 -0400
Subject: [PATCH 2/2] main: Allow cache files to be marked immutable
At the moment, at start up we unconditionally reset permission of all
cache files in /var/lib/AccountsService/users. If the mode of the files
can't be reset, accountsservice fails to start.
But there's a situation where we should proceed anyway: If the
mode is already correct, and the file is read-only, there is no reason
to refuse to proceed.
This commit changes the code to explicitly validate the permissions of
the file before failing.
---
src/main.c | 29 +++++++++++++++++++++++++----
1 file changed, 25 insertions(+), 4 deletions(-)
diff --git a/src/main.c b/src/main.c
index 01cb617..36a2d7e 100644
--- a/src/main.c
+++ b/src/main.c
@@ -16,143 +16,164 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* Written by: Matthias Clasen <mclasen@redhat.com>
*/
#include "config.h"
#include <stdlib.h>
#include <stdarg.h>
#include <locale.h>
#include <libintl.h>
#include <syslog.h>
#include <sys/stat.h>
#include <errno.h>
#include <glib.h>
#include <glib/gi18n.h>
#include <glib/gstdio.h>
#include <glib-unix.h>
#include "daemon.h"
#define NAME_TO_CLAIM "org.freedesktop.Accounts"
static gboolean
ensure_directory (const char *path,
gint mode,
GError **error)
{
+ GStatBuf stat_buffer = { 0 };
+
if (g_mkdir_with_parents (path, mode) < 0) {
g_set_error (error,
G_FILE_ERROR,
g_file_error_from_errno (errno),
"Failed to create directory %s: %m",
path);
return FALSE;
}
- if (g_chmod (path, mode) < 0) {
+ g_chmod (path, mode);
+
+ if (g_stat (path, &stat_buffer) < 0) {
+ g_clear_error (error);
+
g_set_error (error,
G_FILE_ERROR,
g_file_error_from_errno (errno),
- "Failed to change permissions of directory %s: %m",
+ "Failed to validate permissions of directory %s: %m",
path);
return FALSE;
}
+ if ((stat_buffer.st_mode & ~S_IFMT) != mode) {
+ g_set_error (error,
+ G_FILE_ERROR,
+ g_file_error_from_errno (errno),
+ "Directory %s has wrong mode %o; it should be %o",
+ path, stat_buffer.st_mode, mode);
+ return FALSE;
+ }
+
return TRUE;
}
static gboolean
ensure_file_permissions (const char *dir_path,
gint file_mode,
GError **error)
{
GDir *dir = NULL;
const gchar *filename;
gint errsv = 0;
dir = g_dir_open (dir_path, 0, error);
if (dir == NULL)
return FALSE;
while ((filename = g_dir_read_name (dir)) != NULL) {
+ GStatBuf stat_buffer = { 0 };
+
gchar *file_path = g_build_filename (dir_path, filename, NULL);
g_debug ("Changing permission of %s to %04o", file_path, file_mode);
- if (g_chmod (file_path, file_mode) < 0)
+ g_chmod (file_path, file_mode);
+
+ if (g_stat (file_path, &stat_buffer) < 0)
errsv = errno;
+ if ((stat_buffer.st_mode & ~S_IFMT) != file_mode)
+ errsv = EACCES;
+
g_free (file_path);
}
g_dir_close (dir);
/* Report any errors after all chmod()s have been attempted. */
if (errsv != 0) {
g_set_error (error,
G_FILE_ERROR,
g_file_error_from_errno (errsv),
"Failed to change permissions of files in directory %s: %m",
dir_path);
return FALSE;
}
return TRUE;
}
static void
on_bus_acquired (GDBusConnection *connection,
const gchar *name,
gpointer user_data)
{
GMainLoop *loop = user_data;
Daemon *daemon;
g_autoptr(GError) error = NULL;
if (!ensure_directory (ICONDIR, 0775, &error) ||
!ensure_directory (USERDIR, 0700, &error) ||
!ensure_file_permissions (USERDIR, 0600, &error)) {
g_printerr ("%s\n", error->message);
g_main_loop_quit (loop);
return;
}
daemon = daemon_new ();
if (daemon == NULL) {
g_printerr ("Failed to initialize daemon\n");
g_main_loop_quit (loop);
return;
}
-
openlog ("accounts-daemon", LOG_PID, LOG_DAEMON);
syslog (LOG_INFO, "started daemon version %s", VERSION);
closelog ();
openlog ("accounts-daemon", 0, LOG_AUTHPRIV);
}
static void
on_name_lost (GDBusConnection *connection,
const gchar *name,
gpointer user_data)
{
GMainLoop *loop = user_data;
g_debug ("got NameLost, exiting");
g_main_loop_quit (loop);
}
static gboolean debug;
static void
on_log_debug (const gchar *log_domain,
GLogLevelFlags log_level,
const gchar *message,
gpointer user_data)
{
g_autoptr(GString) string = NULL;
const gchar *progname;
int ret G_GNUC_UNUSED;
string = g_string_new (NULL);
--
2.31.1
|