1. Michał Górny
  2. libtinynotify-systemwide

Commits

Michał Górny  committed c2e7a29

fork() when talking to D-Bus.

Nowadays D-Bus no longer likes setuid processes so we need to actually
fork and then switch to the new user completely.

  • Participants
  • Parent commits 4dd05dd
  • Branches master

Comments (0)

Files changed (4)

File configure.ac

View file
 GTK_DOC_CHECK([1.15])
 
 PKG_CHECK_MODULES([LIBTINYNOTIFY], [libtinynotify])
-AC_CHECK_FUNCS([setresuid],,
+AC_CHECK_FUNCS([setreuid],,
 	[AC_MSG_ERROR([One of required system library functions was not found!])])
 PKG_CHECK_MODULES([PROCPS], [libprocps],, [
 	AC_CHECK_LIB([proc], [readproc],,

File doc/libtinynotify-systemwide-sections.txt

View file
 <SECTION>
 <FILE>systemwide</FILE>
 NOTIFY_ERROR_SYSCALL_FAILED
-NOTIFY_ERROR_UIDS_COMPROMISED
 NOTIFY_ERROR_NO_BUS_FOUND
 notification_send_systemwide
 </SECTION>

File lib/tinynotify-systemwide.c

View file
 #include <errno.h>
 
 #include <sys/types.h>
+#include <sys/wait.h>
 #include <pwd.h>
 
 #include <proc/readproc.h>
 const struct notify_error _error_syscall_failed = { "Required system call %s failed: %s" };
 const NotifyError NOTIFY_ERROR_SYSCALL_FAILED = &_error_syscall_failed;
 const struct notify_error _error_uids_compromised = { "Required system call setresuid() failed to restore UIDs: %s" };
-const NotifyError NOTIFY_ERROR_UIDS_COMPROMISED = &_error_uids_compromised;
 const struct notify_error _error_no_bus_found = { "No D-Bus session bus process found" };
 const NotifyError NOTIFY_ERROR_NO_BUS_FOUND = &_error_no_bus_found;
 
 	return NULL;
 }
 
-struct _sys_save_state {
-	int filled_in;
-
-	uid_t ruid;
-	uid_t euid;
-	uid_t suid;
-};
-
 static int _notification_send_for_bus(Notification n, NotifySession s,
-		uid_t uid, struct _sys_save_state *saved_state) {
-	int uids_switched = 0;
-	int ret = 0;
-
-	if (!saved_state->filled_in) {
-		if (getresuid(&saved_state->ruid, &saved_state->euid,
-					&saved_state->suid)) {
-			notify_session_set_error(s, NOTIFY_ERROR_SYSCALL_FAILED,
-					"getresuid()", strerror(errno));
-			return 0;
-		}
-
-		saved_state->filled_in = 1;
-	}
-
-	/* We need to use setresuid() because D-Bus checks uid & euid,
-	 * and we need to be able to return to root */
-	if (!setresuid(uid, uid, saved_state->suid))
-		uids_switched++;
-
-	/* Ensure getting a new connection. */
-	notify_session_disconnect(s);
-	ret = !notification_send(n, s);
-
-	if (uids_switched && setresuid(saved_state->ruid, saved_state->euid,
-				saved_state->suid)) {
-		notify_session_set_error(s, NOTIFY_ERROR_UIDS_COMPROMISED, strerror(errno));
-		saved_state->filled_in = 0;
-		/* XXX: what if notification_send() succeeded? */
-		return 0;
+		uid_t uid) {
+	int ret = -1;
+
+	/* D-Bus no longer likes to talk to setuid processes, so we need to
+	 * fork and switch UIDs completely. */
+	pid_t pid = fork();
+	switch (pid)
+	{
+		case -1:
+			break;
+
+		case 0:
+			/* We need to use setreuid() because D-Bus checks uid & euid */
+			setreuid(uid, uid);
+
+			/* Ensure getting a new connection. */
+			notify_session_disconnect(s);
+			exit(!!notification_send(n, s));
+
+		default:
+			waitpid(pid, &ret, 0);
 	}
 
 	return ret;
 	PROCTAB *proc;
 	proc_t *p = NULL;
 	int ret = 0;
-	struct _sys_save_state saved_state = {0};
 
 	proc = openproc(PROC_FILLCOM | PROC_FILLENV);
 	if (!proc) {
 				}
 			}
 
-			if (_notification_send_for_bus(n, s, p->euid, &saved_state))
+			if (!_notification_send_for_bus(n, s, p->euid))
 				ret += 1;
-			else if (!saved_state.filled_in) /* oh no, early failure! */
-				break;
 		}
 	}
 	closeproc(proc);

File lib/tinynotify-systemwide.h

View file
  */
 extern const NotifyError NOTIFY_ERROR_SYSCALL_FAILED;
 /**
- * NOTIFY_ERROR_UIDS_COMPROMISED
- *
- * An error raised when setresuid() fails to restore the original caller UID.
- *
- * This means that the application has lost its original UID and should
- * terminate ASAP.
- */
-extern const NotifyError NOTIFY_ERROR_UIDS_COMPROMISED;
-/**
  * NOTIFY_ERROR_NO_BUS_FOUND
  *
  * An error returned by notification_send_systemwide() when it was unable
  *
  * Send a notification to all notification daemons found (in procfs).
  *
+ * Please note that this function does fork().
+ *
  * Todo: support formatstring args.
  *
  * Returns: number of notifications actually sent or 0 if no daemon reached