blob: 714aae781f9a307db3ae62d7ab68681d7d3656c7 [file] [log] [blame]
Eric Paris48681bb2011-08-03 11:40:47 -04001/*
2 * restorecond
3 *
4 * Copyright (C) 2006-2009 Red Hat
5 * see file 'COPYING' for use and warranty information
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of
10 * the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16.*
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20 * 02111-1307 USA
21 *
22 * Authors:
23 * Dan Walsh <dwalsh@redhat.com>
24 *
25*/
26
27#define _GNU_SOURCE
28#include <sys/inotify.h>
29#include <errno.h>
30#include <stdio.h>
31#include <stdlib.h>
32#include <signal.h>
33#include <string.h>
34#include <unistd.h>
35#include <ctype.h>
36#include <sys/types.h>
37#include <sys/stat.h>
38#include <syslog.h>
39#include <limits.h>
40#include <fcntl.h>
41
42#include "restorecond.h"
43#include "stringslist.h"
44#include <glib.h>
45#ifdef HAVE_DBUS
46#include <dbus/dbus.h>
47#include <dbus/dbus-glib.h>
48#include <dbus/dbus-glib-lowlevel.h>
49
50static DBusHandlerResult signal_filter (DBusConnection *connection, DBusMessage *message, void *user_data);
51
52static const char *PATH="/org/selinux/Restorecond";
53//static const char *BUSNAME="org.selinux.Restorecond";
54static const char *INTERFACE="org.selinux.RestorecondIface";
55static const char *RULE="type='signal',interface='org.selinux.RestorecondIface'";
56
Dan Walshf2051b22013-10-09 17:37:42 -040057static int local_lock_fd = -1;
Eric Paris48681bb2011-08-03 11:40:47 -040058
59static DBusHandlerResult
60signal_filter (DBusConnection *connection __attribute__ ((__unused__)), DBusMessage *message, void *user_data)
61{
62 /* User data is the event loop we are running in */
63 GMainLoop *loop = user_data;
64
65 /* A signal from the bus saying we are about to be disconnected */
66 if (dbus_message_is_signal
67 (message, INTERFACE, "Stop")) {
68
69 /* Tell the main loop to quit */
70 g_main_loop_quit (loop);
71 /* We have handled this message, don't pass it on */
72 return DBUS_HANDLER_RESULT_HANDLED;
73 }
74 /* A Ping signal on the com.burtonini.dbus.Signal interface */
75 else if (dbus_message_is_signal (message, INTERFACE, "Start")) {
76 DBusError error;
77 dbus_error_init (&error);
78 g_print("Start received\n");
79 return DBUS_HANDLER_RESULT_HANDLED;
80 }
81 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
82}
83
84static int dbus_server(GMainLoop *loop) {
85 DBusConnection *bus;
86 DBusError error;
87 dbus_error_init (&error);
88 bus = dbus_bus_get (DBUS_BUS_SESSION, &error);
89 if (bus) {
90 dbus_connection_setup_with_g_main (bus, NULL);
91
92 /* listening to messages from all objects as no path is specified */
93 dbus_bus_add_match (bus, RULE, &error); // see signals from the given interfacey
94 dbus_connection_add_filter (bus, signal_filter, loop, NULL);
95 return 0;
96 }
97 return -1;
98}
99
100#endif
101#include <selinux/selinux.h>
102#include <sys/file.h>
103
104/* size of the event structure, not counting name */
105#define EVENT_SIZE (sizeof (struct inotify_event))
106/* reasonable guess as to size of 1024 events */
107#define BUF_LEN (1024 * (EVENT_SIZE + 16))
108
109static gboolean
110io_channel_callback
111 (GIOChannel *source,
112 GIOCondition condition,
113 gpointer data __attribute__((__unused__)))
114{
115
116 char buffer[BUF_LEN+1];
117 gsize bytes_read;
118 unsigned int i = 0;
119
120 if (condition & G_IO_IN) {
121 /* Data is available. */
Dan Walsh13760422012-01-24 11:24:37 -0500122 g_io_channel_read_chars
Eric Paris48681bb2011-08-03 11:40:47 -0400123 (source, buffer,
124 sizeof (buffer),
Dan Walsh13760422012-01-24 11:24:37 -0500125 &bytes_read, NULL);
Eric Paris48681bb2011-08-03 11:40:47 -0400126
Dan Walsh4a145b72011-10-06 16:05:03 -0400127 if (! bytes_read) {
128 /* Sesssion/Terminal Ended */
129 exit(0);
130 }
131
Eric Paris48681bb2011-08-03 11:40:47 -0400132 while (i < bytes_read) {
133 struct inotify_event *event;
134 event = (struct inotify_event *)&buffer[i];
135 if (debug_mode)
136 printf("wd=%d mask=%u cookie=%u len=%u\n",
137 event->wd, event->mask,
138 event->cookie, event->len);
139 if (event->len)
140 watch_list_find(event->wd, event->name);
141
142 i += EVENT_SIZE + event->len;
143 }
144 }
145
146 /* An error happened while reading
147 the file. */
148
149 if (condition & G_IO_NVAL)
150 return FALSE;
151
152 /* We have reached the end of the
153 file. */
154
155 if (condition & G_IO_HUP) {
Dan Walsh13760422012-01-24 11:24:37 -0500156 g_io_channel_shutdown (source, 0, NULL);
Dan Walsh4a145b72011-10-06 16:05:03 -0400157 exit(0);
Eric Paris48681bb2011-08-03 11:40:47 -0400158 return FALSE;
159 }
160
161 /* Returning TRUE will make sure
162 the callback remains associated
163 to the channel. */
164
165 return TRUE;
166}
167
168int start() {
169#ifdef HAVE_DBUS
170 DBusConnection *bus;
171 DBusError error;
172 DBusMessage *message;
173
174 /* Get a connection to the session bus */
175 dbus_error_init (&error);
176 bus = dbus_bus_get (DBUS_BUS_SESSION, &error);
177 if (!bus) {
178 if (debug_mode)
179 g_warning ("Failed to connect to the D-BUS daemon: %s", error.message);
180 dbus_error_free (&error);
181 return 1;
182 }
183
184
185 /* Create a new signal "Start" on the interface,
186 * from the object */
187 message = dbus_message_new_signal (PATH,
188 INTERFACE, "Start");
189 /* Send the signal */
190 dbus_connection_send (bus, message, NULL);
191 /* Free the signal now we have finished with it */
192 dbus_message_unref (message);
193#endif /* HAVE_DBUS */
194 return 0;
195}
196
Nicolas Ioossc4a4a1a2014-09-14 23:41:49 +0200197static int local_server(void) {
Eric Paris48681bb2011-08-03 11:40:47 -0400198 // ! dbus, run as local service
199 char *ptr=NULL;
Dan Walsh9961ca62011-08-09 09:58:53 -0400200 if (asprintf(&ptr, "%s/.restorecond", homedir) < 0) {
201 if (debug_mode)
202 perror("asprintf");
203 return -1;
204 }
Dan Walshf2051b22013-10-09 17:37:42 -0400205 local_lock_fd = open(ptr, O_CREAT | O_WRONLY | O_NOFOLLOW | O_CLOEXEC, S_IRUSR | S_IWUSR);
Eric Paris48681bb2011-08-03 11:40:47 -0400206 if (debug_mode)
207 g_warning ("Lock file: %s", ptr);
208
209 free(ptr);
Dan Walshf2051b22013-10-09 17:37:42 -0400210 if (local_lock_fd < 0) {
Eric Paris48681bb2011-08-03 11:40:47 -0400211 if (debug_mode)
212 perror("open");
213 return -1;
214 }
Dan Walshf2051b22013-10-09 17:37:42 -0400215 if (flock(local_lock_fd, LOCK_EX | LOCK_NB) < 0) {
216 close(local_lock_fd);
Eric Paris48681bb2011-08-03 11:40:47 -0400217 if (debug_mode)
218 perror("flock");
219 return -1;
220 }
Dan Walsh4a145b72011-10-06 16:05:03 -0400221 /* watch for stdin/terminal going away */
222 GIOChannel *in = g_io_channel_unix_new(0);
223 g_io_add_watch_full( in,
224 G_PRIORITY_HIGH,
225 G_IO_IN|G_IO_ERR|G_IO_HUP,
226 io_channel_callback, NULL, NULL);
227
Eric Paris48681bb2011-08-03 11:40:47 -0400228 return 0;
229}
230
Dan Walshf2051b22013-10-09 17:37:42 -0400231static void end_local_server(void) {
232 if (local_lock_fd >= 0)
233 close(local_lock_fd);
234 local_lock_fd = -1;
235}
236
Eric Paris48681bb2011-08-03 11:40:47 -0400237int server(int master_fd, const char *watch_file) {
238 GMainLoop *loop;
239
240 loop = g_main_loop_new (NULL, FALSE);
241
242#ifdef HAVE_DBUS
243 if (dbus_server(loop) != 0)
244#endif /* HAVE_DBUS */
Dan Walsh4a145b72011-10-06 16:05:03 -0400245 if (local_server())
Eric Paris48681bb2011-08-03 11:40:47 -0400246 goto end;
247
248 read_config(master_fd, watch_file);
249
250 if (watch_list_isempty()) goto end;
251
252 set_matchpathcon_flags(MATCHPATHCON_NOTRANS);
253
254 GIOChannel *c = g_io_channel_unix_new(master_fd);
255
256 g_io_add_watch_full( c,
257 G_PRIORITY_HIGH,
258 G_IO_IN|G_IO_ERR|G_IO_HUP,
259 io_channel_callback, NULL, NULL);
260
261 g_main_loop_run (loop);
262
263end:
Dan Walshf2051b22013-10-09 17:37:42 -0400264 end_local_server();
Eric Paris48681bb2011-08-03 11:40:47 -0400265 g_main_loop_unref (loop);
266 return 0;
267}
268