Submitted By: Douglas R. Reno Date: 2018-12-14 Initial Package Version: 0.115 Upstream Status: Applied Origin: Upstream/Self Description: This patch contains security fixes for polkit since version 0.115. This also fixes some debug text that was deprecated, and changes some errors to debug msgs. This fixes a vulnerability that has gotten national attention because it allows any UID over 4,000,000 to execute any command without authentication. diff -Naurp polkit-0.115.orig/src/polkit/polkitpermission.c polkit-0.115/src/polkit/polkitpermission.c --- polkit-0.115.orig/src/polkit/polkitpermission.c 2018-04-03 15:57:57.000000000 -0500 +++ polkit-0.115/src/polkit/polkitpermission.c 2018-12-13 13:00:43.554424180 -0600 @@ -137,10 +137,13 @@ polkit_permission_finalize (GObject *obj g_free (permission->tmp_authz_id); g_object_unref (permission->subject); - g_signal_handlers_disconnect_by_func (permission->authority, - on_authority_changed, - permission); - g_object_unref (permission->authority); + if (permission->authority != NULL) + { + g_signal_handlers_disconnect_by_func (permission->authority, + on_authority_changed, + permission); + g_object_unref (permission->authority); + } if (G_OBJECT_CLASS (polkit_permission_parent_class)->finalize != NULL) G_OBJECT_CLASS (polkit_permission_parent_class)->finalize (object); diff -Naurp polkit-0.115.orig/src/polkit/polkitunixgroup.c polkit-0.115/src/polkit/polkitunixgroup.c --- polkit-0.115.orig/src/polkit/polkitunixgroup.c 2017-09-04 14:52:53.000000000 -0500 +++ polkit-0.115/src/polkit/polkitunixgroup.c 2018-12-13 12:22:14.903159457 -0600 @@ -71,6 +71,7 @@ G_DEFINE_TYPE_WITH_CODE (PolkitUnixGroup static void polkit_unix_group_init (PolkitUnixGroup *unix_group) { + unix_group->gid = -1; /* -1 is not a valid GID under Linux */ } static void @@ -100,11 +101,14 @@ polkit_unix_group_set_property (GObject GParamSpec *pspec) { PolkitUnixGroup *unix_group = POLKIT_UNIX_GROUP (object); + gint val; switch (prop_id) { case PROP_GID: - unix_group->gid = g_value_get_int (value); + val = g_value_get_int (value); + g_return_if_fail (val != -1); + unix_group->gid = val; break; default: @@ -131,9 +135,9 @@ polkit_unix_group_class_init (PolkitUnix g_param_spec_int ("gid", "Group ID", "The UNIX group ID", - 0, + G_MININT, G_MAXINT, - 0, + -1, G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_NAME | @@ -166,7 +170,7 @@ polkit_unix_group_get_gid (PolkitUnixGro */ void polkit_unix_group_set_gid (PolkitUnixGroup *group, - gint gid) + gint gid) { g_return_if_fail (POLKIT_IS_UNIX_GROUP (group)); group->gid = gid; @@ -183,6 +187,8 @@ polkit_unix_group_set_gid (PolkitUnixGro PolkitIdentity * polkit_unix_group_new (gint gid) { + g_return_val_if_fail (gid != -1, NULL); + return POLKIT_IDENTITY (g_object_new (POLKIT_TYPE_UNIX_GROUP, "gid", gid, NULL)); diff -Naurp polkit-0.115.orig/src/polkit/polkitunixprocess.c polkit-0.115/src/polkit/polkitunixprocess.c --- polkit-0.115.orig/src/polkit/polkitunixprocess.c 2018-06-25 08:55:45.000000000 -0500 +++ polkit-0.115/src/polkit/polkitunixprocess.c 2018-12-13 12:58:33.019565824 -0600 @@ -159,9 +159,14 @@ polkit_unix_process_set_property (GObjec polkit_unix_process_set_pid (unix_process, g_value_get_int (value)); break; - case PROP_UID: - polkit_unix_process_set_uid (unix_process, g_value_get_int (value)); + case PROP_UID: { + gint val; + + val = g_value_get_int (value); + g_return_if_fail (val != -1); + polkit_unix_process_set_uid (unix_process, val); break; + } case PROP_START_TIME: polkit_unix_process_set_start_time (unix_process, g_value_get_uint64 (value)); @@ -239,7 +244,7 @@ polkit_unix_process_class_init (PolkitUn g_param_spec_int ("uid", "User ID", "The UNIX user ID", - -1, + G_MININT, G_MAXINT, -1, G_PARAM_CONSTRUCT | @@ -303,7 +308,6 @@ polkit_unix_process_set_uid (PolkitUnixP gint uid) { g_return_if_fail (POLKIT_IS_UNIX_PROCESS (process)); - g_return_if_fail (uid >= -1); process->uid = uid; } diff -Naurp polkit-0.115.orig/src/polkit/polkitunixuser.c polkit-0.115/src/polkit/polkitunixuser.c --- polkit-0.115.orig/src/polkit/polkitunixuser.c 2017-09-04 14:52:53.000000000 -0500 +++ polkit-0.115/src/polkit/polkitunixuser.c 2018-12-13 12:26:43.659067703 -0600 @@ -72,6 +72,7 @@ G_DEFINE_TYPE_WITH_CODE (PolkitUnixUser, static void polkit_unix_user_init (PolkitUnixUser *unix_user) { + unix_user->uid = -1; /* (uid_t) -1 is not a valid UID under Linux */ unix_user->name = NULL; } @@ -112,11 +113,14 @@ polkit_unix_user_set_property (GObject GParamSpec *pspec) { PolkitUnixUser *unix_user = POLKIT_UNIX_USER (object); + gint val; switch (prop_id) { case PROP_UID: - unix_user->uid = g_value_get_int (value); + val = g_value_get_int (value); + g_return_if_fail (val != -1); + unix_user->uid = val; break; default: @@ -144,9 +148,9 @@ polkit_unix_user_class_init (PolkitUnixU g_param_spec_int ("uid", "User ID", "The UNIX user ID", - 0, + G_MININT, G_MAXINT, - 0, + -1, G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_NAME | @@ -182,6 +186,7 @@ polkit_unix_user_set_uid (PolkitUnixUser gint uid) { g_return_if_fail (POLKIT_IS_UNIX_USER (user)); + g_return_if_fail (uid != -1); user->uid = uid; } @@ -196,6 +201,8 @@ polkit_unix_user_set_uid (PolkitUnixUser PolkitIdentity * polkit_unix_user_new (gint uid) { + g_return_val_if_fail (uid != -1, NULL); + return POLKIT_IDENTITY (g_object_new (POLKIT_TYPE_UNIX_USER, "uid", uid, NULL)); diff -Naurp polkit-0.115.orig/src/polkitagent/polkitagentlistener.c polkit-0.115/src/polkitagent/polkitagentlistener.c --- polkit-0.115.orig/src/polkitagent/polkitagentlistener.c 2018-04-03 15:57:57.000000000 -0500 +++ polkit-0.115/src/polkitagent/polkitagentlistener.c 2018-12-13 12:14:09.418533147 -0600 @@ -178,10 +178,10 @@ on_notify_authority_owner (GObject *o owner = polkit_authority_get_owner (server->authority); if (owner == NULL) { - g_printerr ("PolicyKit daemon disconnected from the bus.\n"); + g_debug ("PolicyKit daemon disconnected from the bus.\n"); if (server->is_registered) - g_printerr ("We are no longer a registered authentication agent.\n"); + g_debug ("We are no longer a registered authentication agent.\n"); server->is_registered = FALSE; } @@ -192,17 +192,17 @@ on_notify_authority_owner (GObject *o { GError *error; - g_printerr ("PolicyKit daemon reconnected to bus.\n"); - g_printerr ("Attempting to re-register as an authentication agent.\n"); + g_debug ("PolicyKit daemon reconnected to bus.\n"); + g_debug ("Attempting to re-register as an authentication agent.\n"); error = NULL; if (server_register (server, &error)) { - g_printerr ("We are now a registered authentication agent.\n"); + g_debug ("We are now a registered authentication agent.\n"); } else { - g_printerr ("Failed to register as an authentication agent: %s\n", error->message); + g_debug ("Failed to register as an authentication agent: %s\n", error->message); g_error_free (error); } } @@ -439,6 +439,7 @@ polkit_agent_listener_register_with_opti server->thread_initialization_error = NULL; g_thread_join (server->thread); server_free (server); + server = NULL; goto out; } } diff -Naurp polkit-0.115.orig/src/polkitbackend/polkitbackendinteractiveauthority.c polkit-0.115/src/polkitbackend/polkitbackendinteractiveauthority.c --- polkit-0.115.orig/src/polkitbackend/polkitbackendinteractiveauthority.c 2018-06-22 17:20:18.000000000 -0500 +++ polkit-0.115/src/polkitbackend/polkitbackendinteractiveauthority.c 2018-12-13 12:19:01.492266182 -0600 @@ -935,7 +935,7 @@ polkit_backend_interactive_authority_che } /* Not anyone is allowed to check that process XYZ is allowed to do ABC. - * We only allow this if, and only if, + * We allow this if, and only if, * * - processes may check for another process owned by the *same* user but not * if details are passed (otherwise you'd be able to spoof the dialog); @@ -947,7 +947,7 @@ polkit_backend_interactive_authority_che * * - if the action_id has the "org.freedesktop.policykit.owner" annotation * then any uid referenced by that annotation is also allowed to check - * to check anything and pass any details + * anything and pass any details */ if (!user_of_subject_matches || !polkit_identity_equal (user_of_caller, user_of_subject) diff -Naurp polkit-0.115.orig/src/polkitbackend/polkitbackendjsauthority.cpp polkit-0.115/src/polkitbackend/polkitbackendjsauthority.cpp --- polkit-0.115.orig/src/polkitbackend/polkitbackendjsauthority.cpp 2018-04-03 15:57:57.000000000 -0500 +++ polkit-0.115/src/polkitbackend/polkitbackendjsauthority.cpp 2018-12-13 12:11:38.194585334 -0600 @@ -1595,7 +1595,8 @@ utils_spawn_data_free (UtilsSpawnData *d (GSourceFunc) utils_child_watch_from_release_cb, source, (GDestroyNotify) g_source_destroy); - g_source_attach (source, data->main_context); + /* Attach source to the global default main context */ + g_source_attach (source, NULL); g_source_unref (source); data->child_pid = 0; } diff -Naurp polkit-0.115.orig/src/programs/pkttyagent.c polkit-0.115/src/programs/pkttyagent.c --- polkit-0.115.orig/src/programs/pkttyagent.c 2018-04-03 15:57:57.000000000 -0500 +++ polkit-0.115/src/programs/pkttyagent.c 2018-12-13 13:05:01.181202945 -0600 @@ -160,7 +160,8 @@ main (int argc, char *argv[]) authority = polkit_authority_get_sync (NULL /* GCancellable* */, &error); if (authority == NULL) { - g_printerr ("Error getting authority: %s (%s, %d)\n", + g_printerr ("Authorization not available. Check if polkit service is running or see debug message for more information.\n"); + g_debug ("Error getting authority: %s (%s, %d)\n", error->message, g_quark_to_string (error->domain), error->code); g_error_free (error); ret = 127; diff -Naurp polkit-0.115.orig/test/data/etc/group polkit-0.115/test/data/etc/group --- polkit-0.115.orig/test/data/etc/group 2017-09-04 14:52:54.000000000 -0500 +++ polkit-0.115/test/data/etc/group 2018-12-13 12:29:00.729037998 -0600 @@ -5,3 +5,4 @@ john:x:500: jane:x:501: sally:x:502: henry:x:503: +highuid2:x:4000000000: diff -Naurp polkit-0.115.orig/test/data/etc/passwd polkit-0.115/test/data/etc/passwd --- polkit-0.115.orig/test/data/etc/passwd 2017-09-04 14:52:54.000000000 -0500 +++ polkit-0.115/test/data/etc/passwd 2018-12-13 12:28:51.034039809 -0600 @@ -3,3 +3,5 @@ john:x:500:500:John Done:/home/john:/bin jane:x:501:501:Jane Smith:/home/jane:/bin/bash sally:x:502:502:Sally Derp:/home/sally:/bin/bash henry:x:503:503:Henry Herp:/home/henry:/bin/bash +highuid1:x:2147483648:2147483648:The first high uid:/home/highuid1:/sbin/nologin +highuid2:x:4000000000:4000000000:An example high uid:/home/example:/sbin/nologin diff -Naurp polkit-0.115.orig/test/data/etc/polkit-1/rules.d/10-testing.rules polkit-0.115/test/data/etc/polkit-1/rules.d/10-testing.rules --- polkit-0.115.orig/test/data/etc/polkit-1/rules.d/10-testing.rules 2017-09-04 14:52:54.000000000 -0500 +++ polkit-0.115/test/data/etc/polkit-1/rules.d/10-testing.rules 2018-12-13 13:09:41.535019708 -0600 @@ -53,6 +53,27 @@ polkit.addRule(function(action, subject) } }); +polkit.addRule(function(action, subject) { + if (action.id == "net.company.john_action") { + if (subject.user == "john") { + return polkit.Result.YES; + } else { + return polkit.Result.NO; + } + } +}); + +polkit.addRule(function(action,subject) { + if (action.id == "net.company.highuid2_action") { + if (subject.user == "highuid2") { + return polkit.Result.YES; + } else { + return polkit.Result.NO; + } + } +}); + + // --------------------------------------------------------------------- // variables diff -Naurp polkit-0.115.orig/test/polkitbackend/test-polkitbackendjsauthority.c polkit-0.115/test/polkitbackend/test-polkitbackendjsauthority.c --- polkit-0.115.orig/test/polkitbackend/test-polkitbackendjsauthority.c 2018-04-03 15:57:57.000000000 -0500 +++ polkit-0.115/test/polkitbackend/test-polkitbackendjsauthority.c 2018-12-13 12:41:19.054977178 -0600 @@ -330,6 +330,78 @@ static const RulesTestCase rules_test_ca NULL, POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED, }, + + { + /* highuid1 is not a member of group 'users', see test/data/etc/group */ + "group_membership_with_non_member(highuid22)", + "net.company.group.only_group_users", + "unix-user:highuid2", + NULL, + POLKIT_IMPLICIT_AUTHORIZATION_NOT_AUTHORIZED, + }, + + { + /* highuid2 is not a member of group 'users', see test/data/etc/group */ + "group_membership_with_non_member(highuid21)", + "net.company.group.only_group_users", + "unix-user:highuid2", + NULL, + POLKIT_IMPLICIT_AUTHORIZATION_NOT_AUTHORIZED, + }, + + { + /* highuid1 is not a member of group 'users', see test/data/etc/group */ + "group_membership_with_non_member(highuid24)", + "net.company.group.only_group_users", + "unix-user:2147483648", + NULL, + POLKIT_IMPLICIT_AUTHORIZATION_NOT_AUTHORIZED, + }, + + { + /* highuid2 is not a member of group 'users', see test/data/etc/group */ + "group_membership_with_non_member(highuid23)", + "net.company.group.only_group_users", + "unix-user:4000000000", + NULL, + POLKIT_IMPLICIT_AUTHORIZATION_NOT_AUTHORIZED, + }, + + { + /* john is authorized to do this, see 10-testing.rules */ + "john.action", + "net.company.john_action", + "unix-user:john", + NULL, + POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED, + }, + + { + /* ONLY john is authorized to do this, see 10-testing.rules */ + "jane_action", + "net.company.john_action", + "unix-user:jane", + NULL, + POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED, + }, + + { + /* highuid2 is authorized to do this, see 10-testing.rules */ + "highuid2_action", + "net.company.highuid2_action", + "unix-user:highuid2", + NULL, + POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED, + }, + + { + /* ONLY highuid2 is authorized to do this, see 10-testing.rules */ + "highuid1_action", + "net.company.highuid2_action", + "unix-user:highuid1", + NULL, + POLKIT_IMPLICIT_AUTHORIZATION_NOT_AUTHORIZED + }, }; /* ---------------------------------------------------------------------------------------------------- */