wok-next annotate polkit105/stuff/patches/CVE-2015-4625.patch @ rev 20905

Update packages from ISO and LFS backages (all but toolchain)
author Aleksej Bobylev <al.bobylev@gmail.com>
date Tue Aug 07 00:30:45 2018 +0300 (2018-08-07)
parents
children
rev   line source
al@20905 1 From ea544ffc18405237ccd95d28d7f45afef49aca17 Mon Sep 17 00:00:00 2001
al@20905 2 From: Colin Walters <walters@redhat.com>
al@20905 3 Date: Thu, 4 Jun 2015 12:15:18 -0400
al@20905 4 Subject: CVE-2015-4625: Use unpredictable cookie values, keep them secret
al@20905 5 MIME-Version: 1.0
al@20905 6 Content-Type: text/plain; charset=UTF-8
al@20905 7 Content-Transfer-Encoding: 8bit
al@20905 8
al@20905 9 Tavis noted that it'd be possible with a 32 bit counter for someone to
al@20905 10 cause the cookie to wrap by creating Authentication requests in a
al@20905 11 loop.
al@20905 12
al@20905 13 Something important to note here is that wrapping of signed integers
al@20905 14 is undefined behavior in C, so we definitely want to fix that. All
al@20905 15 counter integers used in this patch are unsigned.
al@20905 16
al@20905 17 See the comment above `authentication_agent_generate_cookie` for
al@20905 18 details, but basically we're now using a cookie of the form:
al@20905 19
al@20905 20 ```
al@20905 21 <agent serial> - <agent random id> - <session serial> - <session
al@20905 22 random id>
al@20905 23 ```
al@20905 24
al@20905 25 Which has multiple 64 bit counters, plus unpredictable random 128 bit
al@20905 26 integer ids (effectively UUIDs, but we're not calling them that
al@20905 27 because we don't need to be globally unique.
al@20905 28
al@20905 29 We further ensure that the cookies are not visible to other processes
al@20905 30 by changing the setuid helper to accept them over standard input. This
al@20905 31 means that an attacker would have to guess both ids.
al@20905 32
al@20905 33 In any case, the security hole here is better fixed with the other
al@20905 34 change to bind user id (uid) of the agent with cookie lookups, making
al@20905 35 cookie guessing worthless.
al@20905 36
al@20905 37 Nevertheless, I think it's worth doing this change too, for defense in
al@20905 38 depth.
al@20905 39
al@20905 40 Bug: https://bugs.freedesktop.org/show_bug.cgi?id=90832
al@20905 41 CVE: CVE-2015-4625
al@20905 42 Reported-by: Tavis Ormandy <taviso@google.com>
al@20905 43 Reviewed-by: Miloslav Trmač <mitr@redhat.com>
al@20905 44 Signed-off-by: Colin Walters <walters@redhat.com>
al@20905 45
al@20905 46 diff --git a/src/polkitagent/polkitagenthelper-pam.c b/src/polkitagent/polkitagenthelper-pam.c
al@20905 47 index 937386e..19062aa 100644
al@20905 48 --- a/src/polkitagent/polkitagenthelper-pam.c
al@20905 49 +++ b/src/polkitagent/polkitagenthelper-pam.c
al@20905 50 @@ -65,7 +65,7 @@ main (int argc, char *argv[])
al@20905 51 {
al@20905 52 int rc;
al@20905 53 const char *user_to_auth;
al@20905 54 - const char *cookie;
al@20905 55 + char *cookie = NULL;
al@20905 56 struct pam_conv pam_conversation;
al@20905 57 pam_handle_t *pam_h;
al@20905 58 const void *authed_user;
al@20905 59 @@ -97,7 +97,7 @@ main (int argc, char *argv[])
al@20905 60 openlog ("polkit-agent-helper-1", LOG_CONS | LOG_PID, LOG_AUTHPRIV);
al@20905 61
al@20905 62 /* check for correct invocation */
al@20905 63 - if (argc != 3)
al@20905 64 + if (!(argc == 2 || argc == 3))
al@20905 65 {
al@20905 66 syslog (LOG_NOTICE, "inappropriate use of helper, wrong number of arguments [uid=%d]", getuid ());
al@20905 67 fprintf (stderr, "polkit-agent-helper-1: wrong number of arguments. This incident has been logged.\n");
al@20905 68 @@ -105,7 +105,10 @@ main (int argc, char *argv[])
al@20905 69 }
al@20905 70
al@20905 71 user_to_auth = argv[1];
al@20905 72 - cookie = argv[2];
al@20905 73 +
al@20905 74 + cookie = read_cookie (argc, argv);
al@20905 75 + if (!cookie)
al@20905 76 + goto error;
al@20905 77
al@20905 78 if (getuid () != 0)
al@20905 79 {
al@20905 80 @@ -203,6 +206,8 @@ main (int argc, char *argv[])
al@20905 81 goto error;
al@20905 82 }
al@20905 83
al@20905 84 + free (cookie);
al@20905 85 +
al@20905 86 #ifdef PAH_DEBUG
al@20905 87 fprintf (stderr, "polkit-agent-helper-1: successfully sent D-Bus message to PolicyKit daemon\n");
al@20905 88 #endif /* PAH_DEBUG */
al@20905 89 @@ -212,6 +217,7 @@ main (int argc, char *argv[])
al@20905 90 return 0;
al@20905 91
al@20905 92 error:
al@20905 93 + free (cookie);
al@20905 94 if (pam_h != NULL)
al@20905 95 pam_end (pam_h, rc);
al@20905 96
al@20905 97 diff --git a/src/polkitagent/polkitagenthelper-shadow.c b/src/polkitagent/polkitagenthelper-shadow.c
al@20905 98 index a4f73ac..e877915 100644
al@20905 99 --- a/src/polkitagent/polkitagenthelper-shadow.c
al@20905 100 +++ b/src/polkitagent/polkitagenthelper-shadow.c
al@20905 101 @@ -46,7 +46,7 @@ main (int argc, char *argv[])
al@20905 102 {
al@20905 103 struct spwd *shadow;
al@20905 104 const char *user_to_auth;
al@20905 105 - const char *cookie;
al@20905 106 + char *cookie = NULL;
al@20905 107 time_t now;
al@20905 108
al@20905 109 /* clear the entire environment to avoid attacks with
al@20905 110 @@ -67,7 +67,7 @@ main (int argc, char *argv[])
al@20905 111 openlog ("polkit-agent-helper-1", LOG_CONS | LOG_PID, LOG_AUTHPRIV);
al@20905 112
al@20905 113 /* check for correct invocation */
al@20905 114 - if (argc != 3)
al@20905 115 + if (!(argc == 2 || argc == 3))
al@20905 116 {
al@20905 117 syslog (LOG_NOTICE, "inappropriate use of helper, wrong number of arguments [uid=%d]", getuid ());
al@20905 118 fprintf (stderr, "polkit-agent-helper-1: wrong number of arguments. This incident has been logged.\n");
al@20905 119 @@ -86,7 +86,10 @@ main (int argc, char *argv[])
al@20905 120 }
al@20905 121
al@20905 122 user_to_auth = argv[1];
al@20905 123 - cookie = argv[2];
al@20905 124 +
al@20905 125 + cookie = read_cookie (argc, argv);
al@20905 126 + if (!cookie)
al@20905 127 + goto error;
al@20905 128
al@20905 129 #ifdef PAH_DEBUG
al@20905 130 fprintf (stderr, "polkit-agent-helper-1: user to auth is '%s'.\n", user_to_auth);
al@20905 131 @@ -153,6 +156,8 @@ main (int argc, char *argv[])
al@20905 132 goto error;
al@20905 133 }
al@20905 134
al@20905 135 + free (cookie);
al@20905 136 +
al@20905 137 #ifdef PAH_DEBUG
al@20905 138 fprintf (stderr, "polkit-agent-helper-1: successfully sent D-Bus message to PolicyKit daemon\n");
al@20905 139 #endif /* PAH_DEBUG */
al@20905 140 @@ -162,6 +167,7 @@ main (int argc, char *argv[])
al@20905 141 return 0;
al@20905 142
al@20905 143 error:
al@20905 144 + free (cookie);
al@20905 145 fprintf (stdout, "FAILURE\n");
al@20905 146 flush_and_wait ();
al@20905 147 return 1;
al@20905 148 diff --git a/src/polkitagent/polkitagenthelperprivate.c b/src/polkitagent/polkitagenthelperprivate.c
al@20905 149 index cfa77fc..e23f9f5 100644
al@20905 150 --- a/src/polkitagent/polkitagenthelperprivate.c
al@20905 151 +++ b/src/polkitagent/polkitagenthelperprivate.c
al@20905 152 @@ -23,6 +23,7 @@
al@20905 153 #include "config.h"
al@20905 154 #include "polkitagenthelperprivate.h"
al@20905 155 #include <stdio.h>
al@20905 156 +#include <string.h>
al@20905 157 #include <stdlib.h>
al@20905 158 #include <unistd.h>
al@20905 159
al@20905 160 @@ -45,6 +46,38 @@ _polkit_clearenv (void)
al@20905 161 #endif
al@20905 162
al@20905 163
al@20905 164 +char *
al@20905 165 +read_cookie (int argc, char **argv)
al@20905 166 +{
al@20905 167 + /* As part of CVE-2015-4625, we started passing the cookie
al@20905 168 + * on standard input, to ensure it's not visible to other
al@20905 169 + * processes. However, to ensure that things continue
al@20905 170 + * to work if the setuid binary is upgraded while old
al@20905 171 + * agents are still running (this will be common with
al@20905 172 + * package managers), we support both modes.
al@20905 173 + */
al@20905 174 + if (argc == 3)
al@20905 175 + return strdup (argv[2]);
al@20905 176 + else
al@20905 177 + {
al@20905 178 + char *ret = NULL;
al@20905 179 + size_t n = 0;
al@20905 180 + ssize_t r = getline (&ret, &n, stdin);
al@20905 181 + if (r == -1)
al@20905 182 + {
al@20905 183 + if (!feof (stdin))
al@20905 184 + perror ("getline");
al@20905 185 + free (ret);
al@20905 186 + return NULL;
al@20905 187 + }
al@20905 188 + else
al@20905 189 + {
al@20905 190 + g_strchomp (ret);
al@20905 191 + return ret;
al@20905 192 + }
al@20905 193 + }
al@20905 194 +}
al@20905 195 +
al@20905 196 gboolean
al@20905 197 send_dbus_message (const char *cookie, const char *user)
al@20905 198 {
al@20905 199 diff --git a/src/polkitagent/polkitagenthelperprivate.h b/src/polkitagent/polkitagenthelperprivate.h
al@20905 200 index aeca2c7..547fdcc 100644
al@20905 201 --- a/src/polkitagent/polkitagenthelperprivate.h
al@20905 202 +++ b/src/polkitagent/polkitagenthelperprivate.h
al@20905 203 @@ -38,6 +38,8 @@
al@20905 204
al@20905 205 int _polkit_clearenv (void);
al@20905 206
al@20905 207 +char *read_cookie (int argc, char **argv);
al@20905 208 +
al@20905 209 gboolean send_dbus_message (const char *cookie, const char *user);
al@20905 210
al@20905 211 void flush_and_wait ();
al@20905 212 diff --git a/src/polkitagent/polkitagentsession.c b/src/polkitagent/polkitagentsession.c
al@20905 213 index f014773..8b93ad0 100644
al@20905 214 --- a/src/polkitagent/polkitagentsession.c
al@20905 215 +++ b/src/polkitagent/polkitagentsession.c
al@20905 216 @@ -55,6 +55,7 @@
al@20905 217 #include <stdio.h>
al@20905 218 #include <sys/types.h>
al@20905 219 #include <sys/wait.h>
al@20905 220 +#include <gio/gunixoutputstream.h>
al@20905 221 #include <pwd.h>
al@20905 222
al@20905 223 #include "polkitagentmarshal.h"
al@20905 224 @@ -88,7 +89,7 @@ struct _PolkitAgentSession
al@20905 225 gchar *cookie;
al@20905 226 PolkitIdentity *identity;
al@20905 227
al@20905 228 - int child_stdin;
al@20905 229 + GOutputStream *child_stdin;
al@20905 230 int child_stdout;
al@20905 231 GPid child_pid;
al@20905 232
al@20905 233 @@ -129,7 +130,6 @@ G_DEFINE_TYPE (PolkitAgentSession, polkit_agent_session, G_TYPE_OBJECT);
al@20905 234 static void
al@20905 235 polkit_agent_session_init (PolkitAgentSession *session)
al@20905 236 {
al@20905 237 - session->child_stdin = -1;
al@20905 238 session->child_stdout = -1;
al@20905 239 }
al@20905 240
al@20905 241 @@ -395,11 +395,7 @@ kill_helper (PolkitAgentSession *session)
al@20905 242 session->child_stdout = -1;
al@20905 243 }
al@20905 244
al@20905 245 - if (session->child_stdin != -1)
al@20905 246 - {
al@20905 247 - g_warn_if_fail (close (session->child_stdin) == 0);
al@20905 248 - session->child_stdin = -1;
al@20905 249 - }
al@20905 250 + g_clear_object (&session->child_stdin);
al@20905 251
al@20905 252 session->helper_is_running = FALSE;
al@20905 253
al@20905 254 @@ -545,9 +541,9 @@ polkit_agent_session_response (PolkitAgentSession *session,
al@20905 255
al@20905 256 add_newline = (response[response_len] != '\n');
al@20905 257
al@20905 258 - write (session->child_stdin, response, response_len);
al@20905 259 + (void) g_output_stream_write_all (session->child_stdin, response, response_len, NULL, NULL, NULL);
al@20905 260 if (add_newline)
al@20905 261 - write (session->child_stdin, newline, 1);
al@20905 262 + (void) g_output_stream_write_all (session->child_stdin, newline, 1, NULL, NULL, NULL);
al@20905 263 }
al@20905 264
al@20905 265 /**
al@20905 266 @@ -567,8 +563,9 @@ polkit_agent_session_initiate (PolkitAgentSession *session)
al@20905 267 {
al@20905 268 uid_t uid;
al@20905 269 GError *error;
al@20905 270 - gchar *helper_argv[4];
al@20905 271 + gchar *helper_argv[3];
al@20905 272 struct passwd *passwd;
al@20905 273 + int stdin_fd = -1;
al@20905 274
al@20905 275 g_return_if_fail (POLKIT_AGENT_IS_SESSION (session));
al@20905 276
al@20905 277 @@ -600,10 +597,8 @@ polkit_agent_session_initiate (PolkitAgentSession *session)
al@20905 278
al@20905 279 helper_argv[0] = PACKAGE_PREFIX "/lib/polkit-1/polkit-agent-helper-1";
al@20905 280 helper_argv[1] = passwd->pw_name;
al@20905 281 - helper_argv[2] = session->cookie;
al@20905 282 - helper_argv[3] = NULL;
al@20905 283 + helper_argv[2] = NULL;
al@20905 284
al@20905 285 - session->child_stdin = -1;
al@20905 286 session->child_stdout = -1;
al@20905 287
al@20905 288 error = NULL;
al@20905 289 @@ -615,7 +610,7 @@ polkit_agent_session_initiate (PolkitAgentSession *session)
al@20905 290 NULL,
al@20905 291 NULL,
al@20905 292 &session->child_pid,
al@20905 293 - &session->child_stdin,
al@20905 294 + &stdin_fd,
al@20905 295 &session->child_stdout,
al@20905 296 NULL,
al@20905 297 &error))
al@20905 298 @@ -628,6 +623,13 @@ polkit_agent_session_initiate (PolkitAgentSession *session)
al@20905 299 if (G_UNLIKELY (_show_debug ()))
al@20905 300 g_print ("PolkitAgentSession: spawned helper with pid %d\n", (gint) session->child_pid);
al@20905 301
al@20905 302 + session->child_stdin = (GOutputStream*)g_unix_output_stream_new (stdin_fd, TRUE);
al@20905 303 +
al@20905 304 + /* Write the cookie on stdin so it can't be seen by other processes */
al@20905 305 + (void) g_output_stream_write_all (session->child_stdin, session->cookie, strlen (session->cookie),
al@20905 306 + NULL, NULL, NULL);
al@20905 307 + (void) g_output_stream_write_all (session->child_stdin, "\n", 1, NULL, NULL, NULL);
al@20905 308 +
al@20905 309 session->child_stdout_channel = g_io_channel_unix_new (session->child_stdout);
al@20905 310 session->child_stdout_watch_source = g_io_create_watch (session->child_stdout_channel,
al@20905 311 G_IO_IN | G_IO_ERR | G_IO_HUP);
al@20905 312 diff --git a/src/polkitbackend/polkitbackendinteractiveauthority.c b/src/polkitbackend/polkitbackendinteractiveauthority.c
al@20905 313 index 3f339e9..15adc6a 100644
al@20905 314 --- a/src/polkitbackend/polkitbackendinteractiveauthority.c
al@20905 315 +++ b/src/polkitbackend/polkitbackendinteractiveauthority.c
al@20905 316 @@ -214,6 +214,8 @@ typedef struct
al@20905 317
al@20905 318 GDBusConnection *system_bus_connection;
al@20905 319 guint name_owner_changed_signal_id;
al@20905 320 +
al@20905 321 + guint64 agent_serial;
al@20905 322 } PolkitBackendInteractiveAuthorityPrivate;
al@20905 323
al@20905 324 /* ---------------------------------------------------------------------------------------------------- */
al@20905 325 @@ -439,11 +441,15 @@ struct AuthenticationAgent
al@20905 326 volatile gint ref_count;
al@20905 327
al@20905 328 PolkitSubject *scope;
al@20905 329 + guint64 serial;
al@20905 330
al@20905 331 gchar *locale;
al@20905 332 GVariant *registration_options;
al@20905 333 gchar *object_path;
al@20905 334 gchar *unique_system_bus_name;
al@20905 335 + GRand *cookie_pool;
al@20905 336 + gchar *cookie_prefix;
al@20905 337 + guint64 cookie_serial;
al@20905 338
al@20905 339 GDBusProxy *proxy;
al@20905 340
al@20905 341 @@ -1427,9 +1433,54 @@ authentication_session_cancelled_cb (GCancellable *cancellable,
al@20905 342 authentication_session_cancel (session);
al@20905 343 }
al@20905 344
al@20905 345 +/* We're not calling this a UUID, but it's basically
al@20905 346 + * the same thing, just not formatted that way because:
al@20905 347 + *
al@20905 348 + * - I'm too lazy to do it
al@20905 349 + * - If we did, people might think it was actually
al@20905 350 + * generated from /dev/random, which we're not doing
al@20905 351 + * because this value doesn't actually need to be
al@20905 352 + * globally unique.
al@20905 353 + */
al@20905 354 +static void
al@20905 355 +append_rand_u128_str (GString *buf,
al@20905 356 + GRand *pool)
al@20905 357 +{
al@20905 358 + g_string_append_printf (buf, "%08x%08x%08x%08x",
al@20905 359 + g_rand_int (pool),
al@20905 360 + g_rand_int (pool),
al@20905 361 + g_rand_int (pool),
al@20905 362 + g_rand_int (pool));
al@20905 363 +}
al@20905 364 +
al@20905 365 +/* A value that should be unique to the (AuthenticationAgent, AuthenticationSession)
al@20905 366 + * pair, and not guessable by other agents.
al@20905 367 + *
al@20905 368 + * <agent serial> - <agent uuid> - <session serial> - <session uuid>
al@20905 369 + *
al@20905 370 + * See http://lists.freedesktop.org/archives/polkit-devel/2015-June/000425.html
al@20905 371 + *
al@20905 372 + */
al@20905 373 +static gchar *
al@20905 374 +authentication_agent_generate_cookie (AuthenticationAgent *agent)
al@20905 375 +{
al@20905 376 + GString *buf = g_string_new ("");
al@20905 377 +
al@20905 378 + g_string_append (buf, agent->cookie_prefix);
al@20905 379 +
al@20905 380 + g_string_append_c (buf, '-');
al@20905 381 + agent->cookie_serial++;
al@20905 382 + g_string_append_printf (buf, "%" G_GUINT64_FORMAT,
al@20905 383 + agent->cookie_serial);
al@20905 384 + g_string_append_c (buf, '-');
al@20905 385 + append_rand_u128_str (buf, agent->cookie_pool);
al@20905 386 +
al@20905 387 + return g_string_free (buf, FALSE);
al@20905 388 +}
al@20905 389 +
al@20905 390 +
al@20905 391 static AuthenticationSession *
al@20905 392 authentication_session_new (AuthenticationAgent *agent,
al@20905 393 - const gchar *cookie,
al@20905 394 PolkitSubject *subject,
al@20905 395 PolkitIdentity *user_of_subject,
al@20905 396 PolkitSubject *caller,
al@20905 397 @@ -1447,7 +1498,7 @@ authentication_session_new (AuthenticationAgent *agent,
al@20905 398
al@20905 399 session = g_new0 (AuthenticationSession, 1);
al@20905 400 session->agent = authentication_agent_ref (agent);
al@20905 401 - session->cookie = g_strdup (cookie);
al@20905 402 + session->cookie = authentication_agent_generate_cookie (agent);
al@20905 403 session->subject = g_object_ref (subject);
al@20905 404 session->user_of_subject = g_object_ref (user_of_subject);
al@20905 405 session->caller = g_object_ref (caller);
al@20905 406 @@ -1496,16 +1547,6 @@ authentication_session_free (AuthenticationSession *session)
al@20905 407 g_free (session);
al@20905 408 }
al@20905 409
al@20905 410 -static gchar *
al@20905 411 -authentication_agent_new_cookie (AuthenticationAgent *agent)
al@20905 412 -{
al@20905 413 - static gint counter = 0;
al@20905 414 -
al@20905 415 - /* TODO: use a more random-looking cookie */
al@20905 416 -
al@20905 417 - return g_strdup_printf ("cookie%d", counter++);
al@20905 418 -}
al@20905 419 -
al@20905 420 static PolkitSubject *
al@20905 421 authentication_agent_get_scope (AuthenticationAgent *agent)
al@20905 422 {
al@20905 423 @@ -1553,12 +1594,15 @@ authentication_agent_unref (AuthenticationAgent *agent)
al@20905 424 g_free (agent->unique_system_bus_name);
al@20905 425 if (agent->registration_options != NULL)
al@20905 426 g_variant_unref (agent->registration_options);
al@20905 427 + g_rand_free (agent->cookie_pool);
al@20905 428 + g_free (agent->cookie_prefix);
al@20905 429 g_free (agent);
al@20905 430 }
al@20905 431 }
al@20905 432
al@20905 433 static AuthenticationAgent *
al@20905 434 -authentication_agent_new (PolkitSubject *scope,
al@20905 435 +authentication_agent_new (guint64 serial,
al@20905 436 + PolkitSubject *scope,
al@20905 437 const gchar *unique_system_bus_name,
al@20905 438 const gchar *locale,
al@20905 439 const gchar *object_path,
al@20905 440 @@ -1592,6 +1636,7 @@ authentication_agent_new (PolkitSubject *scope,
al@20905 441
al@20905 442 agent = g_new0 (AuthenticationAgent, 1);
al@20905 443 agent->ref_count = 1;
al@20905 444 + agent->serial = serial;
al@20905 445 agent->scope = g_object_ref (scope);
al@20905 446 agent->object_path = g_strdup (object_path);
al@20905 447 agent->unique_system_bus_name = g_strdup (unique_system_bus_name);
al@20905 448 @@ -1599,6 +1644,25 @@ authentication_agent_new (PolkitSubject *scope,
al@20905 449 agent->registration_options = registration_options != NULL ? g_variant_ref (registration_options) : NULL;
al@20905 450 agent->proxy = proxy;
al@20905 451
al@20905 452 + {
al@20905 453 + GString *cookie_prefix = g_string_new ("");
al@20905 454 + GRand *agent_private_rand = g_rand_new ();
al@20905 455 +
al@20905 456 + g_string_append_printf (cookie_prefix, "%" G_GUINT64_FORMAT "-", agent->serial);
al@20905 457 +
al@20905 458 + /* Use a uniquely seeded PRNG to get a prefix cookie for this agent,
al@20905 459 + * whose sequence will not correlate with the per-authentication session
al@20905 460 + * cookies.
al@20905 461 + */
al@20905 462 + append_rand_u128_str (cookie_prefix, agent_private_rand);
al@20905 463 + g_rand_free (agent_private_rand);
al@20905 464 +
al@20905 465 + agent->cookie_prefix = g_string_free (cookie_prefix, FALSE);
al@20905 466 +
al@20905 467 + /* And a newly seeded pool for per-session cookies */
al@20905 468 + agent->cookie_pool = g_rand_new ();
al@20905 469 + }
al@20905 470 +
al@20905 471 return agent;
al@20905 472 }
al@20905 473
al@20905 474 @@ -2193,7 +2257,6 @@ authentication_agent_initiate_challenge (AuthenticationAgent *agent,
al@20905 475 {
al@20905 476 PolkitBackendInteractiveAuthorityPrivate *priv = POLKIT_BACKEND_INTERACTIVE_AUTHORITY_GET_PRIVATE (authority);
al@20905 477 AuthenticationSession *session;
al@20905 478 - gchar *cookie;
al@20905 479 GList *l;
al@20905 480 GList *identities;
al@20905 481 gchar *localized_message;
al@20905 482 @@ -2215,8 +2278,6 @@ authentication_agent_initiate_challenge (AuthenticationAgent *agent,
al@20905 483 &localized_icon_name,
al@20905 484 &localized_details);
al@20905 485
al@20905 486 - cookie = authentication_agent_new_cookie (agent);
al@20905 487 -
al@20905 488 identities = NULL;
al@20905 489
al@20905 490 /* select admin user if required by the implicit authorization */
al@20905 491 @@ -2279,7 +2340,6 @@ authentication_agent_initiate_challenge (AuthenticationAgent *agent,
al@20905 492 user_identities = g_list_prepend (NULL, polkit_unix_user_new (0));
al@20905 493
al@20905 494 session = authentication_session_new (agent,
al@20905 495 - cookie,
al@20905 496 subject,
al@20905 497 user_of_subject,
al@20905 498 caller,
al@20905 499 @@ -2335,7 +2395,6 @@ authentication_agent_initiate_challenge (AuthenticationAgent *agent,
al@20905 500 g_list_free_full (user_identities, g_object_unref);
al@20905 501 g_list_foreach (identities, (GFunc) g_object_unref, NULL);
al@20905 502 g_list_free (identities);
al@20905 503 - g_free (cookie);
al@20905 504
al@20905 505 g_free (localized_message);
al@20905 506 g_free (localized_icon_name);
al@20905 507 @@ -2482,7 +2541,9 @@ polkit_backend_interactive_authority_register_authentication_agent (PolkitBacken
al@20905 508 goto out;
al@20905 509 }
al@20905 510
al@20905 511 - agent = authentication_agent_new (subject,
al@20905 512 + priv->agent_serial++;
al@20905 513 + agent = authentication_agent_new (priv->agent_serial,
al@20905 514 + subject,
al@20905 515 polkit_system_bus_name_get_name (POLKIT_SYSTEM_BUS_NAME (caller)),
al@20905 516 locale,
al@20905 517 object_path,
al@20905 518 --
al@20905 519 cgit v0.10.2
al@20905 520
al@20905 521 From 493aa5dc1d278ab9097110c1262f5229bbaf1766 Mon Sep 17 00:00:00 2001
al@20905 522 From: Colin Walters <walters@redhat.com>
al@20905 523 Date: Wed, 17 Jun 2015 13:07:02 -0400
al@20905 524 Subject: CVE-2015-4625: Bind use of cookies to specific uids
al@20905 525 MIME-Version: 1.0
al@20905 526 Content-Type: text/plain; charset=UTF-8
al@20905 527 Content-Transfer-Encoding: 8bit
al@20905 528
al@20905 529 http://lists.freedesktop.org/archives/polkit-devel/2015-June/000425.html
al@20905 530
al@20905 531 The "cookie" value that Polkit hands out is global to all polkit
al@20905 532 users. And when `AuthenticationAgentResponse` is invoked, we
al@20905 533 previously only received the cookie and *target* identity, and
al@20905 534 attempted to find an agent from that.
al@20905 535
al@20905 536 The problem is that the current cookie is just an integer
al@20905 537 counter, and if it overflowed, it would be possible for
al@20905 538 an successful authorization in one session to trigger a response
al@20905 539 in another session.
al@20905 540
al@20905 541 The overflow and ability to guess the cookie were fixed by the
al@20905 542 previous patch.
al@20905 543
al@20905 544 This patch is conceptually further hardening on top of that. Polkit
al@20905 545 currently treats uids as equivalent from a security domain
al@20905 546 perspective; there is no support for
al@20905 547 SELinux/AppArmor/etc. differentiation.
al@20905 548
al@20905 549 We can retrieve the uid from `getuid()` in the setuid helper, which
al@20905 550 allows us to ensure the uid invoking `AuthenticationAgentResponse2`
al@20905 551 matches that of the agent.
al@20905 552
al@20905 553 Then the authority only looks at authentication sessions matching the
al@20905 554 cookie that were created by a matching uid, thus removing the ability
al@20905 555 for different uids to interfere with each other entirely.
al@20905 556
al@20905 557 Several fixes to this patch were contributed by:
al@20905 558 Miloslav Trmač <mitr@redhat.com>
al@20905 559
al@20905 560 Bug: https://bugs.freedesktop.org/show_bug.cgi?id=90837
al@20905 561 CVE: CVE-2015-4625
al@20905 562 Reported-by: Tavis Ormandy <taviso@google.com>
al@20905 563 Reviewed-by: Miloslav Trmač <mitr@redhat.com>
al@20905 564 Signed-off-by: Colin Walters <walters@redhat.com>
al@20905 565
al@20905 566 diff --git a/data/org.freedesktop.PolicyKit1.AuthenticationAgent.xml b/data/org.freedesktop.PolicyKit1.AuthenticationAgent.xml
al@20905 567 index 3b519c2..5beef7d 100644
al@20905 568 --- a/data/org.freedesktop.PolicyKit1.AuthenticationAgent.xml
al@20905 569 +++ b/data/org.freedesktop.PolicyKit1.AuthenticationAgent.xml
al@20905 570 @@ -8,7 +8,19 @@
al@20905 571 <annotation name="org.gtk.EggDBus.DocString" value="<para>This D-Bus interface is used for communication between the system-wide PolicyKit daemon and one or more authentication agents each running in a user session.</para><para>An authentication agent must implement this interface and register (passing the object path of the object implementing the interface) using the org.freedesktop.PolicyKit1.Authority.RegisterAuthenticationAgent() and org.freedesktop.PolicyKit1.Authority.UnregisterAuthenticationAgent() methods on the #org.freedesktop.PolicyKit1.Authority interface of the PolicyKit daemon.</para>"/>
al@20905 572
al@20905 573 <method name="BeginAuthentication">
al@20905 574 - <annotation name="org.gtk.EggDBus.DocString" value="<para>Called by the PolicyKit daemon when the authentication agent needs the user to authenticate as one of the identities in @identities for the action with the identifier @action_id.</para><para>Upon succesful authentication, the authentication agent must invoke the org.freedesktop.PolicyKit1.Authority.AuthenticationAgentResponse() method on the #org.freedesktop.PolicyKit1.Authority interface of the PolicyKit daemon before returning.</para><para>If the user dismisses the authentication dialog, the authentication agent should return an error.</para>"/>
al@20905 575 + <annotation name="org.gtk.EggDBus.DocString" value="<para>Called
al@20905 576 + by the PolicyKit daemon when the authentication agent needs the
al@20905 577 + user to authenticate as one of the identities in @identities for
al@20905 578 + the action with the identifier @action_id.</para><para>This
al@20905 579 + authentication is normally achieved via the
al@20905 580 + polkit_agent_session_response() API, which invokes a private
al@20905 581 + setuid helper process to verify the authentication. When
al@20905 582 + successful, it calls the
al@20905 583 + org.freedesktop.PolicyKit1.Authority.AuthenticationAgentResponse2()
al@20905 584 + method on the #org.freedesktop.PolicyKit1.Authority interface of
al@20905 585 + the PolicyKit daemon before returning. If the user dismisses the
al@20905 586 + authentication dialog, the authentication agent should call
al@20905 587 + polkit_agent_session_cancel().</para>"/>
al@20905 588
al@20905 589 <arg name="action_id" direction="in" type="s">
al@20905 590 <annotation name="org.gtk.EggDBus.DocString" value="The identifier for the action that the user is authentication for."/>
al@20905 591 diff --git a/data/org.freedesktop.PolicyKit1.Authority.xml b/data/org.freedesktop.PolicyKit1.Authority.xml
al@20905 592 index fbfb9cd..f9021ee 100644
al@20905 593 --- a/data/org.freedesktop.PolicyKit1.Authority.xml
al@20905 594 +++ b/data/org.freedesktop.PolicyKit1.Authority.xml
al@20905 595 @@ -313,7 +313,29 @@
al@20905 596 </method>
al@20905 597
al@20905 598 <method name="AuthenticationAgentResponse">
al@20905 599 - <annotation name="org.gtk.EggDBus.DocString" value="Method for authentication agents to invoke on successful authentication. This method will fail unless a sufficiently privileged caller invokes it."/>
al@20905 600 + <annotation name="org.gtk.EggDBus.DocString" value="Method for authentication agents to invoke on successful
al@20905 601 +authentication, intended only for use by a privileged helper process
al@20905 602 +internal to polkit."/>
al@20905 603 +
al@20905 604 + <arg name="cookie" direction="in" type="s">
al@20905 605 + <annotation name="org.gtk.EggDBus.DocString" value="The cookie identifying the authentication request that was passed to the authentication agent."/>
al@20905 606 + </arg>
al@20905 607 +
al@20905 608 + <arg name="identity" direction="in" type="(sa{sv})">
al@20905 609 + <annotation name="org.gtk.EggDBus.Type" value="Identity"/>
al@20905 610 + <annotation name="org.gtk.EggDBus.DocString" value="A #Identity struct describing what identity was authenticated."/>
al@20905 611 + </arg>
al@20905 612 + </method>
al@20905 613 +
al@20905 614 + <method name="AuthenticationAgentResponse2">
al@20905 615 + <annotation name="org.gtk.EggDBus.DocString" value="Method for authentication agents to invoke on successful
al@20905 616 +authentication, intended only for use by a privileged helper process
al@20905 617 +internal to polkit. Note this method was added in 0.114, and should be preferred over AuthenticationAgentResponse
al@20905 618 +as it fixes a security issue."/>
al@20905 619 +
al@20905 620 + <arg name="uid" direction="in" type="u">
al@20905 621 + <annotation name="org.gtk.EggDBus.DocString" value="The real uid of the agent. Normally set by the setuid helper program."/>
al@20905 622 + </arg>
al@20905 623
al@20905 624 <arg name="cookie" direction="in" type="s">
al@20905 625 <annotation name="org.gtk.EggDBus.DocString" value="The cookie identifying the authentication request that was passed to the authentication agent."/>
al@20905 626 diff --git a/docs/polkit/docbook-interface-org.freedesktop.PolicyKit1.Authority.xml b/docs/polkit/docbook-interface-org.freedesktop.PolicyKit1.Authority.xml
al@20905 627 index 6525e25..e66bf53 100644
al@20905 628 --- a/docs/polkit/docbook-interface-org.freedesktop.PolicyKit1.Authority.xml
al@20905 629 +++ b/docs/polkit/docbook-interface-org.freedesktop.PolicyKit1.Authority.xml
al@20905 630 @@ -42,6 +42,8 @@ Structure <link linkend="eggdbus-struct-TemporaryAuthorization">TemporaryAuth
al@20905 631 IN String object_path)
al@20905 632 <link linkend="eggdbus-method-org.freedesktop.PolicyKit1.Authority.AuthenticationAgentResponse">AuthenticationAgentResponse</link> (IN String cookie,
al@20905 633 IN <link linkend="eggdbus-struct-Identity">Identity</link> identity)
al@20905 634 +<link linkend="eggdbus-method-org.freedesktop.PolicyKit1.Authority.AuthenticationAgentResponse">AuthenticationAgentResponse2</link> (IN uint32 uid, IN String cookie,
al@20905 635 + IN <link linkend="eggdbus-struct-Identity">Identity</link> identity)
al@20905 636 <link linkend="eggdbus-method-org.freedesktop.PolicyKit1.Authority.EnumerateTemporaryAuthorizations">EnumerateTemporaryAuthorizations</link> (IN <link linkend="eggdbus-struct-Subject">Subject</link> subject,
al@20905 637 OUT Array&lt;<link linkend="eggdbus-struct-TemporaryAuthorization">TemporaryAuthorization</link>&gt; temporary_authorizations)
al@20905 638 <link linkend="eggdbus-method-org.freedesktop.PolicyKit1.Authority.RevokeTemporaryAuthorizations">RevokeTemporaryAuthorizations</link> (IN <link linkend="eggdbus-struct-Subject">Subject</link> subject)
al@20905 639 @@ -777,10 +779,52 @@ AuthenticationAgentResponse (IN String cookie,
al@20905 640 IN <link linkend="eggdbus-struct-Identity">Identity</link> identity)
al@20905 641 </programlisting>
al@20905 642 <para>
al@20905 643 -Method for authentication agents to invoke on successful authentication. This method will fail unless a sufficiently privileged caller invokes it.
al@20905 644 +Method for authentication agents to invoke on successful
al@20905 645 +authentication, intended only for use by a privileged helper process
al@20905 646 +internal to polkit. Deprecated in favor of AuthenticationAgentResponse2.
al@20905 647 + </para>
al@20905 648 +<variablelist role="params">
al@20905 649 + <varlistentry>
al@20905 650 + <term><literal>IN String <parameter>cookie</parameter></literal>:</term>
al@20905 651 + <listitem>
al@20905 652 + <para>
al@20905 653 +The cookie identifying the authentication request that was passed to the authentication agent.
al@20905 654 + </para>
al@20905 655 + </listitem>
al@20905 656 + </varlistentry>
al@20905 657 + <varlistentry>
al@20905 658 + <term><literal>IN <link linkend="eggdbus-struct-Identity">Identity</link> <parameter>identity</parameter></literal>:</term>
al@20905 659 + <listitem>
al@20905 660 + <para>
al@20905 661 +A <link linkend="eggdbus-struct-Identity">Identity</link> struct describing what identity was authenticated.
al@20905 662 + </para>
al@20905 663 + </listitem>
al@20905 664 + </varlistentry>
al@20905 665 +</variablelist>
al@20905 666 + </refsect2>
al@20905 667 + <refsect2 role="function" id="eggdbus-method-org.freedesktop.PolicyKit1.Authority.AuthenticationAgentResponse2">
al@20905 668 + <title>AuthenticationAgentResponse2 ()</title>
al@20905 669 + <programlisting>
al@20905 670 +AuthenticationAgentResponse2 (IN uint32 uid,
al@20905 671 + IN String cookie,
al@20905 672 + IN <link linkend="eggdbus-struct-Identity">Identity</link> identity)
al@20905 673 + </programlisting>
al@20905 674 + <para>
al@20905 675 +Method for authentication agents to invoke on successful
al@20905 676 +authentication, intended only for use by a privileged helper process
al@20905 677 +internal to polkit. Note this method was introduced in 0.114 to fix a security issue.
al@20905 678 </para>
al@20905 679 <variablelist role="params">
al@20905 680 <varlistentry>
al@20905 681 + <term><literal>IN uint32 <parameter>uid</parameter></literal>:</term>
al@20905 682 + <listitem>
al@20905 683 + <para>
al@20905 684 +The user id of the agent; normally this is the owner of the parent pid
al@20905 685 +of the process that invoked the internal setuid helper.
al@20905 686 + </para>
al@20905 687 + </listitem>
al@20905 688 + </varlistentry>
al@20905 689 + <varlistentry>
al@20905 690 <term><literal>IN String <parameter>cookie</parameter></literal>:</term>
al@20905 691 <listitem>
al@20905 692 <para>
al@20905 693 diff --git a/docs/polkit/overview.xml b/docs/polkit/overview.xml
al@20905 694 index 150a7bc..176d2ea 100644
al@20905 695 --- a/docs/polkit/overview.xml
al@20905 696 +++ b/docs/polkit/overview.xml
al@20905 697 @@ -314,16 +314,18 @@
al@20905 698 <para>
al@20905 699 Authentication agents are provided by desktop environments. When
al@20905 700 an user session starts, the agent registers with the polkit
al@20905 701 - Authority using
al@20905 702 - the <link linkend="eggdbus-method-org.freedesktop.PolicyKit1.Authority.RegisterAuthenticationAgent">RegisterAuthenticationAgent()</link>
al@20905 703 + Authority using the <link
al@20905 704 + linkend="eggdbus-method-org.freedesktop.PolicyKit1.Authority.RegisterAuthenticationAgent">RegisterAuthenticationAgent()</link>
al@20905 705 method. When services are needed, the authority will invoke
al@20905 706 - methods on
al@20905 707 - the <link linkend="eggdbus-interface-org.freedesktop.PolicyKit1.AuthenticationAgent">org.freedesktop.PolicyKit1.AuthenticationAgent</link>
al@20905 708 + methods on the <link
al@20905 709 + linkend="eggdbus-interface-org.freedesktop.PolicyKit1.AuthenticationAgent">org.freedesktop.PolicyKit1.AuthenticationAgent</link>
al@20905 710 D-Bus interface. Once the user is authenticated, (a privileged
al@20905 711 - part of) the agent invokes
al@20905 712 - the <link linkend="eggdbus-method-org.freedesktop.PolicyKit1.Authority.AuthenticationAgentResponse">AuthenticationAgentResponse()</link>
al@20905 713 - method. Note that the polkit Authority itself does not care
al@20905 714 - how the agent authenticates the user.
al@20905 715 + part of) the agent invokes the <link
al@20905 716 + linkend="eggdbus-method-org.freedesktop.PolicyKit1.Authority.AuthenticationAgentResponse">AuthenticationAgentResponse()</link>
al@20905 717 + method. This method should be treated as an internal
al@20905 718 + implementation detail, and callers should use the public shared
al@20905 719 + library API to invoke it, which currently uses a setuid helper
al@20905 720 + program.
al@20905 721 </para>
al@20905 722 <para>
al@20905 723 The <link linkend="ref-authentication-agent-api">libpolkit-agent-1</link>
al@20905 724 diff --git a/src/polkit/polkitauthority.c b/src/polkit/polkitauthority.c
al@20905 725 index ab6d3cd..6bd684a 100644
al@20905 726 --- a/src/polkit/polkitauthority.c
al@20905 727 +++ b/src/polkit/polkitauthority.c
al@20905 728 @@ -1492,6 +1492,14 @@ polkit_authority_authentication_agent_response (PolkitAuthority *authority,
al@20905 729 gpointer user_data)
al@20905 730 {
al@20905 731 GVariant *identity_value;
al@20905 732 + /* Note that in reality, this API is only accessible to root, and
al@20905 733 + * only called from the setuid helper `polkit-agent-helper-1`.
al@20905 734 + *
al@20905 735 + * However, because this is currently public API, we avoid
al@20905 736 + * triggering warnings from ABI diff type programs by just grabbing
al@20905 737 + * the real uid of the caller here.
al@20905 738 + */
al@20905 739 + uid_t uid = getuid ();
al@20905 740
al@20905 741 g_return_if_fail (POLKIT_IS_AUTHORITY (authority));
al@20905 742 g_return_if_fail (cookie != NULL);
al@20905 743 @@ -1501,8 +1509,9 @@ polkit_authority_authentication_agent_response (PolkitAuthority *authority,
al@20905 744 identity_value = polkit_identity_to_gvariant (identity);
al@20905 745 g_variant_ref_sink (identity_value);
al@20905 746 g_dbus_proxy_call (authority->proxy,
al@20905 747 - "AuthenticationAgentResponse",
al@20905 748 - g_variant_new ("(s@(sa{sv}))",
al@20905 749 + "AuthenticationAgentResponse2",
al@20905 750 + g_variant_new ("(us@(sa{sv}))",
al@20905 751 + (guint32)uid,
al@20905 752 cookie,
al@20905 753 identity_value),
al@20905 754 G_DBUS_CALL_FLAGS_NONE,
al@20905 755 diff --git a/src/polkitbackend/polkitbackendauthority.c b/src/polkitbackend/polkitbackendauthority.c
al@20905 756 index 601a974..03a4e84 100644
al@20905 757 --- a/src/polkitbackend/polkitbackendauthority.c
al@20905 758 +++ b/src/polkitbackend/polkitbackendauthority.c
al@20905 759 @@ -355,6 +355,7 @@ polkit_backend_authority_unregister_authentication_agent (PolkitBackendAuthority
al@20905 760 gboolean
al@20905 761 polkit_backend_authority_authentication_agent_response (PolkitBackendAuthority *authority,
al@20905 762 PolkitSubject *caller,
al@20905 763 + uid_t uid,
al@20905 764 const gchar *cookie,
al@20905 765 PolkitIdentity *identity,
al@20905 766 GError **error)
al@20905 767 @@ -373,7 +374,7 @@ polkit_backend_authority_authentication_agent_response (PolkitBackendAuthority
al@20905 768 }
al@20905 769 else
al@20905 770 {
al@20905 771 - return klass->authentication_agent_response (authority, caller, cookie, identity, error);
al@20905 772 + return klass->authentication_agent_response (authority, caller, uid, cookie, identity, error);
al@20905 773 }
al@20905 774 }
al@20905 775
al@20905 776 @@ -587,6 +588,11 @@ static const gchar *server_introspection_data =
al@20905 777 " <arg type='s' name='cookie' direction='in'/>"
al@20905 778 " <arg type='(sa{sv})' name='identity' direction='in'/>"
al@20905 779 " </method>"
al@20905 780 + " <method name='AuthenticationAgentResponse2'>"
al@20905 781 + " <arg type='u' name='uid' direction='in'/>"
al@20905 782 + " <arg type='s' name='cookie' direction='in'/>"
al@20905 783 + " <arg type='(sa{sv})' name='identity' direction='in'/>"
al@20905 784 + " </method>"
al@20905 785 " <method name='EnumerateTemporaryAuthorizations'>"
al@20905 786 " <arg type='(sa{sv})' name='subject' direction='in'/>"
al@20905 787 " <arg type='a(ss(sa{sv})tt)' name='temporary_authorizations' direction='out'/>"
al@20905 788 @@ -1035,6 +1041,57 @@ server_handle_authentication_agent_response (Server *server,
al@20905 789 error = NULL;
al@20905 790 if (!polkit_backend_authority_authentication_agent_response (server->authority,
al@20905 791 caller,
al@20905 792 + (uid_t)-1,
al@20905 793 + cookie,
al@20905 794 + identity,
al@20905 795 + &error))
al@20905 796 + {
al@20905 797 + g_dbus_method_invocation_return_gerror (invocation, error);
al@20905 798 + g_error_free (error);
al@20905 799 + goto out;
al@20905 800 + }
al@20905 801 +
al@20905 802 + g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
al@20905 803 +
al@20905 804 + out:
al@20905 805 + if (identity != NULL)
al@20905 806 + g_object_unref (identity);
al@20905 807 +}
al@20905 808 +
al@20905 809 +static void
al@20905 810 +server_handle_authentication_agent_response2 (Server *server,
al@20905 811 + GVariant *parameters,
al@20905 812 + PolkitSubject *caller,
al@20905 813 + GDBusMethodInvocation *invocation)
al@20905 814 +{
al@20905 815 + const gchar *cookie;
al@20905 816 + GVariant *identity_gvariant;
al@20905 817 + PolkitIdentity *identity;
al@20905 818 + GError *error;
al@20905 819 + guint32 uid;
al@20905 820 +
al@20905 821 + identity = NULL;
al@20905 822 +
al@20905 823 + g_variant_get (parameters,
al@20905 824 + "(u&s@(sa{sv}))",
al@20905 825 + &uid,
al@20905 826 + &cookie,
al@20905 827 + &identity_gvariant);
al@20905 828 +
al@20905 829 + error = NULL;
al@20905 830 + identity = polkit_identity_new_for_gvariant (identity_gvariant, &error);
al@20905 831 + if (identity == NULL)
al@20905 832 + {
al@20905 833 + g_prefix_error (&error, "Error getting identity: ");
al@20905 834 + g_dbus_method_invocation_return_gerror (invocation, error);
al@20905 835 + g_error_free (error);
al@20905 836 + goto out;
al@20905 837 + }
al@20905 838 +
al@20905 839 + error = NULL;
al@20905 840 + if (!polkit_backend_authority_authentication_agent_response (server->authority,
al@20905 841 + caller,
al@20905 842 + (uid_t)uid,
al@20905 843 cookie,
al@20905 844 identity,
al@20905 845 &error))
al@20905 846 @@ -1222,6 +1279,8 @@ server_handle_method_call (GDBusConnection *connection,
al@20905 847 server_handle_unregister_authentication_agent (server, parameters, caller, invocation);
al@20905 848 else if (g_strcmp0 (method_name, "AuthenticationAgentResponse") == 0)
al@20905 849 server_handle_authentication_agent_response (server, parameters, caller, invocation);
al@20905 850 + else if (g_strcmp0 (method_name, "AuthenticationAgentResponse2") == 0)
al@20905 851 + server_handle_authentication_agent_response2 (server, parameters, caller, invocation);
al@20905 852 else if (g_strcmp0 (method_name, "EnumerateTemporaryAuthorizations") == 0)
al@20905 853 server_handle_enumerate_temporary_authorizations (server, parameters, caller, invocation);
al@20905 854 else if (g_strcmp0 (method_name, "RevokeTemporaryAuthorizations") == 0)
al@20905 855 diff --git a/src/polkitbackend/polkitbackendauthority.h b/src/polkitbackend/polkitbackendauthority.h
al@20905 856 index f9f7385..88df82e 100644
al@20905 857 --- a/src/polkitbackend/polkitbackendauthority.h
al@20905 858 +++ b/src/polkitbackend/polkitbackendauthority.h
al@20905 859 @@ -147,6 +147,7 @@ struct _PolkitBackendAuthorityClass
al@20905 860
al@20905 861 gboolean (*authentication_agent_response) (PolkitBackendAuthority *authority,
al@20905 862 PolkitSubject *caller,
al@20905 863 + uid_t uid,
al@20905 864 const gchar *cookie,
al@20905 865 PolkitIdentity *identity,
al@20905 866 GError **error);
al@20905 867 @@ -249,6 +250,7 @@ gboolean polkit_backend_authority_unregister_authentication_agent (PolkitBackend
al@20905 868
al@20905 869 gboolean polkit_backend_authority_authentication_agent_response (PolkitBackendAuthority *authority,
al@20905 870 PolkitSubject *caller,
al@20905 871 + uid_t uid,
al@20905 872 const gchar *cookie,
al@20905 873 PolkitIdentity *identity,
al@20905 874 GError **error);
al@20905 875 diff --git a/src/polkitbackend/polkitbackendinteractiveauthority.c b/src/polkitbackend/polkitbackendinteractiveauthority.c
al@20905 876 index 15adc6a..96725f7 100644
al@20905 877 --- a/src/polkitbackend/polkitbackendinteractiveauthority.c
al@20905 878 +++ b/src/polkitbackend/polkitbackendinteractiveauthority.c
al@20905 879 @@ -108,8 +108,9 @@ static AuthenticationAgent *get_authentication_agent_for_subject (PolkitBackendI
al@20905 880 PolkitSubject *subject);
al@20905 881
al@20905 882
al@20905 883 -static AuthenticationSession *get_authentication_session_for_cookie (PolkitBackendInteractiveAuthority *authority,
al@20905 884 - const gchar *cookie);
al@20905 885 +static AuthenticationSession *get_authentication_session_for_uid_and_cookie (PolkitBackendInteractiveAuthority *authority,
al@20905 886 + uid_t uid,
al@20905 887 + const gchar *cookie);
al@20905 888
al@20905 889 static GList *get_authentication_sessions_initiated_by_system_bus_unique_name (PolkitBackendInteractiveAuthority *authority,
al@20905 890 const gchar *system_bus_unique_name);
al@20905 891 @@ -169,6 +170,7 @@ static gboolean polkit_backend_interactive_authority_unregister_authentication_a
al@20905 892
al@20905 893 static gboolean polkit_backend_interactive_authority_authentication_agent_response (PolkitBackendAuthority *authority,
al@20905 894 PolkitSubject *caller,
al@20905 895 + uid_t uid,
al@20905 896 const gchar *cookie,
al@20905 897 PolkitIdentity *identity,
al@20905 898 GError **error);
al@20905 899 @@ -440,6 +442,7 @@ struct AuthenticationAgent
al@20905 900 {
al@20905 901 volatile gint ref_count;
al@20905 902
al@20905 903 + uid_t creator_uid;
al@20905 904 PolkitSubject *scope;
al@20905 905 guint64 serial;
al@20905 906
al@20905 907 @@ -1603,6 +1606,7 @@ authentication_agent_unref (AuthenticationAgent *agent)
al@20905 908 static AuthenticationAgent *
al@20905 909 authentication_agent_new (guint64 serial,
al@20905 910 PolkitSubject *scope,
al@20905 911 + PolkitIdentity *creator,
al@20905 912 const gchar *unique_system_bus_name,
al@20905 913 const gchar *locale,
al@20905 914 const gchar *object_path,
al@20905 915 @@ -1611,6 +1615,10 @@ authentication_agent_new (guint64 serial,
al@20905 916 {
al@20905 917 AuthenticationAgent *agent;
al@20905 918 GDBusProxy *proxy;
al@20905 919 + PolkitUnixUser *creator_user;
al@20905 920 +
al@20905 921 + g_assert (POLKIT_IS_UNIX_USER (creator));
al@20905 922 + creator_user = POLKIT_UNIX_USER (creator);
al@20905 923
al@20905 924 if (!g_variant_is_object_path (object_path))
al@20905 925 {
al@20905 926 @@ -1638,6 +1646,7 @@ authentication_agent_new (guint64 serial,
al@20905 927 agent->ref_count = 1;
al@20905 928 agent->serial = serial;
al@20905 929 agent->scope = g_object_ref (scope);
al@20905 930 + agent->creator_uid = (uid_t)polkit_unix_user_get_uid (creator_user);
al@20905 931 agent->object_path = g_strdup (object_path);
al@20905 932 agent->unique_system_bus_name = g_strdup (unique_system_bus_name);
al@20905 933 agent->locale = g_strdup (locale);
al@20905 934 @@ -1736,8 +1745,9 @@ get_authentication_agent_for_subject (PolkitBackendInteractiveAuthority *authori
al@20905 935 }
al@20905 936
al@20905 937 static AuthenticationSession *
al@20905 938 -get_authentication_session_for_cookie (PolkitBackendInteractiveAuthority *authority,
al@20905 939 - const gchar *cookie)
al@20905 940 +get_authentication_session_for_uid_and_cookie (PolkitBackendInteractiveAuthority *authority,
al@20905 941 + uid_t uid,
al@20905 942 + const gchar *cookie)
al@20905 943 {
al@20905 944 PolkitBackendInteractiveAuthorityPrivate *priv;
al@20905 945 GHashTableIter hash_iter;
al@20905 946 @@ -1755,6 +1765,23 @@ get_authentication_session_for_cookie (PolkitBackendInteractiveAuthority *author
al@20905 947 {
al@20905 948 GList *l;
al@20905 949
al@20905 950 + /* We need to ensure that if somehow we have duplicate cookies
al@20905 951 + * due to wrapping, that the cookie used is matched to the user
al@20905 952 + * who called AuthenticationAgentResponse2. See
al@20905 953 + * http://lists.freedesktop.org/archives/polkit-devel/2015-June/000425.html
al@20905 954 + *
al@20905 955 + * Except if the legacy AuthenticationAgentResponse is invoked,
al@20905 956 + * we don't know the uid and hence use -1. Continue to support
al@20905 957 + * the old behavior for backwards compatibility, although everyone
al@20905 958 + * who is using our own setuid helper will automatically be updated
al@20905 959 + * to the new API.
al@20905 960 + */
al@20905 961 + if (uid != (uid_t)-1)
al@20905 962 + {
al@20905 963 + if (agent->creator_uid != uid)
al@20905 964 + continue;
al@20905 965 + }
al@20905 966 +
al@20905 967 for (l = agent->active_sessions; l != NULL; l = l->next)
al@20905 968 {
al@20905 969 AuthenticationSession *session = l->data;
al@20905 970 @@ -2544,6 +2571,7 @@ polkit_backend_interactive_authority_register_authentication_agent (PolkitBacken
al@20905 971 priv->agent_serial++;
al@20905 972 agent = authentication_agent_new (priv->agent_serial,
al@20905 973 subject,
al@20905 974 + user_of_caller,
al@20905 975 polkit_system_bus_name_get_name (POLKIT_SYSTEM_BUS_NAME (caller)),
al@20905 976 locale,
al@20905 977 object_path,
al@20905 978 @@ -2757,6 +2785,7 @@ polkit_backend_interactive_authority_unregister_authentication_agent (PolkitBack
al@20905 979 static gboolean
al@20905 980 polkit_backend_interactive_authority_authentication_agent_response (PolkitBackendAuthority *authority,
al@20905 981 PolkitSubject *caller,
al@20905 982 + uid_t uid,
al@20905 983 const gchar *cookie,
al@20905 984 PolkitIdentity *identity,
al@20905 985 GError **error)
al@20905 986 @@ -2799,7 +2828,7 @@ polkit_backend_interactive_authority_authentication_agent_response (PolkitBacken
al@20905 987 }
al@20905 988
al@20905 989 /* find the authentication session */
al@20905 990 - session = get_authentication_session_for_cookie (interactive_authority, cookie);
al@20905 991 + session = get_authentication_session_for_uid_and_cookie (interactive_authority, uid, cookie);
al@20905 992 if (session == NULL)
al@20905 993 {
al@20905 994 g_set_error (error,
al@20905 995 --
al@20905 996 cgit v0.10.2
al@20905 997
al@20905 998 --- ./configure.ac.orig
al@20905 999 +++ ./configure.ac
al@20905 1000 @@ -122,7 +122,7 @@
al@20905 1001 changequote([,])dnl
al@20905 1002 fi
al@20905 1003
al@20905 1004 -PKG_CHECK_MODULES(GLIB, [gio-2.0 >= 2.28.0])
al@20905 1005 +PKG_CHECK_MODULES(GLIB, [gmodule-2.0 gio-unix-2.0 gio-2.0 >= 2.30.0])
al@20905 1006 AC_SUBST(GLIB_CFLAGS)
al@20905 1007 AC_SUBST(GLIB_LIBS)
al@20905 1008