commit
fd5065f994
@ -0,0 +1 @@
|
|||||||
|
SOURCES/polkit-0.115.tar.gz
|
@ -0,0 +1 @@
|
|||||||
|
208b7e44fcf0f515d067d37307af9ea1419eb305 SOURCES/polkit-0.115.tar.gz
|
@ -0,0 +1,291 @@
|
|||||||
|
diff --git a/src/polkit/polkitunixgroup.c b/src/polkit/polkitunixgroup.c
|
||||||
|
index c57a1aaacbb13c4e4297dd812cf5904f2f427b03..309f68918895e0f8b547f8c06f89c6fb1326fe20 100644
|
||||||
|
--- a/src/polkit/polkitunixgroup.c
|
||||||
|
+++ b/src/polkit/polkitunixgroup.c
|
||||||
|
@@ -71,6 +71,7 @@ G_DEFINE_TYPE_WITH_CODE (PolkitUnixGroup, polkit_unix_group, G_TYPE_OBJECT,
|
||||||
|
static void
|
||||||
|
polkit_unix_group_init (PolkitUnixGroup *unix_group)
|
||||||
|
{
|
||||||
|
+ unix_group->gid = -1; /* (git_t) -1 is not a valid GID under Linux */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
@@ -100,11 +101,14 @@ polkit_unix_group_set_property (GObject *object,
|
||||||
|
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 (PolkitUnixGroupClass *klass)
|
||||||
|
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,9 +170,10 @@ polkit_unix_group_get_gid (PolkitUnixGroup *group)
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
polkit_unix_group_set_gid (PolkitUnixGroup *group,
|
||||||
|
- gint gid)
|
||||||
|
+ gint gid)
|
||||||
|
{
|
||||||
|
g_return_if_fail (POLKIT_IS_UNIX_GROUP (group));
|
||||||
|
+ g_return_if_fail (gid != -1);
|
||||||
|
group->gid = gid;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -183,6 +188,8 @@ polkit_unix_group_set_gid (PolkitUnixGroup *group,
|
||||||
|
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 --git a/src/polkit/polkitunixprocess.c b/src/polkit/polkitunixprocess.c
|
||||||
|
index 972b7776825d5ccf677ed12ed620fc0c52352547..b02b25894ad120d88ea21d4c96ac8dca1821fcf2 100644
|
||||||
|
--- a/src/polkit/polkitunixprocess.c
|
||||||
|
+++ b/src/polkit/polkitunixprocess.c
|
||||||
|
@@ -159,9 +159,14 @@ polkit_unix_process_set_property (GObject *object,
|
||||||
|
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 (PolkitUnixProcessClass *klass)
|
||||||
|
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 (PolkitUnixProcess *process,
|
||||||
|
gint uid)
|
||||||
|
{
|
||||||
|
g_return_if_fail (POLKIT_IS_UNIX_PROCESS (process));
|
||||||
|
- g_return_if_fail (uid >= -1);
|
||||||
|
process->uid = uid;
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/src/polkit/polkitunixuser.c b/src/polkit/polkitunixuser.c
|
||||||
|
index 8bfd3a1fb05ddb56adebd097569a9977b7b922f3..234a6976c573ac65200ee08228cd50111f0c769b 100644
|
||||||
|
--- a/src/polkit/polkitunixuser.c
|
||||||
|
+++ b/src/polkit/polkitunixuser.c
|
||||||
|
@@ -72,6 +72,7 @@ G_DEFINE_TYPE_WITH_CODE (PolkitUnixUser, polkit_unix_user, G_TYPE_OBJECT,
|
||||||
|
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 *object,
|
||||||
|
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 (PolkitUnixUserClass *klass)
|
||||||
|
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 *user,
|
||||||
|
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 *user,
|
||||||
|
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 --git a/test/data/etc/group b/test/data/etc/group
|
||||||
|
index 12ef328b21b346ee3828ce3aaf15cca83858bd1d..b9acab97211fdf7db521dc0939b2dcfc2c9e350b 100644
|
||||||
|
--- a/test/data/etc/group
|
||||||
|
+++ b/test/data/etc/group
|
||||||
|
@@ -5,3 +5,4 @@ john:x:500:
|
||||||
|
jane:x:501:
|
||||||
|
sally:x:502:
|
||||||
|
henry:x:503:
|
||||||
|
+highuid2:x:4000000000:
|
||||||
|
diff --git a/test/data/etc/passwd b/test/data/etc/passwd
|
||||||
|
index 8544febcd8b1720e5577dfb3f0672a6fef29e701..5cf14a5620259f79806192ca935fee84a29ac96d 100644
|
||||||
|
--- a/test/data/etc/passwd
|
||||||
|
+++ b/test/data/etc/passwd
|
||||||
|
@@ -3,3 +3,5 @@ john:x:500:500:John Done:/home/john:/bin/bash
|
||||||
|
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 --git a/test/data/etc/polkit-1/rules.d/10-testing.rules b/test/data/etc/polkit-1/rules.d/10-testing.rules
|
||||||
|
index 446e62291b7fe4c5bacdceb1045350af1a9dc245..98bf062a08cb11fddb7df95d0bcdec1b1ac3587d 100644
|
||||||
|
--- a/test/data/etc/polkit-1/rules.d/10-testing.rules
|
||||||
|
+++ b/test/data/etc/polkit-1/rules.d/10-testing.rules
|
||||||
|
@@ -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 --git a/test/polkitbackend/test-polkitbackendjsauthority.c b/test/polkitbackend/test-polkitbackendjsauthority.c
|
||||||
|
index b484a26600dbde074ee7d8491f88624fdc83c39c..71aad23e2f5d1a7b15e138f23e6581a31498bad6 100644
|
||||||
|
--- a/test/polkitbackend/test-polkitbackendjsauthority.c
|
||||||
|
+++ b/test/polkitbackend/test-polkitbackendjsauthority.c
|
||||||
|
@@ -330,6 +330,78 @@ static const RulesTestCase rules_test_cases[] = {
|
||||||
|
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_NOT_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,
|
||||||
|
+ },
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------------- */
|
||||||
|
|
@ -0,0 +1,185 @@
|
|||||||
|
From 6cc6aafee135ba44ea748250d7d29b562ca190e3 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Colin Walters <walters@verbum.org>
|
||||||
|
Date: Fri, 4 Jan 2019 14:24:48 -0500
|
||||||
|
Subject: [PATCH] backend: Compare PolkitUnixProcess uids for temporary
|
||||||
|
authorizations
|
||||||
|
|
||||||
|
It turns out that the combination of `(pid, start time)` is not
|
||||||
|
enough to be unique. For temporary authorizations, we can avoid
|
||||||
|
separate users racing on pid reuse by simply comparing the uid.
|
||||||
|
|
||||||
|
https://bugs.chromium.org/p/project-zero/issues/detail?id=1692
|
||||||
|
|
||||||
|
And the above original email report is included in full in a new comment.
|
||||||
|
|
||||||
|
Reported-by: Jann Horn <jannh@google.com>
|
||||||
|
|
||||||
|
Closes: https://gitlab.freedesktop.org/polkit/polkit/issues/75
|
||||||
|
---
|
||||||
|
src/polkit/polkitsubject.c | 2 +
|
||||||
|
src/polkit/polkitunixprocess.c | 71 ++++++++++++++++++-
|
||||||
|
.../polkitbackendinteractiveauthority.c | 39 +++++++++-
|
||||||
|
3 files changed, 110 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/polkit/polkitsubject.c b/src/polkit/polkitsubject.c
|
||||||
|
index d4c1182..ccabd0a 100644
|
||||||
|
--- a/src/polkit/polkitsubject.c
|
||||||
|
+++ b/src/polkit/polkitsubject.c
|
||||||
|
@@ -99,6 +99,8 @@ polkit_subject_hash (PolkitSubject *subject)
|
||||||
|
* @b: A #PolkitSubject.
|
||||||
|
*
|
||||||
|
* Checks if @a and @b are equal, ie. represent the same subject.
|
||||||
|
+ * However, avoid calling polkit_subject_equal() to compare two processes;
|
||||||
|
+ * for more information see the `PolkitUnixProcess` documentation.
|
||||||
|
*
|
||||||
|
* This function can be used in e.g. g_hash_table_new().
|
||||||
|
*
|
||||||
|
diff --git a/src/polkit/polkitunixprocess.c b/src/polkit/polkitunixprocess.c
|
||||||
|
index b02b258..78d7251 100644
|
||||||
|
--- a/src/polkit/polkitunixprocess.c
|
||||||
|
+++ b/src/polkit/polkitunixprocess.c
|
||||||
|
@@ -51,7 +51,10 @@
|
||||||
|
* @title: PolkitUnixProcess
|
||||||
|
* @short_description: Unix processs
|
||||||
|
*
|
||||||
|
- * An object for representing a UNIX process.
|
||||||
|
+ * An object for representing a UNIX process. NOTE: This object as
|
||||||
|
+ * designed is now known broken; a mechanism to exploit a delay in
|
||||||
|
+ * start time in the Linux kernel was identified. Avoid
|
||||||
|
+ * calling polkit_subject_equal() to compare two processes.
|
||||||
|
*
|
||||||
|
* To uniquely identify processes, both the process id and the start
|
||||||
|
* time of the process (a monotonic increasing value representing the
|
||||||
|
@@ -66,6 +69,72 @@
|
||||||
|
* polkit_unix_process_new_for_owner() with trusted data.
|
||||||
|
*/
|
||||||
|
|
||||||
|
+/* See https://gitlab.freedesktop.org/polkit/polkit/issues/75
|
||||||
|
+
|
||||||
|
+ But quoting the original email in full here to ensure it's preserved:
|
||||||
|
+
|
||||||
|
+ From: Jann Horn <jannh@google.com>
|
||||||
|
+ Subject: [SECURITY] polkit: temporary auth hijacking via PID reuse and non-atomic fork
|
||||||
|
+ Date: Wednesday, October 10, 2018 5:34 PM
|
||||||
|
+
|
||||||
|
+When a (non-root) user attempts to e.g. control systemd units in the system
|
||||||
|
+instance from an active session over DBus, the access is gated by a polkit
|
||||||
|
+policy that requires "auth_admin_keep" auth. This results in an auth prompt
|
||||||
|
+being shown to the user, asking the user to confirm the action by entering the
|
||||||
|
+password of an administrator account.
|
||||||
|
+
|
||||||
|
+After the action has been confirmed, the auth decision for "auth_admin_keep" is
|
||||||
|
+cached for up to five minutes. Subject to some restrictions, similar actions can
|
||||||
|
+then be performed in this timespan without requiring re-auth:
|
||||||
|
+
|
||||||
|
+ - The PID of the DBus client requesting the new action must match the PID of
|
||||||
|
+ the DBus client requesting the old action (based on SO_PEERCRED information
|
||||||
|
+ forwarded by the DBus daemon).
|
||||||
|
+ - The "start time" of the client's PID (as seen in /proc/$pid/stat, field 22)
|
||||||
|
+ must not have changed. The granularity of this timestamp is in the
|
||||||
|
+ millisecond range.
|
||||||
|
+ - polkit polls every two seconds whether a process with the expected start time
|
||||||
|
+ still exists. If not, the temporary auth entry is purged.
|
||||||
|
+
|
||||||
|
+Without the start time check, this would obviously be buggy because an attacker
|
||||||
|
+could simply wait for the legitimate client to disappear, then create a new
|
||||||
|
+client with the same PID.
|
||||||
|
+
|
||||||
|
+Unfortunately, the start time check is bypassable because fork() is not atomic.
|
||||||
|
+Looking at the source code of copy_process() in the kernel:
|
||||||
|
+
|
||||||
|
+ p->start_time = ktime_get_ns();
|
||||||
|
+ p->real_start_time = ktime_get_boot_ns();
|
||||||
|
+ [...]
|
||||||
|
+ retval = copy_thread_tls(clone_flags, stack_start, stack_size, p, tls);
|
||||||
|
+ if (retval)
|
||||||
|
+ goto bad_fork_cleanup_io;
|
||||||
|
+
|
||||||
|
+ if (pid != &init_struct_pid) {
|
||||||
|
+ pid = alloc_pid(p->nsproxy->pid_ns_for_children);
|
||||||
|
+ if (IS_ERR(pid)) {
|
||||||
|
+ retval = PTR_ERR(pid);
|
||||||
|
+ goto bad_fork_cleanup_thread;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+The ktime_get_boot_ns() call is where the "start time" of the process is
|
||||||
|
+recorded. The alloc_pid() call is where a free PID is allocated. In between
|
||||||
|
+these, some time passes; and because the copy_thread_tls() call between them can
|
||||||
|
+access userspace memory when sys_clone() is invoked through the 32-bit syscall
|
||||||
|
+entry point, an attacker can even stall the kernel arbitrarily long at this
|
||||||
|
+point (by supplying a pointer into userspace memory that is associated with a
|
||||||
|
+userfaultfd or is backed by a custom FUSE filesystem).
|
||||||
|
+
|
||||||
|
+This means that an attacker can immediately call sys_clone() when the victim
|
||||||
|
+process is created, often resulting in a process that has the exact same start
|
||||||
|
+time reported in procfs; and then the attacker can delay the alloc_pid() call
|
||||||
|
+until after the victim process has died and the PID assignment has cycled
|
||||||
|
+around. This results in an attacker process that polkit can't distinguish from
|
||||||
|
+the victim process.
|
||||||
|
+*/
|
||||||
|
+
|
||||||
|
+
|
||||||
|
/**
|
||||||
|
* PolkitUnixProcess:
|
||||||
|
*
|
||||||
|
diff --git a/src/polkitbackend/polkitbackendinteractiveauthority.c b/src/polkitbackend/polkitbackendinteractiveauthority.c
|
||||||
|
index a1630b9..80e8141 100644
|
||||||
|
--- a/src/polkitbackend/polkitbackendinteractiveauthority.c
|
||||||
|
+++ b/src/polkitbackend/polkitbackendinteractiveauthority.c
|
||||||
|
@@ -3031,6 +3031,43 @@ temporary_authorization_store_free (TemporaryAuthorizationStore *store)
|
||||||
|
g_free (store);
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* See the comment at the top of polkitunixprocess.c */
|
||||||
|
+static gboolean
|
||||||
|
+subject_equal_for_authz (PolkitSubject *a,
|
||||||
|
+ PolkitSubject *b)
|
||||||
|
+{
|
||||||
|
+ if (!polkit_subject_equal (a, b))
|
||||||
|
+ return FALSE;
|
||||||
|
+
|
||||||
|
+ /* Now special case unix processes, as we want to protect against
|
||||||
|
+ * pid reuse by including the UID.
|
||||||
|
+ */
|
||||||
|
+ if (POLKIT_IS_UNIX_PROCESS (a) && POLKIT_IS_UNIX_PROCESS (b)) {
|
||||||
|
+ PolkitUnixProcess *ap = (PolkitUnixProcess*)a;
|
||||||
|
+ int uid_a = polkit_unix_process_get_uid ((PolkitUnixProcess*)a);
|
||||||
|
+ PolkitUnixProcess *bp = (PolkitUnixProcess*)b;
|
||||||
|
+ int uid_b = polkit_unix_process_get_uid ((PolkitUnixProcess*)b);
|
||||||
|
+
|
||||||
|
+ if (uid_a != -1 && uid_b != -1)
|
||||||
|
+ {
|
||||||
|
+ if (uid_a == uid_b)
|
||||||
|
+ {
|
||||||
|
+ return TRUE;
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ g_printerr ("denying slowfork; pid %d uid %d != %d!\n",
|
||||||
|
+ polkit_unix_process_get_pid (ap),
|
||||||
|
+ uid_a, uid_b);
|
||||||
|
+ return FALSE;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ /* Fall through; one of the uids is unset so we can't reliably compare */
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return TRUE;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static gboolean
|
||||||
|
temporary_authorization_store_has_authorization (TemporaryAuthorizationStore *store,
|
||||||
|
PolkitSubject *subject,
|
||||||
|
@@ -3073,7 +3110,7 @@ temporary_authorization_store_has_authorization (TemporaryAuthorizationStore *st
|
||||||
|
TemporaryAuthorization *authorization = l->data;
|
||||||
|
|
||||||
|
if (strcmp (action_id, authorization->action_id) == 0 &&
|
||||||
|
- polkit_subject_equal (subject_to_use, authorization->subject))
|
||||||
|
+ subject_equal_for_authz (subject_to_use, authorization->subject))
|
||||||
|
{
|
||||||
|
ret = TRUE;
|
||||||
|
if (out_tmp_authz_id != NULL)
|
||||||
|
--
|
||||||
|
2.19.2
|
||||||
|
|
@ -0,0 +1,13 @@
|
|||||||
|
--- a/src/polkit/polkitsystembusname.c
|
||||||
|
+++ b/src/polkit/polkitsystembusname.c
|
||||||
|
@@ -435,6 +435,9 @@ polkit_system_bus_name_get_creds_sync (PolkitSystemBusName *system_bus
|
||||||
|
while (!((data.retrieved_uid && data.retrieved_pid) || data.caught_error))
|
||||||
|
g_main_context_iteration (tmp_context, TRUE);
|
||||||
|
|
||||||
|
+ if (data.caught_error)
|
||||||
|
+ goto out;
|
||||||
|
+
|
||||||
|
if (out_uid)
|
||||||
|
*out_uid = data.uid;
|
||||||
|
if (out_pid)
|
||||||
|
|
@ -0,0 +1,69 @@
|
|||||||
|
diff --git a/src/programs/pkcheck.c b/src/programs/pkcheck.c
|
||||||
|
index f1bb4e1..aff4f60 100644
|
||||||
|
--- a/src/programs/pkcheck.c
|
||||||
|
+++ b/src/programs/pkcheck.c
|
||||||
|
@@ -363,6 +363,12 @@ main (int argc, char *argv[])
|
||||||
|
local_agent_handle = NULL;
|
||||||
|
ret = 126;
|
||||||
|
|
||||||
|
+ if (argc < 1)
|
||||||
|
+ {
|
||||||
|
+ help();
|
||||||
|
+ exit(1);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
/* Disable remote file access from GIO. */
|
||||||
|
setenv ("GIO_USE_VFS", "local", 1);
|
||||||
|
|
||||||
|
diff --git a/src/programs/pkexec.c b/src/programs/pkexec.c
|
||||||
|
index 7698c5c..d84dc57 100644
|
||||||
|
--- a/src/programs/pkexec.c
|
||||||
|
+++ b/src/programs/pkexec.c
|
||||||
|
@@ -488,6 +488,17 @@ main (int argc, char *argv[])
|
||||||
|
pid_t pid_of_caller;
|
||||||
|
gpointer local_agent_handle;
|
||||||
|
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * If 'pkexec' is called wrong, just show help and bail out.
|
||||||
|
+ */
|
||||||
|
+ if (argc<1)
|
||||||
|
+ {
|
||||||
|
+ clearenv();
|
||||||
|
+ usage(argc, argv);
|
||||||
|
+ exit(1);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
ret = 127;
|
||||||
|
authority = NULL;
|
||||||
|
subject = NULL;
|
||||||
|
@@ -614,10 +625,10 @@ main (int argc, char *argv[])
|
||||||
|
|
||||||
|
path = g_strdup (pwstruct.pw_shell);
|
||||||
|
if (!path)
|
||||||
|
- {
|
||||||
|
+ {
|
||||||
|
g_printerr ("No shell configured or error retrieving pw_shell\n");
|
||||||
|
goto out;
|
||||||
|
- }
|
||||||
|
+ }
|
||||||
|
/* If you change this, be sure to change the if (!command_line)
|
||||||
|
case below too */
|
||||||
|
command_line = g_strdup (path);
|
||||||
|
@@ -636,7 +647,15 @@ main (int argc, char *argv[])
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
g_free (path);
|
||||||
|
- argv[n] = path = s;
|
||||||
|
+ path = s;
|
||||||
|
+
|
||||||
|
+ /* argc<2 and pkexec runs just shell, argv is guaranteed to be null-terminated.
|
||||||
|
+ * /-less shell shouldn't happen, but let's be defensive and don't write to null-termination
|
||||||
|
+ */
|
||||||
|
+ if (argv[n] != NULL)
|
||||||
|
+ {
|
||||||
|
+ argv[n] = path;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
if (access (path, F_OK) != 0)
|
||||||
|
{
|
@ -0,0 +1,71 @@
|
|||||||
|
diff --git a/src/polkit/polkitsystembusname.c b/src/polkit/polkitsystembusname.c
|
||||||
|
index 8ed1363..2fbf5f1 100644
|
||||||
|
--- a/src/polkit/polkitsystembusname.c
|
||||||
|
+++ b/src/polkit/polkitsystembusname.c
|
||||||
|
@@ -62,6 +62,10 @@ enum
|
||||||
|
PROP_NAME,
|
||||||
|
};
|
||||||
|
|
||||||
|
+
|
||||||
|
+guint8 dbus_call_respond_fails; // has to be global because of callback
|
||||||
|
+
|
||||||
|
+
|
||||||
|
static void subject_iface_init (PolkitSubjectIface *subject_iface);
|
||||||
|
|
||||||
|
G_DEFINE_TYPE_WITH_CODE (PolkitSystemBusName, polkit_system_bus_name, G_TYPE_OBJECT,
|
||||||
|
@@ -364,6 +368,7 @@ on_retrieved_unix_uid_pid (GObject *src,
|
||||||
|
if (!v)
|
||||||
|
{
|
||||||
|
data->caught_error = TRUE;
|
||||||
|
+ dbus_call_respond_fails += 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
@@ -405,6 +410,8 @@ polkit_system_bus_name_get_creds_sync (PolkitSystemBusName *system_bus
|
||||||
|
tmp_context = g_main_context_new ();
|
||||||
|
g_main_context_push_thread_default (tmp_context);
|
||||||
|
|
||||||
|
+ dbus_call_respond_fails = 0;
|
||||||
|
+
|
||||||
|
/* Do two async calls as it's basically as fast as one sync call.
|
||||||
|
*/
|
||||||
|
g_dbus_connection_call (connection,
|
||||||
|
@@ -432,11 +439,34 @@ polkit_system_bus_name_get_creds_sync (PolkitSystemBusName *system_bus
|
||||||
|
on_retrieved_unix_uid_pid,
|
||||||
|
&data);
|
||||||
|
|
||||||
|
- while (!((data.retrieved_uid && data.retrieved_pid) || data.caught_error))
|
||||||
|
- g_main_context_iteration (tmp_context, TRUE);
|
||||||
|
+ while (TRUE)
|
||||||
|
+ {
|
||||||
|
+ /* If one dbus call returns error, we must wait until the other call
|
||||||
|
+ * calls _call_finish(), otherwise fd leak is possible.
|
||||||
|
+ * Resolves: GHSL-2021-077
|
||||||
|
+ */
|
||||||
|
|
||||||
|
- if (data.caught_error)
|
||||||
|
- goto out;
|
||||||
|
+ if ( (dbus_call_respond_fails > 1) )
|
||||||
|
+ {
|
||||||
|
+ // we got two faults, we can leave
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if ((data.caught_error && (data.retrieved_pid || data.retrieved_uid)))
|
||||||
|
+ {
|
||||||
|
+ // we got one fault and the other call finally finished, we can leave
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if ( !(data.retrieved_uid && data.retrieved_pid) )
|
||||||
|
+ {
|
||||||
|
+ g_main_context_iteration (tmp_context, TRUE);
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
|
||||||
|
if (out_uid)
|
||||||
|
*out_uid = data.uid;
|
@ -0,0 +1,20 @@
|
|||||||
|
diff -up ./src/polkit/polkitunixprocess.c.ori ./src/polkit/polkitunixprocess.c
|
||||||
|
--- ./src/polkit/polkitunixprocess.c.ori 2019-02-06 16:47:23.460666237 +0100
|
||||||
|
+++ ./src/polkit/polkitunixprocess.c 2019-02-06 16:47:43.846573792 +0100
|
||||||
|
@@ -211,14 +211,9 @@ polkit_unix_process_set_property (GObjec
|
||||||
|
polkit_unix_process_set_pid (unix_process, g_value_get_int (value));
|
||||||
|
break;
|
||||||
|
|
||||||
|
- 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);
|
||||||
|
+ case PROP_UID:
|
||||||
|
+ polkit_unix_process_set_uid (unix_process, g_value_get_int (value));
|
||||||
|
break;
|
||||||
|
- }
|
||||||
|
|
||||||
|
case PROP_START_TIME:
|
||||||
|
polkit_unix_process_set_start_time (unix_process, g_value_get_uint64 (value));
|
@ -0,0 +1,60 @@
|
|||||||
|
From 0ce0a7b3298d7b0fd5ce8c6775bcef9b0caf1bdb Mon Sep 17 00:00:00 2001
|
||||||
|
From: David Herrmann <dh.herrmann@gmail.com>
|
||||||
|
Date: Wed, 4 Jul 2018 13:51:24 +0200
|
||||||
|
Subject: [PATCH] polkitagent: suppress disconnect messages
|
||||||
|
|
||||||
|
The polkitagent may be used by pkexec and friends. These might very
|
||||||
|
well survive until very late during system shutdown. Hence, a
|
||||||
|
disconnect of polkitd during runtime might be expected [1].
|
||||||
|
|
||||||
|
This patch silences the disconnect/reconnect messages and turns them
|
||||||
|
into debug messages. This only affects the polkit-agent, it does not
|
||||||
|
affect the polkit-daemon implementation.
|
||||||
|
|
||||||
|
[1] https://bugzilla.redhat.com/show_bug.cgi?id=1249627
|
||||||
|
---
|
||||||
|
src/polkitagent/polkitagentlistener.c | 12 ++++++------
|
||||||
|
1 file changed, 6 insertions(+), 6 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/polkitagent/polkitagentlistener.c b/src/polkitagent/polkitagentlistener.c
|
||||||
|
index debd1bb..1c8b666 100644
|
||||||
|
--- a/src/polkitagent/polkitagentlistener.c
|
||||||
|
+++ b/src/polkitagent/polkitagentlistener.c
|
||||||
|
@@ -178,10 +178,10 @@ on_notify_authority_owner (GObject *object,
|
||||||
|
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 *object,
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.18.0
|
||||||
|
|
@ -0,0 +1,19 @@
|
|||||||
|
commit 28e3a6653d8c3777b07e0128a0d97d46e586e311
|
||||||
|
Author: Jan Rybar <jrybar@redhat.com>
|
||||||
|
Date: Tue Oct 8 13:28:18 2019 +0000
|
||||||
|
|
||||||
|
jsauthority: Fix two minor memory leaks
|
||||||
|
|
||||||
|
diff --git a/src/polkitbackend/polkitbackendjsauthority.cpp b/src/polkitbackend/polkitbackendjsauthority.cpp
|
||||||
|
index 9b752d1..e97b8aa 100644
|
||||||
|
--- a/src/polkitbackend/polkitbackendjsauthority.cpp
|
||||||
|
+++ b/src/polkitbackend/polkitbackendjsauthority.cpp
|
||||||
|
@@ -567,6 +567,8 @@ polkit_backend_js_authority_finalize (GObject *object)
|
||||||
|
g_strfreev (authority->priv->rules_dirs);
|
||||||
|
|
||||||
|
delete authority->priv->ac;
|
||||||
|
+ delete authority->priv->js_global;
|
||||||
|
+ delete authority->priv->js_polkit;
|
||||||
|
|
||||||
|
JS_DestroyContext (authority->priv->cx);
|
||||||
|
/* JS_ShutDown (); */
|
@ -0,0 +1,148 @@
|
|||||||
|
diff --git a/configure.ac b/configure.ac
|
||||||
|
index 5c37e481147466fd5a3a0a6b814f20fd2fe6bce8..5cedb4eca980f050fb5855ab577e93100adf8fec 100644
|
||||||
|
--- a/configure.ac
|
||||||
|
+++ b/configure.ac
|
||||||
|
@@ -79,7 +79,7 @@ PKG_CHECK_MODULES(GLIB, [gmodule-2.0 gio-unix-2.0 >= 2.30.0])
|
||||||
|
AC_SUBST(GLIB_CFLAGS)
|
||||||
|
AC_SUBST(GLIB_LIBS)
|
||||||
|
|
||||||
|
-PKG_CHECK_MODULES(LIBJS, [mozjs-52])
|
||||||
|
+PKG_CHECK_MODULES(LIBJS, [mozjs-60])
|
||||||
|
|
||||||
|
AC_SUBST(LIBJS_CFLAGS)
|
||||||
|
AC_SUBST(LIBJS_CXXFLAGS)
|
||||||
|
diff --git a/src/polkitbackend/polkitbackendjsauthority.cpp b/src/polkitbackend/polkitbackendjsauthority.cpp
|
||||||
|
index 76027149d4dfdc54064be48a3aeafeec8326a67b..984a0f0e579d51c09117f4e495b0c3fdc46fe61b 100644
|
||||||
|
--- a/src/polkitbackend/polkitbackendjsauthority.cpp
|
||||||
|
+++ b/src/polkitbackend/polkitbackendjsauthority.cpp
|
||||||
|
@@ -150,18 +150,17 @@ G_DEFINE_TYPE (PolkitBackendJsAuthority, polkit_backend_js_authority, POLKIT_BAC
|
||||||
|
/* ---------------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
static const struct JSClassOps js_global_class_ops = {
|
||||||
|
- NULL,
|
||||||
|
- NULL,
|
||||||
|
- NULL,
|
||||||
|
- NULL,
|
||||||
|
- NULL,
|
||||||
|
- NULL,
|
||||||
|
- NULL,
|
||||||
|
- NULL,
|
||||||
|
- NULL,
|
||||||
|
- NULL,
|
||||||
|
- NULL,
|
||||||
|
- NULL
|
||||||
|
+ nullptr, // addProperty
|
||||||
|
+ nullptr, // deleteProperty
|
||||||
|
+ nullptr, // enumerate
|
||||||
|
+ nullptr, // newEnumerate
|
||||||
|
+ nullptr, // resolve
|
||||||
|
+ nullptr, // mayResolve
|
||||||
|
+ nullptr, // finalize
|
||||||
|
+ nullptr, // call
|
||||||
|
+ nullptr, // hasInstance
|
||||||
|
+ nullptr, // construct
|
||||||
|
+ JS_GlobalObjectTraceHook
|
||||||
|
};
|
||||||
|
|
||||||
|
static JSClass js_global_class = {
|
||||||
|
@@ -172,18 +171,17 @@ static JSClass js_global_class = {
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------------- */
|
||||||
|
static const struct JSClassOps js_polkit_class_ops = {
|
||||||
|
- NULL,
|
||||||
|
- NULL,
|
||||||
|
- NULL,
|
||||||
|
- NULL,
|
||||||
|
- NULL,
|
||||||
|
- NULL,
|
||||||
|
- NULL,
|
||||||
|
- NULL,
|
||||||
|
- NULL,
|
||||||
|
- NULL,
|
||||||
|
- NULL,
|
||||||
|
- NULL
|
||||||
|
+ nullptr, // addProperty
|
||||||
|
+ nullptr, // deleteProperty
|
||||||
|
+ nullptr, // enumerate
|
||||||
|
+ nullptr, // newEnumerate
|
||||||
|
+ nullptr, // resolve
|
||||||
|
+ nullptr, // mayResolve
|
||||||
|
+ nullptr, // finalize
|
||||||
|
+ nullptr, // call
|
||||||
|
+ nullptr, // hasInstance
|
||||||
|
+ nullptr, // construct
|
||||||
|
+ nullptr // trace
|
||||||
|
};
|
||||||
|
|
||||||
|
static JSClass js_polkit_class = {
|
||||||
|
@@ -469,19 +467,18 @@ polkit_backend_js_authority_constructed (GObject *object)
|
||||||
|
|
||||||
|
{
|
||||||
|
JS::CompartmentOptions compart_opts;
|
||||||
|
- compart_opts.behaviors().setVersion(JSVERSION_LATEST);
|
||||||
|
+
|
||||||
|
JS::RootedObject global(authority->priv->cx);
|
||||||
|
|
||||||
|
authority->priv->js_global = new JS::Heap<JSObject*> (JS_NewGlobalObject (authority->priv->cx, &js_global_class, NULL, JS::FireOnNewGlobalHook, compart_opts));
|
||||||
|
|
||||||
|
global = authority->priv->js_global->get ();
|
||||||
|
-
|
||||||
|
- if (global == NULL)
|
||||||
|
+ if (!global)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
authority->priv->ac = new JSAutoCompartment(authority->priv->cx, global);
|
||||||
|
|
||||||
|
- if (authority->priv->ac == NULL)
|
||||||
|
+ if (!authority->priv->ac)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (!JS_InitStandardClasses (authority->priv->cx, global))
|
||||||
|
@@ -493,7 +490,7 @@ polkit_backend_js_authority_constructed (GObject *object)
|
||||||
|
|
||||||
|
polkit = authority->priv->js_polkit->get ();
|
||||||
|
|
||||||
|
- if (polkit == NULL)
|
||||||
|
+ if (!polkit)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (!JS_DefineProperty(authority->priv->cx, global, "polkit", polkit, JSPROP_ENUMERATE))
|
||||||
|
@@ -504,7 +501,7 @@ polkit_backend_js_authority_constructed (GObject *object)
|
||||||
|
js_polkit_functions))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
- JS::CompileOptions options(authority->priv->cx, JSVERSION_UNKNOWN);
|
||||||
|
+ JS::CompileOptions options(authority->priv->cx);
|
||||||
|
JS::RootedValue rval(authority->priv->cx);
|
||||||
|
if (!JS::Evaluate (authority->priv->cx,
|
||||||
|
options,
|
||||||
|
@@ -684,7 +681,9 @@ set_property_strv (PolkitBackendJsAuthority *authority,
|
||||||
|
JS::AutoValueVector elems(authority->priv->cx);
|
||||||
|
guint n;
|
||||||
|
|
||||||
|
- elems.resize(value->len);
|
||||||
|
+ if (!elems.resize(value->len))
|
||||||
|
+ g_error ("Unable to resize vector");
|
||||||
|
+
|
||||||
|
for (n = 0; n < value->len; n++)
|
||||||
|
{
|
||||||
|
const char *c_string = (const char *) g_ptr_array_index(value, n);
|
||||||
|
@@ -741,7 +740,7 @@ subject_to_jsval (PolkitBackendJsAuthority *authority,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
gboolean ret = FALSE;
|
||||||
|
- JS::CompileOptions options(authority->priv->cx, JSVERSION_UNKNOWN);
|
||||||
|
+ JS::CompileOptions options(authority->priv->cx);
|
||||||
|
const char *src;
|
||||||
|
JS::RootedObject obj(authority->priv->cx);
|
||||||
|
pid_t pid;
|
||||||
|
@@ -868,7 +867,7 @@ action_and_details_to_jsval (PolkitBackendJsAuthority *authority,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
gboolean ret = FALSE;
|
||||||
|
- JS::CompileOptions options(authority->priv->cx, JSVERSION_UNKNOWN);
|
||||||
|
+ JS::CompileOptions options(authority->priv->cx);
|
||||||
|
const char *src;
|
||||||
|
JS::RootedObject obj(authority->priv->cx);
|
||||||
|
gchar **keys;
|
||||||
|
|
@ -0,0 +1,13 @@
|
|||||||
|
diff -up ./src/programs/pkttyagent.c.ori ./src/programs/pkttyagent.c
|
||||||
|
--- ./src/programs/pkttyagent.c.ori 2018-08-01 15:51:28.495910434 +0200
|
||||||
|
+++ ./src/programs/pkttyagent.c 2018-08-02 15:51:45.126311197 +0200
|
||||||
|
@@ -150,7 +150,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;
|
@ -0,0 +1,12 @@
|
|||||||
|
diff -up ./src/programs/pkttyagent.c.ori ./src/programs/pkttyagent.c
|
||||||
|
--- ./src/programs/pkttyagent.c.ori 2019-09-27 14:14:35.096310576 +0200
|
||||||
|
+++ ./src/programs/pkttyagent.c 2019-09-27 14:14:56.988586737 +0200
|
||||||
|
@@ -55,7 +55,7 @@ static void tty_handler(int signal)
|
||||||
|
|
||||||
|
if (tty_flags_saved)
|
||||||
|
{
|
||||||
|
- tcsetattr (fileno (tty), TCSAFLUSH, &ts);
|
||||||
|
+ tcsetattr (fileno (tty), TCSADRAIN, &ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
kill(getpid(), signal);
|
@ -0,0 +1,94 @@
|
|||||||
|
commit bfb722bbe5a503095cc7e860f282b142f5aa75f1
|
||||||
|
Author: Jan Rybar <jrybar@redhat.com>
|
||||||
|
Date: Fri Mar 15 16:07:53 2019 +0000
|
||||||
|
|
||||||
|
pkttyagent: PolkitAgentTextListener leaves echo tty disabled if SIGINT/SIGTERM
|
||||||
|
|
||||||
|
If no password is typed into terminal during authentication raised by PolkitAgentTextListener, pkttyagent sends kill (it receives from systemctl/hostnamectl e.g.) without chance to restore echoing back on. This cannot be done in on_request() since it's run in a thread without guarantee the signal is distributed there.
|
||||||
|
|
||||||
|
diff --git a/src/programs/pkttyagent.c b/src/programs/pkttyagent.c
|
||||||
|
index 3f324b8..3c8d502 100644
|
||||||
|
--- a/src/programs/pkttyagent.c
|
||||||
|
+++ b/src/programs/pkttyagent.c
|
||||||
|
@@ -25,11 +25,44 @@
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
+#include <signal.h>
|
||||||
|
+#include <termios.h>
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
#include <polkit/polkit.h>
|
||||||
|
#define POLKIT_AGENT_I_KNOW_API_IS_SUBJECT_TO_CHANGE
|
||||||
|
#include <polkitagent/polkitagent.h>
|
||||||
|
|
||||||
|
+
|
||||||
|
+static volatile sig_atomic_t tty_flags_saved;
|
||||||
|
+struct termios ts;
|
||||||
|
+FILE *tty = NULL;
|
||||||
|
+struct sigaction savesigterm, savesigint, savesigtstp;
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+static void tty_handler(int signal)
|
||||||
|
+{
|
||||||
|
+ switch (signal)
|
||||||
|
+ {
|
||||||
|
+ case SIGTERM:
|
||||||
|
+ sigaction (SIGTERM, &savesigterm, NULL);
|
||||||
|
+ break;
|
||||||
|
+ case SIGINT:
|
||||||
|
+ sigaction (SIGINT, &savesigint, NULL);
|
||||||
|
+ break;
|
||||||
|
+ case SIGTSTP:
|
||||||
|
+ sigaction (SIGTSTP, &savesigtstp, NULL);
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (tty_flags_saved)
|
||||||
|
+ {
|
||||||
|
+ tcsetattr (fileno (tty), TCSAFLUSH, &ts);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ kill(getpid(), signal);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
int
|
||||||
|
main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
@@ -74,6 +107,8 @@ main (int argc, char *argv[])
|
||||||
|
GMainLoop *loop = NULL;
|
||||||
|
guint ret = 126;
|
||||||
|
GVariantBuilder builder;
|
||||||
|
+ struct sigaction sa;
|
||||||
|
+ const char *tty_name = NULL;
|
||||||
|
|
||||||
|
/* Disable remote file access from GIO. */
|
||||||
|
setenv ("GIO_USE_VFS", "local", 1);
|
||||||
|
@@ -212,6 +247,27 @@ main (int argc, char *argv[])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* Bash leaves tty echo disabled if SIGINT/SIGTERM comes to polkitagenttextlistener.c::on_request(),
|
||||||
|
+ but due to threading the handlers cannot take care of the signal there.
|
||||||
|
+ Though if controlling terminal cannot be found, the world won't stop spinning.
|
||||||
|
+*/
|
||||||
|
+ tty_name = ctermid(NULL);
|
||||||
|
+ if (tty_name != NULL)
|
||||||
|
+ {
|
||||||
|
+ tty = fopen(tty_name, "r+");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (tty != NULL && !tcgetattr (fileno (tty), &ts))
|
||||||
|
+ {
|
||||||
|
+ tty_flags_saved = TRUE;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ memset (&sa, 0, sizeof (sa));
|
||||||
|
+ sa.sa_handler = &tty_handler;
|
||||||
|
+ sigaction (SIGTERM, &sa, &savesigterm);
|
||||||
|
+ sigaction (SIGINT, &sa, &savesigint);
|
||||||
|
+ sigaction (SIGTSTP, &sa, &savesigtstp);
|
||||||
|
+
|
||||||
|
loop = g_main_loop_new (NULL, FALSE);
|
||||||
|
g_main_loop_run (loop);
|
||||||
|
|
@ -0,0 +1,11 @@
|
|||||||
|
diff -up ./src/polkitagent/polkitagentlistener.c.ori ./src/polkitagent/polkitagentlistener.c
|
||||||
|
--- ./src/polkitagent/polkitagentlistener.c.ori 2018-08-10 14:58:58.555475169 +0200
|
||||||
|
+++ ./src/polkitagent/polkitagentlistener.c 2018-08-10 14:59:15.900396570 +0200
|
||||||
|
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
diff -up ./src/polkitbackend/polkitbackendjsauthority.cpp.ori ./src/polkitbackend/polkitbackendjsauthority.cpp
|
||||||
|
--- ./src/polkitbackend/polkitbackendjsauthority.cpp.ori 2018-04-03 22:57:57.000000000 +0200
|
||||||
|
+++ ./src/polkitbackend/polkitbackendjsauthority.cpp 2018-08-14 16:47:48.416993302 +0200
|
||||||
|
@@ -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;
|
||||||
|
}
|
@ -0,0 +1,77 @@
|
|||||||
|
diff -up ./src/polkitagent/polkitagenttextlistener.c.ori ./src/polkitagent/polkitagenttextlistener.c
|
||||||
|
--- ./src/polkitagent/polkitagenttextlistener.c.ori 2018-05-31 13:52:23.000000000 +0200
|
||||||
|
+++ ./src/polkitagent/polkitagenttextlistener.c 2022-10-21 17:21:11.227665209 +0200
|
||||||
|
@@ -121,6 +121,12 @@ polkit_agent_text_listener_class_init (P
|
||||||
|
listener_class = POLKIT_AGENT_LISTENER_CLASS (klass);
|
||||||
|
listener_class->initiate_authentication = polkit_agent_text_listener_initiate_authentication;
|
||||||
|
listener_class->initiate_authentication_finish = polkit_agent_text_listener_initiate_authentication_finish;
|
||||||
|
+
|
||||||
|
+ g_signal_new("tty_attrs_changed",
|
||||||
|
+ G_TYPE_FROM_CLASS(gobject_class),
|
||||||
|
+ G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
|
||||||
|
+ 0, NULL, NULL, NULL,
|
||||||
|
+ G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@@ -268,6 +274,7 @@ on_request (PolkitAgentSession *session,
|
||||||
|
* the problem.
|
||||||
|
*/
|
||||||
|
|
||||||
|
+ g_signal_emit_by_name(listener, "tty_attrs_changed", TRUE);
|
||||||
|
tcgetattr (fileno (listener->tty), &ts);
|
||||||
|
ots = ts;
|
||||||
|
ts.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
|
||||||
|
@@ -296,6 +303,7 @@ on_request (PolkitAgentSession *session,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tcsetattr (fileno (listener->tty), TCSAFLUSH, &ots);
|
||||||
|
+ g_signal_emit_by_name(listener, "tty_attrs_changed", FALSE);
|
||||||
|
putc ('\n', listener->tty);
|
||||||
|
|
||||||
|
polkit_agent_session_response (session, str->str);
|
||||||
|
diff -up ./src/programs/pkttyagent.c.ori ./src/programs/pkttyagent.c
|
||||||
|
--- ./src/programs/pkttyagent.c.ori 2020-01-28 14:16:32.000000000 +0100
|
||||||
|
+++ ./src/programs/pkttyagent.c 2022-10-21 16:56:12.449760361 +0200
|
||||||
|
@@ -34,6 +34,7 @@
|
||||||
|
|
||||||
|
|
||||||
|
static volatile sig_atomic_t tty_flags_saved;
|
||||||
|
+static volatile sig_atomic_t tty_flags_changed;
|
||||||
|
struct termios ts;
|
||||||
|
FILE *tty = NULL;
|
||||||
|
struct sigaction savesigterm, savesigint, savesigtstp;
|
||||||
|
@@ -54,7 +55,7 @@ static void tty_handler(int signal)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (tty_flags_saved)
|
||||||
|
+ if (tty_flags_saved && tty_flags_changed)
|
||||||
|
{
|
||||||
|
tcsetattr (fileno (tty), TCSADRAIN, &ts);
|
||||||
|
}
|
||||||
|
@@ -63,6 +64,14 @@ static void tty_handler(int signal)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
+static void tty_attrs_changed(PolkitAgentListener *listener G_GNUC_UNUSED,
|
||||||
|
+ gboolean changed,
|
||||||
|
+ gpointer user_data G_GNUC_UNUSED)
|
||||||
|
+{
|
||||||
|
+ tty_flags_changed = changed;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
int
|
||||||
|
main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
@@ -221,6 +230,9 @@ main (int argc, char *argv[])
|
||||||
|
ret = 127;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
+ g_signal_connect(G_OBJECT(listener), "tty_attrs_changed",
|
||||||
|
+ G_CALLBACK(tty_attrs_changed), NULL);
|
||||||
|
+
|
||||||
|
local_agent_handle = polkit_agent_listener_register_with_options (listener,
|
||||||
|
POLKIT_AGENT_REGISTER_FLAGS_RUN_IN_THREAD,
|
||||||
|
subject,
|
@ -0,0 +1,6 @@
|
|||||||
|
-----BEGIN PGP SIGNATURE-----
|
||||||
|
|
||||||
|
iF0EABECAB0WIQTBl22e2Rp0WcvOUxRaM/Zgs4R53wUCW0S8UgAKCRBaM/Zgs4R5
|
||||||
|
3wNmAJ9YYc3MgbepSXr0mqWdiL93TmYMvwCeNf1e4EGsqndw9DP3CbpICMN7gV0=
|
||||||
|
=mAps
|
||||||
|
-----END PGP SIGNATURE-----
|
Loading…
Reference in new issue