summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--meta-oe/recipes-extended/polkit/polkit/0001-pkexec-local-privilege-escalation-CVE-2021-4034.patch84
-rw-r--r--meta-oe/recipes-extended/polkit/polkit/0002-CVE-2021-4115-GHSL-2021-077-fix.patch88
-rw-r--r--meta-oe/recipes-extended/polkit/polkit/0002-jsauthority-port-to-mozjs-91.patch38
-rw-r--r--meta-oe/recipes-extended/polkit/polkit/0003-Added-support-for-duktape-as-JS-engine.patch3459
-rw-r--r--meta-oe/recipes-extended/polkit/polkit/0003-jsauthority-ensure-to-call-JS_Init-and-JS_ShutDown-e.patch63
-rw-r--r--meta-oe/recipes-extended/polkit/polkit/0004-Make-netgroup-support-optional.patch253
-rw-r--r--meta-oe/recipes-extended/polkit/polkit/0005-Make-netgroup-support-optional-duktape.patch34
-rw-r--r--meta-oe/recipes-extended/polkit/polkit/polkit-1_pam.patch35
-rw-r--r--meta-oe/recipes-extended/polkit/polkit_0.119.bb79
9 files changed, 0 insertions, 4133 deletions
diff --git a/meta-oe/recipes-extended/polkit/polkit/0001-pkexec-local-privilege-escalation-CVE-2021-4034.patch b/meta-oe/recipes-extended/polkit/polkit/0001-pkexec-local-privilege-escalation-CVE-2021-4034.patch
deleted file mode 100644
index c725c001dd..0000000000
--- a/meta-oe/recipes-extended/polkit/polkit/0001-pkexec-local-privilege-escalation-CVE-2021-4034.patch
+++ /dev/null
@@ -1,84 +0,0 @@
1From 85c2dd9275cdfb369f613089f22733c0f1ba2aec Mon Sep 17 00:00:00 2001
2From: Jan Rybar <jrybar@redhat.com>
3Date: Tue, 25 Jan 2022 17:21:46 +0000
4Subject: [PATCH 1/3] pkexec: local privilege escalation (CVE-2021-4034)
5
6Signed-off-by: Mikko Rapeli <mikko.rapeli@bmw.de>
7
8---
9 src/programs/pkcheck.c | 5 +++++
10 src/programs/pkexec.c | 23 ++++++++++++++++++++---
11 2 files changed, 25 insertions(+), 3 deletions(-)
12
13CVE: CVE-2021-4034
14Upstream-Status: Backport [a2bf5c9c83b6ae46cbd5c779d3055bff81ded683]
15
16diff --git a/src/programs/pkcheck.c b/src/programs/pkcheck.c
17index f1bb4e1..768525c 100644
18--- a/src/programs/pkcheck.c
19+++ b/src/programs/pkcheck.c
20@@ -363,6 +363,11 @@ main (int argc, char *argv[])
21 local_agent_handle = NULL;
22 ret = 126;
23
24+ if (argc < 1)
25+ {
26+ exit(126);
27+ }
28+
29 /* Disable remote file access from GIO. */
30 setenv ("GIO_USE_VFS", "local", 1);
31
32diff --git a/src/programs/pkexec.c b/src/programs/pkexec.c
33index 7698c5c..84e5ef6 100644
34--- a/src/programs/pkexec.c
35+++ b/src/programs/pkexec.c
36@@ -488,6 +488,15 @@ main (int argc, char *argv[])
37 pid_t pid_of_caller;
38 gpointer local_agent_handle;
39
40+
41+ /*
42+ * If 'pkexec' is called THIS wrong, someone's probably evil-doing. Don't be nice, just bail out.
43+ */
44+ if (argc<1)
45+ {
46+ exit(127);
47+ }
48+
49 ret = 127;
50 authority = NULL;
51 subject = NULL;
52@@ -614,10 +623,10 @@ main (int argc, char *argv[])
53
54 path = g_strdup (pwstruct.pw_shell);
55 if (!path)
56- {
57+ {
58 g_printerr ("No shell configured or error retrieving pw_shell\n");
59 goto out;
60- }
61+ }
62 /* If you change this, be sure to change the if (!command_line)
63 case below too */
64 command_line = g_strdup (path);
65@@ -636,7 +645,15 @@ main (int argc, char *argv[])
66 goto out;
67 }
68 g_free (path);
69- argv[n] = path = s;
70+ path = s;
71+
72+ /* argc<2 and pkexec runs just shell, argv is guaranteed to be null-terminated.
73+ * /-less shell shouldn't happen, but let's be defensive and don't write to null-termination
74+ */
75+ if (argv[n] != NULL)
76+ {
77+ argv[n] = path;
78+ }
79 }
80 if (access (path, F_OK) != 0)
81 {
82--
832.20.1
84
diff --git a/meta-oe/recipes-extended/polkit/polkit/0002-CVE-2021-4115-GHSL-2021-077-fix.patch b/meta-oe/recipes-extended/polkit/polkit/0002-CVE-2021-4115-GHSL-2021-077-fix.patch
deleted file mode 100644
index fcad872dc3..0000000000
--- a/meta-oe/recipes-extended/polkit/polkit/0002-CVE-2021-4115-GHSL-2021-077-fix.patch
+++ /dev/null
@@ -1,88 +0,0 @@
1From c86aea01a06ad4d6c428137e9cfe2f74b1ae7f01 Mon Sep 17 00:00:00 2001
2From: Jan Rybar <jrybar@redhat.com>
3Date: Mon, 21 Feb 2022 08:29:05 +0000
4Subject: [PATCH 2/3] CVE-2021-4115 (GHSL-2021-077) fix
5
6Signed-off-by: Mikko Rapeli <mikko.rapeli@bmw.de>
7
8---
9 src/polkit/polkitsystembusname.c | 38 ++++++++++++++++++++++++++++----
10 1 file changed, 34 insertions(+), 4 deletions(-)
11
12CVE: CVE-2021-4115
13Upstream-Status: Backport [41cb093f554da8772362654a128a84dd8a5542a7]
14
15diff --git a/src/polkit/polkitsystembusname.c b/src/polkit/polkitsystembusname.c
16index 8ed1363..2fbf5f1 100644
17--- a/src/polkit/polkitsystembusname.c
18+++ b/src/polkit/polkitsystembusname.c
19@@ -62,6 +62,10 @@ enum
20 PROP_NAME,
21 };
22
23+
24+guint8 dbus_call_respond_fails; // has to be global because of callback
25+
26+
27 static void subject_iface_init (PolkitSubjectIface *subject_iface);
28
29 G_DEFINE_TYPE_WITH_CODE (PolkitSystemBusName, polkit_system_bus_name, G_TYPE_OBJECT,
30@@ -364,6 +368,7 @@ on_retrieved_unix_uid_pid (GObject *src,
31 if (!v)
32 {
33 data->caught_error = TRUE;
34+ dbus_call_respond_fails += 1;
35 }
36 else
37 {
38@@ -405,6 +410,8 @@ polkit_system_bus_name_get_creds_sync (PolkitSystemBusName *system_bus
39 tmp_context = g_main_context_new ();
40 g_main_context_push_thread_default (tmp_context);
41
42+ dbus_call_respond_fails = 0;
43+
44 /* Do two async calls as it's basically as fast as one sync call.
45 */
46 g_dbus_connection_call (connection,
47@@ -432,11 +439,34 @@ polkit_system_bus_name_get_creds_sync (PolkitSystemBusName *system_bus
48 on_retrieved_unix_uid_pid,
49 &data);
50
51- while (!((data.retrieved_uid && data.retrieved_pid) || data.caught_error))
52- g_main_context_iteration (tmp_context, TRUE);
53+ while (TRUE)
54+ {
55+ /* If one dbus call returns error, we must wait until the other call
56+ * calls _call_finish(), otherwise fd leak is possible.
57+ * Resolves: GHSL-2021-077
58+ */
59
60- if (data.caught_error)
61- goto out;
62+ if ( (dbus_call_respond_fails > 1) )
63+ {
64+ // we got two faults, we can leave
65+ goto out;
66+ }
67+
68+ if ((data.caught_error && (data.retrieved_pid || data.retrieved_uid)))
69+ {
70+ // we got one fault and the other call finally finished, we can leave
71+ goto out;
72+ }
73+
74+ if ( !(data.retrieved_uid && data.retrieved_pid) )
75+ {
76+ g_main_context_iteration (tmp_context, TRUE);
77+ }
78+ else
79+ {
80+ break;
81+ }
82+ }
83
84 if (out_uid)
85 *out_uid = data.uid;
86--
872.20.1
88
diff --git a/meta-oe/recipes-extended/polkit/polkit/0002-jsauthority-port-to-mozjs-91.patch b/meta-oe/recipes-extended/polkit/polkit/0002-jsauthority-port-to-mozjs-91.patch
deleted file mode 100644
index 5b3660da2f..0000000000
--- a/meta-oe/recipes-extended/polkit/polkit/0002-jsauthority-port-to-mozjs-91.patch
+++ /dev/null
@@ -1,38 +0,0 @@
1From 4ce27b66bb07b72cb96d3d43a75108a5a6e7e156 Mon Sep 17 00:00:00 2001
2From: Xi Ruoyao <xry111@mengyan1223.wang>
3Date: Tue, 10 Aug 2021 19:09:42 +0800
4Subject: [PATCH] jsauthority: port to mozjs-91
5
6Upstream-Status: Submitted [https://gitlab.freedesktop.org/polkit/polkit/-/merge_requests/92]
7Signed-off-by: Alexander Kanavin <alex@linutronix.de>
8---
9 configure.ac | 2 +-
10 meson.build | 2 +-
11 2 files changed, 2 insertions(+), 2 deletions(-)
12
13diff --git a/configure.ac b/configure.ac
14index d807086..5a7fc11 100644
15--- a/configure.ac
16+++ b/configure.ac
17@@ -80,7 +80,7 @@ PKG_CHECK_MODULES(GLIB, [gmodule-2.0 gio-unix-2.0 >= 2.30.0])
18 AC_SUBST(GLIB_CFLAGS)
19 AC_SUBST(GLIB_LIBS)
20
21-PKG_CHECK_MODULES(LIBJS, [mozjs-78])
22+PKG_CHECK_MODULES(LIBJS, [mozjs-91])
23
24 AC_SUBST(LIBJS_CFLAGS)
25 AC_SUBST(LIBJS_CXXFLAGS)
26diff --git a/meson.build b/meson.build
27index b3702be..733bbff 100644
28--- a/meson.build
29+++ b/meson.build
30@@ -126,7 +126,7 @@ expat_dep = dependency('expat')
31 assert(cc.has_header('expat.h', dependencies: expat_dep), 'Can\'t find expat.h. Please install expat.')
32 assert(cc.has_function('XML_ParserCreate', dependencies: expat_dep), 'Can\'t find expat library. Please install expat.')
33
34-mozjs_dep = dependency('mozjs-78')
35+mozjs_dep = dependency('mozjs-91')
36
37 dbus_dep = dependency('dbus-1')
38 dbus_confdir = dbus_dep.get_pkgconfig_variable('datadir', define_variable: ['datadir', pk_prefix / pk_datadir]) #changed from sysconfdir with respect to commit#8eada3836465838
diff --git a/meta-oe/recipes-extended/polkit/polkit/0003-Added-support-for-duktape-as-JS-engine.patch b/meta-oe/recipes-extended/polkit/polkit/0003-Added-support-for-duktape-as-JS-engine.patch
deleted file mode 100644
index b8562f8ce2..0000000000
--- a/meta-oe/recipes-extended/polkit/polkit/0003-Added-support-for-duktape-as-JS-engine.patch
+++ /dev/null
@@ -1,3459 +0,0 @@
1From 4af72493cb380ab5ce0dd7c5bcd25a8b5457d770 Mon Sep 17 00:00:00 2001
2From: Gustavo Lima Chaves <limachaves@gmail.com>
3Date: Tue, 25 Jan 2022 09:43:21 +0000
4Subject: [PATCH] Added support for duktape as JS engine
5
6Original author: Wu Xiaotian (@yetist)
7Resurrection author, runaway-killer author: Gustavo Lima Chaves (@limachaves)
8
9Signed-off-by: Mikko Rapeli <mikko.rapeli@bmw.de>
10
11Upstream-Status: Backport [c7fc4e1b61f0fd82fc697c19c604af7e9fb291a2]
12Dropped change to .gitlab-ci.yml and adapted configure.ac due to other
13patches in meta-oe.
14
15---
16 buildutil/ax_pthread.m4 | 522 ++++++++
17 configure.ac | 34 +-
18 docs/man/polkit.xml | 4 +-
19 meson.build | 16 +-
20 meson_options.txt | 1 +
21 src/polkitbackend/Makefile.am | 17 +-
22 src/polkitbackend/meson.build | 14 +-
23 src/polkitbackend/polkitbackendcommon.c | 530 +++++++++
24 src/polkitbackend/polkitbackendcommon.h | 158 +++
25 .../polkitbackendduktapeauthority.c | 1051 +++++++++++++++++
26 .../polkitbackendjsauthority.cpp | 721 +----------
27 .../etc/polkit-1/rules.d/10-testing.rules | 6 +-
28 .../test-polkitbackendjsauthority.c | 2 +-
29 13 files changed, 2398 insertions(+), 678 deletions(-)
30 create mode 100644 buildutil/ax_pthread.m4
31 create mode 100644 src/polkitbackend/polkitbackendcommon.c
32 create mode 100644 src/polkitbackend/polkitbackendcommon.h
33 create mode 100644 src/polkitbackend/polkitbackendduktapeauthority.c
34
35diff --git a/buildutil/ax_pthread.m4 b/buildutil/ax_pthread.m4
36new file mode 100644
37index 0000000..9f35d13
38--- /dev/null
39+++ b/buildutil/ax_pthread.m4
40@@ -0,0 +1,522 @@
41+# ===========================================================================
42+# https://www.gnu.org/software/autoconf-archive/ax_pthread.html
43+# ===========================================================================
44+#
45+# SYNOPSIS
46+#
47+# AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
48+#
49+# DESCRIPTION
50+#
51+# This macro figures out how to build C programs using POSIX threads. It
52+# sets the PTHREAD_LIBS output variable to the threads library and linker
53+# flags, and the PTHREAD_CFLAGS output variable to any special C compiler
54+# flags that are needed. (The user can also force certain compiler
55+# flags/libs to be tested by setting these environment variables.)
56+#
57+# Also sets PTHREAD_CC and PTHREAD_CXX to any special C compiler that is
58+# needed for multi-threaded programs (defaults to the value of CC
59+# respectively CXX otherwise). (This is necessary on e.g. AIX to use the
60+# special cc_r/CC_r compiler alias.)
61+#
62+# NOTE: You are assumed to not only compile your program with these flags,
63+# but also to link with them as well. For example, you might link with
64+# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
65+# $PTHREAD_CXX $CXXFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
66+#
67+# If you are only building threaded programs, you may wish to use these
68+# variables in your default LIBS, CFLAGS, and CC:
69+#
70+# LIBS="$PTHREAD_LIBS $LIBS"
71+# CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
72+# CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS"
73+# CC="$PTHREAD_CC"
74+# CXX="$PTHREAD_CXX"
75+#
76+# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant
77+# has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to
78+# that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
79+#
80+# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the
81+# PTHREAD_PRIO_INHERIT symbol is defined when compiling with
82+# PTHREAD_CFLAGS.
83+#
84+# ACTION-IF-FOUND is a list of shell commands to run if a threads library
85+# is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it
86+# is not found. If ACTION-IF-FOUND is not specified, the default action
87+# will define HAVE_PTHREAD.
88+#
89+# Please let the authors know if this macro fails on any platform, or if
90+# you have any other suggestions or comments. This macro was based on work
91+# by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help
92+# from M. Frigo), as well as ac_pthread and hb_pthread macros posted by
93+# Alejandro Forero Cuervo to the autoconf macro repository. We are also
94+# grateful for the helpful feedback of numerous users.
95+#
96+# Updated for Autoconf 2.68 by Daniel Richard G.
97+#
98+# LICENSE
99+#
100+# Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu>
101+# Copyright (c) 2011 Daniel Richard G. <skunk@iSKUNK.ORG>
102+# Copyright (c) 2019 Marc Stevens <marc.stevens@cwi.nl>
103+#
104+# This program is free software: you can redistribute it and/or modify it
105+# under the terms of the GNU General Public License as published by the
106+# Free Software Foundation, either version 3 of the License, or (at your
107+# option) any later version.
108+#
109+# This program is distributed in the hope that it will be useful, but
110+# WITHOUT ANY WARRANTY; without even the implied warranty of
111+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
112+# Public License for more details.
113+#
114+# You should have received a copy of the GNU General Public License along
115+# with this program. If not, see <https://www.gnu.org/licenses/>.
116+#
117+# As a special exception, the respective Autoconf Macro's copyright owner
118+# gives unlimited permission to copy, distribute and modify the configure
119+# scripts that are the output of Autoconf when processing the Macro. You
120+# need not follow the terms of the GNU General Public License when using
121+# or distributing such scripts, even though portions of the text of the
122+# Macro appear in them. The GNU General Public License (GPL) does govern
123+# all other use of the material that constitutes the Autoconf Macro.
124+#
125+# This special exception to the GPL applies to versions of the Autoconf
126+# Macro released by the Autoconf Archive. When you make and distribute a
127+# modified version of the Autoconf Macro, you may extend this special
128+# exception to the GPL to apply to your modified version as well.
129+
130+#serial 31
131+
132+AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
133+AC_DEFUN([AX_PTHREAD], [
134+AC_REQUIRE([AC_CANONICAL_HOST])
135+AC_REQUIRE([AC_PROG_CC])
136+AC_REQUIRE([AC_PROG_SED])
137+AC_LANG_PUSH([C])
138+ax_pthread_ok=no
139+
140+# We used to check for pthread.h first, but this fails if pthread.h
141+# requires special compiler flags (e.g. on Tru64 or Sequent).
142+# It gets checked for in the link test anyway.
143+
144+# First of all, check if the user has set any of the PTHREAD_LIBS,
145+# etcetera environment variables, and if threads linking works using
146+# them:
147+if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then
148+ ax_pthread_save_CC="$CC"
149+ ax_pthread_save_CFLAGS="$CFLAGS"
150+ ax_pthread_save_LIBS="$LIBS"
151+ AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"])
152+ AS_IF([test "x$PTHREAD_CXX" != "x"], [CXX="$PTHREAD_CXX"])
153+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
154+ LIBS="$PTHREAD_LIBS $LIBS"
155+ AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS])
156+ AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes])
157+ AC_MSG_RESULT([$ax_pthread_ok])
158+ if test "x$ax_pthread_ok" = "xno"; then
159+ PTHREAD_LIBS=""
160+ PTHREAD_CFLAGS=""
161+ fi
162+ CC="$ax_pthread_save_CC"
163+ CFLAGS="$ax_pthread_save_CFLAGS"
164+ LIBS="$ax_pthread_save_LIBS"
165+fi
166+
167+# We must check for the threads library under a number of different
168+# names; the ordering is very important because some systems
169+# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
170+# libraries is broken (non-POSIX).
171+
172+# Create a list of thread flags to try. Items with a "," contain both
173+# C compiler flags (before ",") and linker flags (after ","). Other items
174+# starting with a "-" are C compiler flags, and remaining items are
175+# library names, except for "none" which indicates that we try without
176+# any flags at all, and "pthread-config" which is a program returning
177+# the flags for the Pth emulation library.
178+
179+ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
180+
181+# The ordering *is* (sometimes) important. Some notes on the
182+# individual items follow:
183+
184+# pthreads: AIX (must check this before -lpthread)
185+# none: in case threads are in libc; should be tried before -Kthread and
186+# other compiler flags to prevent continual compiler warnings
187+# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
188+# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64
189+# (Note: HP C rejects this with "bad form for `-t' option")
190+# -pthreads: Solaris/gcc (Note: HP C also rejects)
191+# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
192+# doesn't hurt to check since this sometimes defines pthreads and
193+# -D_REENTRANT too), HP C (must be checked before -lpthread, which
194+# is present but should not be used directly; and before -mthreads,
195+# because the compiler interprets this as "-mt" + "-hreads")
196+# -mthreads: Mingw32/gcc, Lynx/gcc
197+# pthread: Linux, etcetera
198+# --thread-safe: KAI C++
199+# pthread-config: use pthread-config program (for GNU Pth library)
200+
201+case $host_os in
202+
203+ freebsd*)
204+
205+ # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
206+ # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
207+
208+ ax_pthread_flags="-kthread lthread $ax_pthread_flags"
209+ ;;
210+
211+ hpux*)
212+
213+ # From the cc(1) man page: "[-mt] Sets various -D flags to enable
214+ # multi-threading and also sets -lpthread."
215+
216+ ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags"
217+ ;;
218+
219+ openedition*)
220+
221+ # IBM z/OS requires a feature-test macro to be defined in order to
222+ # enable POSIX threads at all, so give the user a hint if this is
223+ # not set. (We don't define these ourselves, as they can affect
224+ # other portions of the system API in unpredictable ways.)
225+
226+ AC_EGREP_CPP([AX_PTHREAD_ZOS_MISSING],
227+ [
228+# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS)
229+ AX_PTHREAD_ZOS_MISSING
230+# endif
231+ ],
232+ [AC_MSG_WARN([IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support.])])
233+ ;;
234+
235+ solaris*)
236+
237+ # On Solaris (at least, for some versions), libc contains stubbed
238+ # (non-functional) versions of the pthreads routines, so link-based
239+ # tests will erroneously succeed. (N.B.: The stubs are missing
240+ # pthread_cleanup_push, or rather a function called by this macro,
241+ # so we could check for that, but who knows whether they'll stub
242+ # that too in a future libc.) So we'll check first for the
243+ # standard Solaris way of linking pthreads (-mt -lpthread).
244+
245+ ax_pthread_flags="-mt,-lpthread pthread $ax_pthread_flags"
246+ ;;
247+esac
248+
249+# Are we compiling with Clang?
250+
251+AC_CACHE_CHECK([whether $CC is Clang],
252+ [ax_cv_PTHREAD_CLANG],
253+ [ax_cv_PTHREAD_CLANG=no
254+ # Note that Autoconf sets GCC=yes for Clang as well as GCC
255+ if test "x$GCC" = "xyes"; then
256+ AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG],
257+ [/* Note: Clang 2.7 lacks __clang_[a-z]+__ */
258+# if defined(__clang__) && defined(__llvm__)
259+ AX_PTHREAD_CC_IS_CLANG
260+# endif
261+ ],
262+ [ax_cv_PTHREAD_CLANG=yes])
263+ fi
264+ ])
265+ax_pthread_clang="$ax_cv_PTHREAD_CLANG"
266+
267+
268+# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC)
269+
270+# Note that for GCC and Clang -pthread generally implies -lpthread,
271+# except when -nostdlib is passed.
272+# This is problematic using libtool to build C++ shared libraries with pthread:
273+# [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25460
274+# [2] https://bugzilla.redhat.com/show_bug.cgi?id=661333
275+# [3] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=468555
276+# To solve this, first try -pthread together with -lpthread for GCC
277+
278+AS_IF([test "x$GCC" = "xyes"],
279+ [ax_pthread_flags="-pthread,-lpthread -pthread -pthreads $ax_pthread_flags"])
280+
281+# Clang takes -pthread (never supported any other flag), but we'll try with -lpthread first
282+
283+AS_IF([test "x$ax_pthread_clang" = "xyes"],
284+ [ax_pthread_flags="-pthread,-lpthread -pthread"])
285+
286+
287+# The presence of a feature test macro requesting re-entrant function
288+# definitions is, on some systems, a strong hint that pthreads support is
289+# correctly enabled
290+
291+case $host_os in
292+ darwin* | hpux* | linux* | osf* | solaris*)
293+ ax_pthread_check_macro="_REENTRANT"
294+ ;;
295+
296+ aix*)
297+ ax_pthread_check_macro="_THREAD_SAFE"
298+ ;;
299+
300+ *)
301+ ax_pthread_check_macro="--"
302+ ;;
303+esac
304+AS_IF([test "x$ax_pthread_check_macro" = "x--"],
305+ [ax_pthread_check_cond=0],
306+ [ax_pthread_check_cond="!defined($ax_pthread_check_macro)"])
307+
308+
309+if test "x$ax_pthread_ok" = "xno"; then
310+for ax_pthread_try_flag in $ax_pthread_flags; do
311+
312+ case $ax_pthread_try_flag in
313+ none)
314+ AC_MSG_CHECKING([whether pthreads work without any flags])
315+ ;;
316+
317+ *,*)
318+ PTHREAD_CFLAGS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\1/"`
319+ PTHREAD_LIBS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\2/"`
320+ AC_MSG_CHECKING([whether pthreads work with "$PTHREAD_CFLAGS" and "$PTHREAD_LIBS"])
321+ ;;
322+
323+ -*)
324+ AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag])
325+ PTHREAD_CFLAGS="$ax_pthread_try_flag"
326+ ;;
327+
328+ pthread-config)
329+ AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no])
330+ AS_IF([test "x$ax_pthread_config" = "xno"], [continue])
331+ PTHREAD_CFLAGS="`pthread-config --cflags`"
332+ PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
333+ ;;
334+
335+ *)
336+ AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag])
337+ PTHREAD_LIBS="-l$ax_pthread_try_flag"
338+ ;;
339+ esac
340+
341+ ax_pthread_save_CFLAGS="$CFLAGS"
342+ ax_pthread_save_LIBS="$LIBS"
343+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
344+ LIBS="$PTHREAD_LIBS $LIBS"
345+
346+ # Check for various functions. We must include pthread.h,
347+ # since some functions may be macros. (On the Sequent, we
348+ # need a special flag -Kthread to make this header compile.)
349+ # We check for pthread_join because it is in -lpthread on IRIX
350+ # while pthread_create is in libc. We check for pthread_attr_init
351+ # due to DEC craziness with -lpthreads. We check for
352+ # pthread_cleanup_push because it is one of the few pthread
353+ # functions on Solaris that doesn't have a non-functional libc stub.
354+ # We try pthread_create on general principles.
355+
356+ AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>
357+# if $ax_pthread_check_cond
358+# error "$ax_pthread_check_macro must be defined"
359+# endif
360+ static void *some_global = NULL;
361+ static void routine(void *a)
362+ {
363+ /* To avoid any unused-parameter or
364+ unused-but-set-parameter warning. */
365+ some_global = a;
366+ }
367+ static void *start_routine(void *a) { return a; }],
368+ [pthread_t th; pthread_attr_t attr;
369+ pthread_create(&th, 0, start_routine, 0);
370+ pthread_join(th, 0);
371+ pthread_attr_init(&attr);
372+ pthread_cleanup_push(routine, 0);
373+ pthread_cleanup_pop(0) /* ; */])],
374+ [ax_pthread_ok=yes],
375+ [])
376+
377+ CFLAGS="$ax_pthread_save_CFLAGS"
378+ LIBS="$ax_pthread_save_LIBS"
379+
380+ AC_MSG_RESULT([$ax_pthread_ok])
381+ AS_IF([test "x$ax_pthread_ok" = "xyes"], [break])
382+
383+ PTHREAD_LIBS=""
384+ PTHREAD_CFLAGS=""
385+done
386+fi
387+
388+
389+# Clang needs special handling, because older versions handle the -pthread
390+# option in a rather... idiosyncratic way
391+
392+if test "x$ax_pthread_clang" = "xyes"; then
393+
394+ # Clang takes -pthread; it has never supported any other flag
395+
396+ # (Note 1: This will need to be revisited if a system that Clang
397+ # supports has POSIX threads in a separate library. This tends not
398+ # to be the way of modern systems, but it's conceivable.)
399+
400+ # (Note 2: On some systems, notably Darwin, -pthread is not needed
401+ # to get POSIX threads support; the API is always present and
402+ # active. We could reasonably leave PTHREAD_CFLAGS empty. But
403+ # -pthread does define _REENTRANT, and while the Darwin headers
404+ # ignore this macro, third-party headers might not.)
405+
406+ # However, older versions of Clang make a point of warning the user
407+ # that, in an invocation where only linking and no compilation is
408+ # taking place, the -pthread option has no effect ("argument unused
409+ # during compilation"). They expect -pthread to be passed in only
410+ # when source code is being compiled.
411+ #
412+ # Problem is, this is at odds with the way Automake and most other
413+ # C build frameworks function, which is that the same flags used in
414+ # compilation (CFLAGS) are also used in linking. Many systems
415+ # supported by AX_PTHREAD require exactly this for POSIX threads
416+ # support, and in fact it is often not straightforward to specify a
417+ # flag that is used only in the compilation phase and not in
418+ # linking. Such a scenario is extremely rare in practice.
419+ #
420+ # Even though use of the -pthread flag in linking would only print
421+ # a warning, this can be a nuisance for well-run software projects
422+ # that build with -Werror. So if the active version of Clang has
423+ # this misfeature, we search for an option to squash it.
424+
425+ AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread],
426+ [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG],
427+ [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown
428+ # Create an alternate version of $ac_link that compiles and
429+ # links in two steps (.c -> .o, .o -> exe) instead of one
430+ # (.c -> exe), because the warning occurs only in the second
431+ # step
432+ ax_pthread_save_ac_link="$ac_link"
433+ ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g'
434+ ax_pthread_link_step=`AS_ECHO(["$ac_link"]) | sed "$ax_pthread_sed"`
435+ ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)"
436+ ax_pthread_save_CFLAGS="$CFLAGS"
437+ for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do
438+ AS_IF([test "x$ax_pthread_try" = "xunknown"], [break])
439+ CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS"
440+ ac_link="$ax_pthread_save_ac_link"
441+ AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],
442+ [ac_link="$ax_pthread_2step_ac_link"
443+ AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],
444+ [break])
445+ ])
446+ done
447+ ac_link="$ax_pthread_save_ac_link"
448+ CFLAGS="$ax_pthread_save_CFLAGS"
449+ AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no])
450+ ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try"
451+ ])
452+
453+ case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in
454+ no | unknown) ;;
455+ *) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;;
456+ esac
457+
458+fi # $ax_pthread_clang = yes
459+
460+
461+
462+# Various other checks:
463+if test "x$ax_pthread_ok" = "xyes"; then
464+ ax_pthread_save_CFLAGS="$CFLAGS"
465+ ax_pthread_save_LIBS="$LIBS"
466+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
467+ LIBS="$PTHREAD_LIBS $LIBS"
468+
469+ # Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
470+ AC_CACHE_CHECK([for joinable pthread attribute],
471+ [ax_cv_PTHREAD_JOINABLE_ATTR],
472+ [ax_cv_PTHREAD_JOINABLE_ATTR=unknown
473+ for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
474+ AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>],
475+ [int attr = $ax_pthread_attr; return attr /* ; */])],
476+ [ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break],
477+ [])
478+ done
479+ ])
480+ AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \
481+ test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \
482+ test "x$ax_pthread_joinable_attr_defined" != "xyes"],
483+ [AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE],
484+ [$ax_cv_PTHREAD_JOINABLE_ATTR],
485+ [Define to necessary symbol if this constant
486+ uses a non-standard name on your system.])
487+ ax_pthread_joinable_attr_defined=yes
488+ ])
489+
490+ AC_CACHE_CHECK([whether more special flags are required for pthreads],
491+ [ax_cv_PTHREAD_SPECIAL_FLAGS],
492+ [ax_cv_PTHREAD_SPECIAL_FLAGS=no
493+ case $host_os in
494+ solaris*)
495+ ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS"
496+ ;;
497+ esac
498+ ])
499+ AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \
500+ test "x$ax_pthread_special_flags_added" != "xyes"],
501+ [PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS"
502+ ax_pthread_special_flags_added=yes])
503+
504+ AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT],
505+ [ax_cv_PTHREAD_PRIO_INHERIT],
506+ [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pthread.h>]],
507+ [[int i = PTHREAD_PRIO_INHERIT;
508+ return i;]])],
509+ [ax_cv_PTHREAD_PRIO_INHERIT=yes],
510+ [ax_cv_PTHREAD_PRIO_INHERIT=no])
511+ ])
512+ AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \
513+ test "x$ax_pthread_prio_inherit_defined" != "xyes"],
514+ [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.])
515+ ax_pthread_prio_inherit_defined=yes
516+ ])
517+
518+ CFLAGS="$ax_pthread_save_CFLAGS"
519+ LIBS="$ax_pthread_save_LIBS"
520+
521+ # More AIX lossage: compile with *_r variant
522+ if test "x$GCC" != "xyes"; then
523+ case $host_os in
524+ aix*)
525+ AS_CASE(["x/$CC"],
526+ [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6],
527+ [#handle absolute path differently from PATH based program lookup
528+ AS_CASE(["x$CC"],
529+ [x/*],
530+ [
531+ AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])
532+ AS_IF([test "x${CXX}" != "x"], [AS_IF([AS_EXECUTABLE_P([${CXX}_r])],[PTHREAD_CXX="${CXX}_r"])])
533+ ],
534+ [
535+ AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])
536+ AS_IF([test "x${CXX}" != "x"], [AC_CHECK_PROGS([PTHREAD_CXX],[${CXX}_r],[$CXX])])
537+ ]
538+ )
539+ ])
540+ ;;
541+ esac
542+ fi
543+fi
544+
545+test -n "$PTHREAD_CC" || PTHREAD_CC="$CC"
546+test -n "$PTHREAD_CXX" || PTHREAD_CXX="$CXX"
547+
548+AC_SUBST([PTHREAD_LIBS])
549+AC_SUBST([PTHREAD_CFLAGS])
550+AC_SUBST([PTHREAD_CC])
551+AC_SUBST([PTHREAD_CXX])
552+
553+# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
554+if test "x$ax_pthread_ok" = "xyes"; then
555+ ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1])
556+ :
557+else
558+ ax_pthread_ok=no
559+ $2
560+fi
561+AC_LANG_POP
562+])dnl AX_PTHREAD
563diff --git a/configure.ac b/configure.ac
564index b625743..bbf4768 100644
565--- a/configure.ac
566+++ b/configure.ac
567@@ -80,11 +80,22 @@ PKG_CHECK_MODULES(GLIB, [gmodule-2.0 gio-unix-2.0 >= 2.30.0])
568 AC_SUBST(GLIB_CFLAGS)
569 AC_SUBST(GLIB_LIBS)
570
571-PKG_CHECK_MODULES(LIBJS, [mozjs-78])
572-
573-AC_SUBST(LIBJS_CFLAGS)
574-AC_SUBST(LIBJS_CXXFLAGS)
575-AC_SUBST(LIBJS_LIBS)
576+dnl ---------------------------------------------------------------------------
577+dnl - Check javascript backend
578+dnl ---------------------------------------------------------------------------
579+AC_ARG_WITH(duktape, AS_HELP_STRING([--with-duktape],[Use Duktape as javascript backend]),with_duktape=yes,with_duktape=no)
580+AS_IF([test x${with_duktape} == xyes], [
581+ PKG_CHECK_MODULES(LIBJS, [duktape >= 2.2.0 ])
582+ AC_SUBST(LIBJS_CFLAGS)
583+ AC_SUBST(LIBJS_LIBS)
584+], [
585+ PKG_CHECK_MODULES(LIBJS, [mozjs-78])
586+
587+ AC_SUBST(LIBJS_CFLAGS)
588+ AC_SUBST(LIBJS_CXXFLAGS)
589+ AC_SUBST(LIBJS_LIBS)
590+])
591+AM_CONDITIONAL(USE_DUKTAPE, [test x$with_duktape == xyes], [Using duktape as javascript engine library])
592
593 EXPAT_LIB=""
594 AC_ARG_WITH(expat, [ --with-expat=<dir> Use expat from here],
595@@ -100,6 +111,12 @@ AC_CHECK_LIB(expat,XML_ParserCreate,[EXPAT_LIBS="-lexpat"],
596 [AC_MSG_ERROR([Can't find expat library. Please install expat.])])
597 AC_SUBST(EXPAT_LIBS)
598
599+AX_PTHREAD([], [AC_MSG_ERROR([Cannot find the way to enable pthread support.])])
600+LIBS="$PTHREAD_LIBS $LIBS"
601+CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
602+CC="$PTHREAD_CC"
603+AC_CHECK_FUNCS([pthread_condattr_setclock])
604+
605 AC_CHECK_FUNCS(clearenv fdatasync)
606
607 if test "x$GCC" = "xyes"; then
608@@ -581,6 +598,13 @@ echo "
609 PAM support: ${have_pam}
610 systemdsystemunitdir: ${systemdsystemunitdir}
611 polkitd user: ${POLKITD_USER}"
612+if test "x${with_duktape}" = xyes; then
613+echo "
614+ Javascript engine: Duktape"
615+else
616+echo "
617+ Javascript engine: Mozjs"
618+fi
619
620 if test "$have_pam" = yes ; then
621 echo "
622diff --git a/docs/man/polkit.xml b/docs/man/polkit.xml
623index 99aa474..90715a5 100644
624--- a/docs/man/polkit.xml
625+++ b/docs/man/polkit.xml
626@@ -639,7 +639,9 @@ polkit.Result = {
627 If user-provided code takes a long time to execute, an exception
628 will be thrown which normally results in the function being
629 terminated (the current limit is 15 seconds). This is used to
630- catch runaway scripts.
631+ catch runaway scripts. If the duktape JavaScript backend is
632+ compiled in, instead of mozjs, no exception will be thrown—the
633+ script will be killed right away (same timeout).
634 </para>
635
636 <para>
637diff --git a/meson.build b/meson.build
638index b3702be..7506231 100644
639--- a/meson.build
640+++ b/meson.build
641@@ -126,7 +126,18 @@ expat_dep = dependency('expat')
642 assert(cc.has_header('expat.h', dependencies: expat_dep), 'Can\'t find expat.h. Please install expat.')
643 assert(cc.has_function('XML_ParserCreate', dependencies: expat_dep), 'Can\'t find expat library. Please install expat.')
644
645-mozjs_dep = dependency('mozjs-78')
646+duktape_req_version = '>= 2.2.0'
647+
648+js_engine = get_option('js_engine')
649+if js_engine == 'duktape'
650+ js_dep = dependency('duktape', version: duktape_req_version)
651+ libm_dep = cc.find_library('m')
652+ thread_dep = dependency('threads')
653+ func = 'pthread_condattr_setclock'
654+ config_h.set('HAVE_' + func.to_upper(), cc.has_function(func, prefix : '#include <pthread.h>'))
655+elif js_engine == 'mozjs'
656+ js_dep = dependency('mozjs-78')
657+endif
658
659 dbus_dep = dependency('dbus-1')
660 dbus_confdir = dbus_dep.get_pkgconfig_variable('datadir', define_variable: ['datadir', pk_prefix / pk_datadir]) #changed from sysconfdir with respect to commit#8eada3836465838
661@@ -350,6 +361,9 @@ if enable_logind
662 output += ' systemdsystemunitdir: ' + systemd_systemdsystemunitdir + '\n'
663 endif
664 output += ' polkitd user: ' + polkitd_user + ' \n'
665+output += ' Javascript engine: ' + js_engine + '\n'
666+if enable_logind
667+endif
668 output += ' PAM support: ' + enable_pam.to_string() + '\n\n'
669 if enable_pam
670 output += ' PAM file auth: ' + pam_conf['PAM_FILE_INCLUDE_AUTH'] + '\n'
671diff --git a/meson_options.txt b/meson_options.txt
672index 25e3e77..76aa311 100644
673--- a/meson_options.txt
674+++ b/meson_options.txt
675@@ -16,3 +16,4 @@ option('introspection', type: 'boolean', value: true, description: 'Enable intro
676
677 option('gtk_doc', type: 'boolean', value: false, description: 'use gtk-doc to build documentation')
678 option('man', type: 'boolean', value: false, description: 'build manual pages')
679+option('js_engine', type: 'combo', choices: ['mozjs', 'duktape'], value: 'duktape', description: 'javascript engine')
680diff --git a/src/polkitbackend/Makefile.am b/src/polkitbackend/Makefile.am
681index 7e3c080..935fb98 100644
682--- a/src/polkitbackend/Makefile.am
683+++ b/src/polkitbackend/Makefile.am
684@@ -17,6 +17,8 @@ AM_CPPFLAGS = \
685 -DPACKAGE_LIB_DIR=\""$(libdir)"\" \
686 -D_POSIX_PTHREAD_SEMANTICS \
687 -D_REENTRANT \
688+ -D_XOPEN_SOURCE=700 \
689+ -D_GNU_SOURCE=1 \
690 $(NULL)
691
692 noinst_LTLIBRARIES=libpolkit-backend-1.la
693@@ -31,9 +33,10 @@ libpolkit_backend_1_la_SOURCES = \
694 polkitbackend.h \
695 polkitbackendtypes.h \
696 polkitbackendprivate.h \
697+ polkitbackendcommon.h polkitbackendcommon.c \
698 polkitbackendauthority.h polkitbackendauthority.c \
699 polkitbackendinteractiveauthority.h polkitbackendinteractiveauthority.c \
700- polkitbackendjsauthority.h polkitbackendjsauthority.cpp \
701+ polkitbackendjsauthority.h \
702 polkitbackendactionpool.h polkitbackendactionpool.c \
703 polkitbackendactionlookup.h polkitbackendactionlookup.c \
704 $(NULL)
705@@ -51,19 +54,27 @@ libpolkit_backend_1_la_CFLAGS = \
706 -D_POLKIT_BACKEND_COMPILATION \
707 $(GLIB_CFLAGS) \
708 $(LIBSYSTEMD_CFLAGS) \
709- $(LIBJS_CFLAGS) \
710+ $(LIBJS_CFLAGS) \
711 $(NULL)
712
713 libpolkit_backend_1_la_CXXFLAGS = $(libpolkit_backend_1_la_CFLAGS)
714
715 libpolkit_backend_1_la_LIBADD = \
716 $(GLIB_LIBS) \
717+ $(DUKTAPE_LIBS) \
718 $(LIBSYSTEMD_LIBS) \
719 $(top_builddir)/src/polkit/libpolkit-gobject-1.la \
720 $(EXPAT_LIBS) \
721- $(LIBJS_LIBS) \
722+ $(LIBJS_LIBS) \
723 $(NULL)
724
725+if USE_DUKTAPE
726+libpolkit_backend_1_la_SOURCES += polkitbackendduktapeauthority.c
727+libpolkit_backend_1_la_LIBADD += -lm
728+else
729+libpolkit_backend_1_la_SOURCES += polkitbackendjsauthority.cpp
730+endif
731+
732 rulesdir = $(sysconfdir)/polkit-1/rules.d
733 rules_DATA = 50-default.rules
734
735diff --git a/src/polkitbackend/meson.build b/src/polkitbackend/meson.build
736index 93c3c34..99f8e33 100644
737--- a/src/polkitbackend/meson.build
738+++ b/src/polkitbackend/meson.build
739@@ -4,8 +4,8 @@ sources = files(
740 'polkitbackendactionlookup.c',
741 'polkitbackendactionpool.c',
742 'polkitbackendauthority.c',
743+ 'polkitbackendcommon.c',
744 'polkitbackendinteractiveauthority.c',
745- 'polkitbackendjsauthority.cpp',
746 )
747
748 output = 'initjs.h'
749@@ -21,7 +21,7 @@ sources += custom_target(
750 deps = [
751 expat_dep,
752 libpolkit_gobject_dep,
753- mozjs_dep,
754+ js_dep,
755 ]
756
757 c_flags = [
758@@ -29,8 +29,18 @@ c_flags = [
759 '-D_POLKIT_BACKEND_COMPILATION',
760 '-DPACKAGE_DATA_DIR="@0@"'.format(pk_prefix / pk_datadir),
761 '-DPACKAGE_SYSCONF_DIR="@0@"'.format(pk_prefix / pk_sysconfdir),
762+ '-D_XOPEN_SOURCE=700',
763+ '-D_GNU_SOURCE=1',
764 ]
765
766+if js_engine == 'duktape'
767+ sources += files('polkitbackendduktapeauthority.c')
768+ deps += libm_dep
769+ deps += thread_dep
770+elif js_engine == 'mozjs'
771+ sources += files('polkitbackendjsauthority.cpp')
772+endif
773+
774 if enable_logind
775 sources += files('polkitbackendsessionmonitor-systemd.c')
776
777diff --git a/src/polkitbackend/polkitbackendcommon.c b/src/polkitbackend/polkitbackendcommon.c
778new file mode 100644
779index 0000000..6783dff
780--- /dev/null
781+++ b/src/polkitbackend/polkitbackendcommon.c
782@@ -0,0 +1,530 @@
783+/*
784+ * Copyright (C) 2008 Red Hat, Inc.
785+ *
786+ * This library is free software; you can redistribute it and/or
787+ * modify it under the terms of the GNU Lesser General Public
788+ * License as published by the Free Software Foundation; either
789+ * version 2 of the License, or (at your option) any later version.
790+ *
791+ * This library is distributed in the hope that it will be useful,
792+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
793+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
794+ * Lesser General Public License for more details.
795+ *
796+ * You should have received a copy of the GNU Lesser General
797+ * Public License along with this library; if not, write to the
798+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
799+ * Boston, MA 02111-1307, USA.
800+ *
801+ * Author: David Zeuthen <davidz@redhat.com>
802+ */
803+
804+#include "polkitbackendcommon.h"
805+
806+static void
807+utils_child_watch_from_release_cb (GPid pid,
808+ gint status,
809+ gpointer user_data)
810+{
811+}
812+
813+static void
814+utils_spawn_data_free (UtilsSpawnData *data)
815+{
816+ if (data->timeout_source != NULL)
817+ {
818+ g_source_destroy (data->timeout_source);
819+ data->timeout_source = NULL;
820+ }
821+
822+ /* Nuke the child, if necessary */
823+ if (data->child_watch_source != NULL)
824+ {
825+ g_source_destroy (data->child_watch_source);
826+ data->child_watch_source = NULL;
827+ }
828+
829+ if (data->child_pid != 0)
830+ {
831+ GSource *source;
832+ kill (data->child_pid, SIGTERM);
833+ /* OK, we need to reap for the child ourselves - we don't want
834+ * to use waitpid() because that might block the calling
835+ * thread (the child might handle SIGTERM and use several
836+ * seconds for cleanup/rollback).
837+ *
838+ * So we use GChildWatch instead.
839+ *
840+ * Avoid taking a references to ourselves. but note that we need
841+ * to pass the GSource so we can nuke it once handled.
842+ */
843+ source = g_child_watch_source_new (data->child_pid);
844+ g_source_set_callback (source,
845+ (GSourceFunc) utils_child_watch_from_release_cb,
846+ source,
847+ (GDestroyNotify) g_source_destroy);
848+ g_source_attach (source, data->main_context);
849+ g_source_unref (source);
850+ data->child_pid = 0;
851+ }
852+
853+ if (data->child_stdout != NULL)
854+ {
855+ g_string_free (data->child_stdout, TRUE);
856+ data->child_stdout = NULL;
857+ }
858+
859+ if (data->child_stderr != NULL)
860+ {
861+ g_string_free (data->child_stderr, TRUE);
862+ data->child_stderr = NULL;
863+ }
864+
865+ if (data->child_stdout_channel != NULL)
866+ {
867+ g_io_channel_unref (data->child_stdout_channel);
868+ data->child_stdout_channel = NULL;
869+ }
870+ if (data->child_stderr_channel != NULL)
871+ {
872+ g_io_channel_unref (data->child_stderr_channel);
873+ data->child_stderr_channel = NULL;
874+ }
875+
876+ if (data->child_stdout_source != NULL)
877+ {
878+ g_source_destroy (data->child_stdout_source);
879+ data->child_stdout_source = NULL;
880+ }
881+ if (data->child_stderr_source != NULL)
882+ {
883+ g_source_destroy (data->child_stderr_source);
884+ data->child_stderr_source = NULL;
885+ }
886+
887+ if (data->child_stdout_fd != -1)
888+ {
889+ g_warn_if_fail (close (data->child_stdout_fd) == 0);
890+ data->child_stdout_fd = -1;
891+ }
892+ if (data->child_stderr_fd != -1)
893+ {
894+ g_warn_if_fail (close (data->child_stderr_fd) == 0);
895+ data->child_stderr_fd = -1;
896+ }
897+
898+ if (data->cancellable_handler_id > 0)
899+ {
900+ g_cancellable_disconnect (data->cancellable, data->cancellable_handler_id);
901+ data->cancellable_handler_id = 0;
902+ }
903+
904+ if (data->main_context != NULL)
905+ g_main_context_unref (data->main_context);
906+
907+ if (data->cancellable != NULL)
908+ g_object_unref (data->cancellable);
909+
910+ g_slice_free (UtilsSpawnData, data);
911+}
912+
913+/* called in the thread where @cancellable was cancelled */
914+static void
915+utils_on_cancelled (GCancellable *cancellable,
916+ gpointer user_data)
917+{
918+ UtilsSpawnData *data = (UtilsSpawnData *)user_data;
919+ GError *error;
920+
921+ error = NULL;
922+ g_warn_if_fail (g_cancellable_set_error_if_cancelled (cancellable, &error));
923+ g_simple_async_result_take_error (data->simple, error);
924+ g_simple_async_result_complete_in_idle (data->simple);
925+ g_object_unref (data->simple);
926+}
927+
928+static gboolean
929+utils_timeout_cb (gpointer user_data)
930+{
931+ UtilsSpawnData *data = (UtilsSpawnData *)user_data;
932+
933+ data->timed_out = TRUE;
934+
935+ /* ok, timeout is history, make sure we don't free it in spawn_data_free() */
936+ data->timeout_source = NULL;
937+
938+ /* we're done */
939+ g_simple_async_result_complete_in_idle (data->simple);
940+ g_object_unref (data->simple);
941+
942+ return FALSE; /* remove source */
943+}
944+
945+static void
946+utils_child_watch_cb (GPid pid,
947+ gint status,
948+ gpointer user_data)
949+{
950+ UtilsSpawnData *data = (UtilsSpawnData *)user_data;
951+ gchar *buf;
952+ gsize buf_size;
953+
954+ if (g_io_channel_read_to_end (data->child_stdout_channel, &buf, &buf_size, NULL) == G_IO_STATUS_NORMAL)
955+ {
956+ g_string_append_len (data->child_stdout, buf, buf_size);
957+ g_free (buf);
958+ }
959+ if (g_io_channel_read_to_end (data->child_stderr_channel, &buf, &buf_size, NULL) == G_IO_STATUS_NORMAL)
960+ {
961+ g_string_append_len (data->child_stderr, buf, buf_size);
962+ g_free (buf);
963+ }
964+
965+ data->exit_status = status;
966+
967+ /* ok, child watch is history, make sure we don't free it in spawn_data_free() */
968+ data->child_pid = 0;
969+ data->child_watch_source = NULL;
970+
971+ /* we're done */
972+ g_simple_async_result_complete_in_idle (data->simple);
973+ g_object_unref (data->simple);
974+}
975+
976+static gboolean
977+utils_read_child_stderr (GIOChannel *channel,
978+ GIOCondition condition,
979+ gpointer user_data)
980+{
981+ UtilsSpawnData *data = (UtilsSpawnData *)user_data;
982+ gchar buf[1024];
983+ gsize bytes_read;
984+
985+ g_io_channel_read_chars (channel, buf, sizeof buf, &bytes_read, NULL);
986+ g_string_append_len (data->child_stderr, buf, bytes_read);
987+ return TRUE;
988+}
989+
990+static gboolean
991+utils_read_child_stdout (GIOChannel *channel,
992+ GIOCondition condition,
993+ gpointer user_data)
994+{
995+ UtilsSpawnData *data = (UtilsSpawnData *)user_data;
996+ gchar buf[1024];
997+ gsize bytes_read;
998+
999+ g_io_channel_read_chars (channel, buf, sizeof buf, &bytes_read, NULL);
1000+ g_string_append_len (data->child_stdout, buf, bytes_read);
1001+ return TRUE;
1002+}
1003+
1004+void
1005+polkit_backend_common_spawn (const gchar *const *argv,
1006+ guint timeout_seconds,
1007+ GCancellable *cancellable,
1008+ GAsyncReadyCallback callback,
1009+ gpointer user_data)
1010+{
1011+ UtilsSpawnData *data;
1012+ GError *error;
1013+
1014+ data = g_slice_new0 (UtilsSpawnData);
1015+ data->timeout_seconds = timeout_seconds;
1016+ data->simple = g_simple_async_result_new (NULL,
1017+ callback,
1018+ user_data,
1019+ (gpointer*)polkit_backend_common_spawn);
1020+ data->main_context = g_main_context_get_thread_default ();
1021+ if (data->main_context != NULL)
1022+ g_main_context_ref (data->main_context);
1023+
1024+ data->cancellable = cancellable != NULL ? (GCancellable*)g_object_ref (cancellable) : NULL;
1025+
1026+ data->child_stdout = g_string_new (NULL);
1027+ data->child_stderr = g_string_new (NULL);
1028+ data->child_stdout_fd = -1;
1029+ data->child_stderr_fd = -1;
1030+
1031+ /* the life-cycle of UtilsSpawnData is tied to its GSimpleAsyncResult */
1032+ g_simple_async_result_set_op_res_gpointer (data->simple, data, (GDestroyNotify) utils_spawn_data_free);
1033+
1034+ error = NULL;
1035+ if (data->cancellable != NULL)
1036+ {
1037+ /* could already be cancelled */
1038+ error = NULL;
1039+ if (g_cancellable_set_error_if_cancelled (data->cancellable, &error))
1040+ {
1041+ g_simple_async_result_take_error (data->simple, error);
1042+ g_simple_async_result_complete_in_idle (data->simple);
1043+ g_object_unref (data->simple);
1044+ goto out;
1045+ }
1046+
1047+ data->cancellable_handler_id = g_cancellable_connect (data->cancellable,
1048+ G_CALLBACK (utils_on_cancelled),
1049+ data,
1050+ NULL);
1051+ }
1052+
1053+ error = NULL;
1054+ if (!g_spawn_async_with_pipes (NULL, /* working directory */
1055+ (gchar **) argv,
1056+ NULL, /* envp */
1057+ G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
1058+ NULL, /* child_setup */
1059+ NULL, /* child_setup's user_data */
1060+ &(data->child_pid),
1061+ NULL, /* gint *stdin_fd */
1062+ &(data->child_stdout_fd),
1063+ &(data->child_stderr_fd),
1064+ &error))
1065+ {
1066+ g_prefix_error (&error, "Error spawning: ");
1067+ g_simple_async_result_take_error (data->simple, error);
1068+ g_simple_async_result_complete_in_idle (data->simple);
1069+ g_object_unref (data->simple);
1070+ goto out;
1071+ }
1072+
1073+ if (timeout_seconds > 0)
1074+ {
1075+ data->timeout_source = g_timeout_source_new_seconds (timeout_seconds);
1076+ g_source_set_priority (data->timeout_source, G_PRIORITY_DEFAULT);
1077+ g_source_set_callback (data->timeout_source, utils_timeout_cb, data, NULL);
1078+ g_source_attach (data->timeout_source, data->main_context);
1079+ g_source_unref (data->timeout_source);
1080+ }
1081+
1082+ data->child_watch_source = g_child_watch_source_new (data->child_pid);
1083+ g_source_set_callback (data->child_watch_source, (GSourceFunc) utils_child_watch_cb, data, NULL);
1084+ g_source_attach (data->child_watch_source, data->main_context);
1085+ g_source_unref (data->child_watch_source);
1086+
1087+ data->child_stdout_channel = g_io_channel_unix_new (data->child_stdout_fd);
1088+ g_io_channel_set_flags (data->child_stdout_channel, G_IO_FLAG_NONBLOCK, NULL);
1089+ data->child_stdout_source = g_io_create_watch (data->child_stdout_channel, G_IO_IN);
1090+ g_source_set_callback (data->child_stdout_source, (GSourceFunc) utils_read_child_stdout, data, NULL);
1091+ g_source_attach (data->child_stdout_source, data->main_context);
1092+ g_source_unref (data->child_stdout_source);
1093+
1094+ data->child_stderr_channel = g_io_channel_unix_new (data->child_stderr_fd);
1095+ g_io_channel_set_flags (data->child_stderr_channel, G_IO_FLAG_NONBLOCK, NULL);
1096+ data->child_stderr_source = g_io_create_watch (data->child_stderr_channel, G_IO_IN);
1097+ g_source_set_callback (data->child_stderr_source, (GSourceFunc) utils_read_child_stderr, data, NULL);
1098+ g_source_attach (data->child_stderr_source, data->main_context);
1099+ g_source_unref (data->child_stderr_source);
1100+
1101+ out:
1102+ ;
1103+}
1104+
1105+void
1106+polkit_backend_common_on_dir_monitor_changed (GFileMonitor *monitor,
1107+ GFile *file,
1108+ GFile *other_file,
1109+ GFileMonitorEvent event_type,
1110+ gpointer user_data)
1111+{
1112+ PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (user_data);
1113+
1114+ /* TODO: maybe rate-limit so storms of events are collapsed into one with a 500ms resolution?
1115+ * Because when editing a file with emacs we get 4-8 events..
1116+ */
1117+
1118+ if (file != NULL)
1119+ {
1120+ gchar *name;
1121+
1122+ name = g_file_get_basename (file);
1123+
1124+ /* g_print ("event_type=%d file=%p name=%s\n", event_type, file, name); */
1125+ if (!g_str_has_prefix (name, ".") &&
1126+ !g_str_has_prefix (name, "#") &&
1127+ g_str_has_suffix (name, ".rules") &&
1128+ (event_type == G_FILE_MONITOR_EVENT_CREATED ||
1129+ event_type == G_FILE_MONITOR_EVENT_DELETED ||
1130+ event_type == G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT))
1131+ {
1132+ polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
1133+ "Reloading rules");
1134+ polkit_backend_common_reload_scripts (authority);
1135+ }
1136+ g_free (name);
1137+ }
1138+}
1139+
1140+gboolean
1141+polkit_backend_common_spawn_finish (GAsyncResult *res,
1142+ gint *out_exit_status,
1143+ gchar **out_standard_output,
1144+ gchar **out_standard_error,
1145+ GError **error)
1146+{
1147+ GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
1148+ UtilsSpawnData *data;
1149+ gboolean ret = FALSE;
1150+
1151+ g_return_val_if_fail (G_IS_ASYNC_RESULT (res), FALSE);
1152+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1153+
1154+ g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == polkit_backend_common_spawn);
1155+
1156+ if (g_simple_async_result_propagate_error (simple, error))
1157+ goto out;
1158+
1159+ data = (UtilsSpawnData*)g_simple_async_result_get_op_res_gpointer (simple);
1160+
1161+ if (data->timed_out)
1162+ {
1163+ g_set_error (error,
1164+ G_IO_ERROR,
1165+ G_IO_ERROR_TIMED_OUT,
1166+ "Timed out after %d seconds",
1167+ data->timeout_seconds);
1168+ goto out;
1169+ }
1170+
1171+ if (out_exit_status != NULL)
1172+ *out_exit_status = data->exit_status;
1173+
1174+ if (out_standard_output != NULL)
1175+ *out_standard_output = g_strdup (data->child_stdout->str);
1176+
1177+ if (out_standard_error != NULL)
1178+ *out_standard_error = g_strdup (data->child_stderr->str);
1179+
1180+ ret = TRUE;
1181+
1182+ out:
1183+ return ret;
1184+}
1185+
1186+static const gchar *
1187+polkit_backend_js_authority_get_name (PolkitBackendAuthority *authority)
1188+{
1189+ return "js";
1190+}
1191+
1192+static const gchar *
1193+polkit_backend_js_authority_get_version (PolkitBackendAuthority *authority)
1194+{
1195+ return PACKAGE_VERSION;
1196+}
1197+
1198+static PolkitAuthorityFeatures
1199+polkit_backend_js_authority_get_features (PolkitBackendAuthority *authority)
1200+{
1201+ return POLKIT_AUTHORITY_FEATURES_TEMPORARY_AUTHORIZATION;
1202+}
1203+
1204+void
1205+polkit_backend_common_js_authority_class_init_common (PolkitBackendJsAuthorityClass *klass)
1206+{
1207+ GObjectClass *gobject_class;
1208+ PolkitBackendAuthorityClass *authority_class;
1209+ PolkitBackendInteractiveAuthorityClass *interactive_authority_class;
1210+
1211+ gobject_class = G_OBJECT_CLASS (klass);
1212+ gobject_class->finalize = polkit_backend_common_js_authority_finalize;
1213+ gobject_class->set_property = polkit_backend_common_js_authority_set_property;
1214+ gobject_class->constructed = polkit_backend_common_js_authority_constructed;
1215+
1216+ authority_class = POLKIT_BACKEND_AUTHORITY_CLASS (klass);
1217+ authority_class->get_name = polkit_backend_js_authority_get_name;
1218+ authority_class->get_version = polkit_backend_js_authority_get_version;
1219+ authority_class->get_features = polkit_backend_js_authority_get_features;
1220+
1221+ interactive_authority_class = POLKIT_BACKEND_INTERACTIVE_AUTHORITY_CLASS (klass);
1222+ interactive_authority_class->get_admin_identities = polkit_backend_common_js_authority_get_admin_auth_identities;
1223+ interactive_authority_class->check_authorization_sync = polkit_backend_common_js_authority_check_authorization_sync;
1224+
1225+ g_object_class_install_property (gobject_class,
1226+ PROP_RULES_DIRS,
1227+ g_param_spec_boxed ("rules-dirs",
1228+ NULL,
1229+ NULL,
1230+ G_TYPE_STRV,
1231+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE));
1232+}
1233+
1234+gint
1235+polkit_backend_common_rules_file_name_cmp (const gchar *a,
1236+ const gchar *b)
1237+{
1238+ gint ret;
1239+ const gchar *a_base;
1240+ const gchar *b_base;
1241+
1242+ a_base = strrchr (a, '/');
1243+ b_base = strrchr (b, '/');
1244+
1245+ g_assert (a_base != NULL);
1246+ g_assert (b_base != NULL);
1247+ a_base += 1;
1248+ b_base += 1;
1249+
1250+ ret = g_strcmp0 (a_base, b_base);
1251+ if (ret == 0)
1252+ {
1253+ /* /etc wins over /usr */
1254+ ret = g_strcmp0 (a, b);
1255+ g_assert (ret != 0);
1256+ }
1257+
1258+ return ret;
1259+}
1260+
1261+const gchar *
1262+polkit_backend_common_get_signal_name (gint signal_number)
1263+{
1264+ switch (signal_number)
1265+ {
1266+#define _HANDLE_SIG(sig) case sig: return #sig;
1267+ _HANDLE_SIG (SIGHUP);
1268+ _HANDLE_SIG (SIGINT);
1269+ _HANDLE_SIG (SIGQUIT);
1270+ _HANDLE_SIG (SIGILL);
1271+ _HANDLE_SIG (SIGABRT);
1272+ _HANDLE_SIG (SIGFPE);
1273+ _HANDLE_SIG (SIGKILL);
1274+ _HANDLE_SIG (SIGSEGV);
1275+ _HANDLE_SIG (SIGPIPE);
1276+ _HANDLE_SIG (SIGALRM);
1277+ _HANDLE_SIG (SIGTERM);
1278+ _HANDLE_SIG (SIGUSR1);
1279+ _HANDLE_SIG (SIGUSR2);
1280+ _HANDLE_SIG (SIGCHLD);
1281+ _HANDLE_SIG (SIGCONT);
1282+ _HANDLE_SIG (SIGSTOP);
1283+ _HANDLE_SIG (SIGTSTP);
1284+ _HANDLE_SIG (SIGTTIN);
1285+ _HANDLE_SIG (SIGTTOU);
1286+ _HANDLE_SIG (SIGBUS);
1287+#ifdef SIGPOLL
1288+ _HANDLE_SIG (SIGPOLL);
1289+#endif
1290+ _HANDLE_SIG (SIGPROF);
1291+ _HANDLE_SIG (SIGSYS);
1292+ _HANDLE_SIG (SIGTRAP);
1293+ _HANDLE_SIG (SIGURG);
1294+ _HANDLE_SIG (SIGVTALRM);
1295+ _HANDLE_SIG (SIGXCPU);
1296+ _HANDLE_SIG (SIGXFSZ);
1297+#undef _HANDLE_SIG
1298+ default:
1299+ break;
1300+ }
1301+ return "UNKNOWN_SIGNAL";
1302+}
1303+
1304+void
1305+polkit_backend_common_spawn_cb (GObject *source_object,
1306+ GAsyncResult *res,
1307+ gpointer user_data)
1308+{
1309+ SpawnData *data = (SpawnData *)user_data;
1310+ data->res = (GAsyncResult*)g_object_ref (res);
1311+ g_main_loop_quit (data->loop);
1312+}
1313diff --git a/src/polkitbackend/polkitbackendcommon.h b/src/polkitbackend/polkitbackendcommon.h
1314new file mode 100644
1315index 0000000..dd700fc
1316--- /dev/null
1317+++ b/src/polkitbackend/polkitbackendcommon.h
1318@@ -0,0 +1,158 @@
1319+/*
1320+ * Copyright (C) 2008 Red Hat, Inc.
1321+ *
1322+ * This library is free software; you can redistribute it and/or
1323+ * modify it under the terms of the GNU Lesser General Public
1324+ * License as published by the Free Software Foundation; either
1325+ * version 2 of the License, or (at your option) any later version.
1326+ *
1327+ * This library is distributed in the hope that it will be useful,
1328+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1329+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1330+ * Lesser General Public License for more details.
1331+ *
1332+ * You should have received a copy of the GNU Lesser General
1333+ * Public License along with this library; if not, write to the
1334+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
1335+ * Boston, MA 02111-1307, USA.
1336+ *
1337+ * Author: David Zeuthen <davidz@redhat.com>
1338+ */
1339+
1340+#if !defined (_POLKIT_BACKEND_COMPILATION) && !defined(_POLKIT_BACKEND_INSIDE_POLKIT_BACKEND_H)
1341+#error "Only <polkitbackend/polkitbackend.h> can be included directly, this file may disappear or change contents."
1342+#endif
1343+
1344+#ifndef __POLKIT_BACKEND_COMMON_H
1345+#define __POLKIT_BACKEND_COMMON_H
1346+
1347+#include "config.h"
1348+#include <sys/wait.h>
1349+#include <errno.h>
1350+#include <pwd.h>
1351+#include <grp.h>
1352+#ifdef HAVE_NETGROUP_H
1353+#include <netgroup.h>
1354+#else
1355+#include <netdb.h>
1356+#endif
1357+#include <string.h>
1358+#include <glib/gstdio.h>
1359+#include <locale.h>
1360+#include <glib/gi18n-lib.h> //here, all things glib via glib.h (including -> gspawn.h)
1361+
1362+#include <polkit/polkit.h>
1363+#include "polkitbackendjsauthority.h"
1364+
1365+#include <polkit/polkitprivate.h>
1366+
1367+#ifdef HAVE_LIBSYSTEMD
1368+#include <systemd/sd-login.h>
1369+#endif /* HAVE_LIBSYSTEMD */
1370+
1371+#define RUNAWAY_KILLER_TIMEOUT (15)
1372+
1373+#ifdef __cplusplus
1374+extern "C" {
1375+#endif
1376+
1377+enum
1378+{
1379+ PROP_0,
1380+ PROP_RULES_DIRS,
1381+};
1382+
1383+typedef struct
1384+{
1385+ GSimpleAsyncResult *simple; /* borrowed reference */
1386+ GMainContext *main_context; /* may be NULL */
1387+
1388+ GCancellable *cancellable; /* may be NULL */
1389+ gulong cancellable_handler_id;
1390+
1391+ GPid child_pid;
1392+ gint child_stdout_fd;
1393+ gint child_stderr_fd;
1394+
1395+ GIOChannel *child_stdout_channel;
1396+ GIOChannel *child_stderr_channel;
1397+
1398+ GSource *child_watch_source;
1399+ GSource *child_stdout_source;
1400+ GSource *child_stderr_source;
1401+
1402+ guint timeout_seconds;
1403+ gboolean timed_out;
1404+ GSource *timeout_source;
1405+
1406+ GString *child_stdout;
1407+ GString *child_stderr;
1408+
1409+ gint exit_status;
1410+} UtilsSpawnData;
1411+
1412+typedef struct
1413+{
1414+ GMainLoop *loop;
1415+ GAsyncResult *res;
1416+} SpawnData;
1417+
1418+void polkit_backend_common_spawn (const gchar *const *argv,
1419+ guint timeout_seconds,
1420+ GCancellable *cancellable,
1421+ GAsyncReadyCallback callback,
1422+ gpointer user_data);
1423+void polkit_backend_common_spawn_cb (GObject *source_object,
1424+ GAsyncResult *res,
1425+ gpointer user_data);
1426+gboolean polkit_backend_common_spawn_finish (GAsyncResult *res,
1427+ gint *out_exit_status,
1428+ gchar **out_standard_output,
1429+ gchar **out_standard_error,
1430+ GError **error);
1431+
1432+void polkit_backend_common_on_dir_monitor_changed (GFileMonitor *monitor,
1433+ GFile *file,
1434+ GFile *other_file,
1435+ GFileMonitorEvent event_type,
1436+ gpointer user_data);
1437+
1438+void polkit_backend_common_js_authority_class_init_common (PolkitBackendJsAuthorityClass *klass);
1439+
1440+gint polkit_backend_common_rules_file_name_cmp (const gchar *a,
1441+ const gchar *b);
1442+
1443+const gchar *polkit_backend_common_get_signal_name (gint signal_number);
1444+
1445+/* To be provided by each JS backend, from here onwards ---------------------------------------------- */
1446+
1447+void polkit_backend_common_reload_scripts (PolkitBackendJsAuthority *authority);
1448+void polkit_backend_common_js_authority_finalize (GObject *object);
1449+void polkit_backend_common_js_authority_constructed (GObject *object);
1450+GList *polkit_backend_common_js_authority_get_admin_auth_identities (PolkitBackendInteractiveAuthority *_authority,
1451+ PolkitSubject *caller,
1452+ PolkitSubject *subject,
1453+ PolkitIdentity *user_for_subject,
1454+ gboolean subject_is_local,
1455+ gboolean subject_is_active,
1456+ const gchar *action_id,
1457+ PolkitDetails *details);
1458+void polkit_backend_common_js_authority_set_property (GObject *object,
1459+ guint property_id,
1460+ const GValue *value,
1461+ GParamSpec *pspec);
1462+PolkitImplicitAuthorization polkit_backend_common_js_authority_check_authorization_sync (PolkitBackendInteractiveAuthority *_authority,
1463+ PolkitSubject *caller,
1464+ PolkitSubject *subject,
1465+ PolkitIdentity *user_for_subject,
1466+ gboolean subject_is_local,
1467+ gboolean subject_is_active,
1468+ const gchar *action_id,
1469+ PolkitDetails *details,
1470+ PolkitImplicitAuthorization implicit);
1471+#ifdef __cplusplus
1472+}
1473+#endif
1474+
1475+#endif /* __POLKIT_BACKEND_COMMON_H */
1476+
1477diff --git a/src/polkitbackend/polkitbackendduktapeauthority.c b/src/polkitbackend/polkitbackendduktapeauthority.c
1478new file mode 100644
1479index 0000000..c89dbcf
1480--- /dev/null
1481+++ b/src/polkitbackend/polkitbackendduktapeauthority.c
1482@@ -0,0 +1,1051 @@
1483+/*
1484+ * Copyright (C) 2008-2012 Red Hat, Inc.
1485+ * Copyright (C) 2015 Tangent Space <jstpierre@mecheye.net>
1486+ * Copyright (C) 2019 Wu Xiaotian <yetist@gmail.com>
1487+ *
1488+ * This library is free software; you can redistribute it and/or
1489+ * modify it under the terms of the GNU Lesser General Public
1490+ * License as published by the Free Software Foundation; either
1491+ * version 2 of the License, or (at your option) any later version.
1492+ *
1493+ * This library is distributed in the hope that it will be useful,
1494+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1495+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1496+ * Lesser General Public License for more details.
1497+ *
1498+ * You should have received a copy of the GNU Lesser General
1499+ * Public License along with this library; if not, write to the
1500+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
1501+ * Boston, MA 02111-1307, USA.
1502+ *
1503+ * Author: David Zeuthen <davidz@redhat.com>
1504+ */
1505+
1506+#include <pthread.h>
1507+
1508+#include "polkitbackendcommon.h"
1509+
1510+#include "duktape.h"
1511+
1512+/* Built source and not too big to worry about deduplication */
1513+#include "initjs.h" /* init.js */
1514+
1515+/**
1516+ * SECTION:polkitbackendjsauthority
1517+ * @title: PolkitBackendJsAuthority
1518+ * @short_description: JS Authority
1519+ * @stability: Unstable
1520+ *
1521+ * An (Duktape-based) implementation of #PolkitBackendAuthority that reads and
1522+ * evaluates Javascript files and supports interaction with authentication
1523+ * agents (virtue of being based on #PolkitBackendInteractiveAuthority).
1524+ */
1525+
1526+/* ---------------------------------------------------------------------------------------------------- */
1527+
1528+struct _PolkitBackendJsAuthorityPrivate
1529+{
1530+ gchar **rules_dirs;
1531+ GFileMonitor **dir_monitors; /* NULL-terminated array of GFileMonitor instances */
1532+
1533+ duk_context *cx;
1534+
1535+ pthread_t runaway_killer_thread;
1536+};
1537+
1538+enum
1539+{
1540+ RUNAWAY_KILLER_THREAD_EXIT_STATUS_UNSET,
1541+ RUNAWAY_KILLER_THREAD_EXIT_STATUS_SUCCESS,
1542+ RUNAWAY_KILLER_THREAD_EXIT_STATUS_FAILURE,
1543+};
1544+
1545+static gboolean execute_script_with_runaway_killer(PolkitBackendJsAuthority *authority,
1546+ const gchar *filename);
1547+
1548+/* ---------------------------------------------------------------------------------------------------- */
1549+
1550+G_DEFINE_TYPE (PolkitBackendJsAuthority, polkit_backend_js_authority, POLKIT_BACKEND_TYPE_INTERACTIVE_AUTHORITY);
1551+
1552+/* ---------------------------------------------------------------------------------------------------- */
1553+
1554+static duk_ret_t js_polkit_log (duk_context *cx);
1555+static duk_ret_t js_polkit_spawn (duk_context *cx);
1556+static duk_ret_t js_polkit_user_is_in_netgroup (duk_context *cx);
1557+
1558+static const duk_function_list_entry js_polkit_functions[] =
1559+{
1560+ { "log", js_polkit_log, 1 },
1561+ { "spawn", js_polkit_spawn, 1 },
1562+ { "_userIsInNetGroup", js_polkit_user_is_in_netgroup, 2 },
1563+ { NULL, NULL, 0 },
1564+};
1565+
1566+static void report_error (void *udata,
1567+ const char *msg)
1568+{
1569+ PolkitBackendJsAuthority *authority = udata;
1570+ polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
1571+ "fatal Duktape JS backend error: %s",
1572+ (msg ? msg : "no message"));
1573+}
1574+
1575+static void
1576+polkit_backend_js_authority_init (PolkitBackendJsAuthority *authority)
1577+{
1578+ authority->priv = G_TYPE_INSTANCE_GET_PRIVATE (authority,
1579+ POLKIT_BACKEND_TYPE_JS_AUTHORITY,
1580+ PolkitBackendJsAuthorityPrivate);
1581+}
1582+
1583+static void
1584+load_scripts (PolkitBackendJsAuthority *authority)
1585+{
1586+ GList *files = NULL;
1587+ GList *l;
1588+ guint num_scripts = 0;
1589+ GError *error = NULL;
1590+ guint n;
1591+
1592+ files = NULL;
1593+
1594+ for (n = 0; authority->priv->rules_dirs != NULL && authority->priv->rules_dirs[n] != NULL; n++)
1595+ {
1596+ const gchar *dir_name = authority->priv->rules_dirs[n];
1597+ GDir *dir = NULL;
1598+
1599+ polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
1600+ "Loading rules from directory %s",
1601+ dir_name);
1602+
1603+ dir = g_dir_open (dir_name,
1604+ 0,
1605+ &error);
1606+ if (dir == NULL)
1607+ {
1608+ polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
1609+ "Error opening rules directory: %s (%s, %d)",
1610+ error->message, g_quark_to_string (error->domain), error->code);
1611+ g_clear_error (&error);
1612+ }
1613+ else
1614+ {
1615+ const gchar *name;
1616+ while ((name = g_dir_read_name (dir)) != NULL)
1617+ {
1618+ if (g_str_has_suffix (name, ".rules"))
1619+ files = g_list_prepend (files, g_strdup_printf ("%s/%s", dir_name, name));
1620+ }
1621+ g_dir_close (dir);
1622+ }
1623+ }
1624+
1625+ files = g_list_sort (files, (GCompareFunc) polkit_backend_common_rules_file_name_cmp);
1626+
1627+ for (l = files; l != NULL; l = l->next)
1628+ {
1629+ const gchar *filename = (gchar *)l->data;
1630+
1631+ if (!execute_script_with_runaway_killer(authority, filename))
1632+ continue;
1633+ num_scripts++;
1634+ }
1635+
1636+ polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
1637+ "Finished loading, compiling and executing %d rules",
1638+ num_scripts);
1639+ g_list_free_full (files, g_free);
1640+}
1641+
1642+void
1643+polkit_backend_common_reload_scripts (PolkitBackendJsAuthority *authority)
1644+{
1645+ duk_context *cx = authority->priv->cx;
1646+
1647+ duk_set_top (cx, 0);
1648+ if (!duk_get_global_string (cx, "polkit")) {
1649+ polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
1650+ "Error deleting old rules, not loading new ones");
1651+ return;
1652+ }
1653+ duk_push_string (cx, "_deleteRules");
1654+
1655+ duk_call_prop (cx, 0, 0);
1656+
1657+ polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
1658+ "Collecting garbage unconditionally...");
1659+
1660+ load_scripts (authority);
1661+
1662+ /* Let applications know we have new rules... */
1663+ g_signal_emit_by_name (authority, "changed");
1664+}
1665+
1666+static void
1667+setup_file_monitors (PolkitBackendJsAuthority *authority)
1668+{
1669+ guint n;
1670+ GPtrArray *p;
1671+
1672+ p = g_ptr_array_new ();
1673+ for (n = 0; authority->priv->rules_dirs != NULL && authority->priv->rules_dirs[n] != NULL; n++)
1674+ {
1675+ GFile *file;
1676+ GError *error;
1677+ GFileMonitor *monitor;
1678+
1679+ file = g_file_new_for_path (authority->priv->rules_dirs[n]);
1680+ error = NULL;
1681+ monitor = g_file_monitor_directory (file,
1682+ G_FILE_MONITOR_NONE,
1683+ NULL,
1684+ &error);
1685+ g_object_unref (file);
1686+ if (monitor == NULL)
1687+ {
1688+ g_warning ("Error monitoring directory %s: %s",
1689+ authority->priv->rules_dirs[n],
1690+ error->message);
1691+ g_clear_error (&error);
1692+ }
1693+ else
1694+ {
1695+ g_signal_connect (monitor,
1696+ "changed",
1697+ G_CALLBACK (polkit_backend_common_on_dir_monitor_changed),
1698+ authority);
1699+ g_ptr_array_add (p, monitor);
1700+ }
1701+ }
1702+ g_ptr_array_add (p, NULL);
1703+ authority->priv->dir_monitors = (GFileMonitor**) g_ptr_array_free (p, FALSE);
1704+}
1705+
1706+void
1707+polkit_backend_common_js_authority_constructed (GObject *object)
1708+{
1709+ PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (object);
1710+ duk_context *cx;
1711+
1712+ cx = duk_create_heap (NULL, NULL, NULL, authority, report_error);
1713+ if (cx == NULL)
1714+ goto fail;
1715+
1716+ authority->priv->cx = cx;
1717+
1718+ duk_push_global_object (cx);
1719+ duk_push_object (cx);
1720+ duk_put_function_list (cx, -1, js_polkit_functions);
1721+ duk_put_prop_string (cx, -2, "polkit");
1722+
1723+ /* load polkit objects/functions into JS context (e.g. addRule(),
1724+ * _deleteRules(), _runRules() et al)
1725+ */
1726+ duk_eval_string (cx, init_js);
1727+
1728+ if (authority->priv->rules_dirs == NULL)
1729+ {
1730+ authority->priv->rules_dirs = g_new0 (gchar *, 3);
1731+ authority->priv->rules_dirs[0] = g_strdup (PACKAGE_SYSCONF_DIR "/polkit-1/rules.d");
1732+ authority->priv->rules_dirs[1] = g_strdup (PACKAGE_DATA_DIR "/polkit-1/rules.d");
1733+ }
1734+
1735+ setup_file_monitors (authority);
1736+ load_scripts (authority);
1737+
1738+ G_OBJECT_CLASS (polkit_backend_js_authority_parent_class)->constructed (object);
1739+ return;
1740+
1741+ fail:
1742+ g_critical ("Error initializing JavaScript environment");
1743+ g_assert_not_reached ();
1744+}
1745+
1746+void
1747+polkit_backend_common_js_authority_finalize (GObject *object)
1748+{
1749+ PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (object);
1750+ guint n;
1751+
1752+ for (n = 0; authority->priv->dir_monitors != NULL && authority->priv->dir_monitors[n] != NULL; n++)
1753+ {
1754+ GFileMonitor *monitor = authority->priv->dir_monitors[n];
1755+ g_signal_handlers_disconnect_by_func (monitor,
1756+ G_CALLBACK (polkit_backend_common_on_dir_monitor_changed),
1757+ authority);
1758+ g_object_unref (monitor);
1759+ }
1760+ g_free (authority->priv->dir_monitors);
1761+ g_strfreev (authority->priv->rules_dirs);
1762+
1763+ duk_destroy_heap (authority->priv->cx);
1764+
1765+ G_OBJECT_CLASS (polkit_backend_js_authority_parent_class)->finalize (object);
1766+}
1767+
1768+void
1769+polkit_backend_common_js_authority_set_property (GObject *object,
1770+ guint property_id,
1771+ const GValue *value,
1772+ GParamSpec *pspec)
1773+{
1774+ PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (object);
1775+
1776+ switch (property_id)
1777+ {
1778+ case PROP_RULES_DIRS:
1779+ g_assert (authority->priv->rules_dirs == NULL);
1780+ authority->priv->rules_dirs = (gchar **) g_value_dup_boxed (value);
1781+ break;
1782+
1783+ default:
1784+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1785+ break;
1786+ }
1787+}
1788+
1789+static void
1790+polkit_backend_js_authority_class_init (PolkitBackendJsAuthorityClass *klass)
1791+{
1792+ polkit_backend_common_js_authority_class_init_common (klass);
1793+ g_type_class_add_private (klass, sizeof (PolkitBackendJsAuthorityPrivate));
1794+}
1795+
1796+/* ---------------------------------------------------------------------------------------------------- */
1797+
1798+static void
1799+set_property_str (duk_context *cx,
1800+ const gchar *name,
1801+ const gchar *value)
1802+{
1803+ duk_push_string (cx, value);
1804+ duk_put_prop_string (cx, -2, name);
1805+}
1806+
1807+static void
1808+set_property_strv (duk_context *cx,
1809+ const gchar *name,
1810+ GPtrArray *value)
1811+{
1812+ guint n;
1813+ duk_push_array (cx);
1814+ for (n = 0; n < value->len; n++)
1815+ {
1816+ duk_push_string (cx, g_ptr_array_index (value, n));
1817+ duk_put_prop_index (cx, -2, n);
1818+ }
1819+ duk_put_prop_string (cx, -2, name);
1820+}
1821+
1822+static void
1823+set_property_int32 (duk_context *cx,
1824+ const gchar *name,
1825+ gint32 value)
1826+{
1827+ duk_push_int (cx, value);
1828+ duk_put_prop_string (cx, -2, name);
1829+}
1830+
1831+static void
1832+set_property_bool (duk_context *cx,
1833+ const char *name,
1834+ gboolean value)
1835+{
1836+ duk_push_boolean (cx, value);
1837+ duk_put_prop_string (cx, -2, name);
1838+}
1839+
1840+/* ---------------------------------------------------------------------------------------------------- */
1841+
1842+static gboolean
1843+push_subject (duk_context *cx,
1844+ PolkitSubject *subject,
1845+ PolkitIdentity *user_for_subject,
1846+ gboolean subject_is_local,
1847+ gboolean subject_is_active,
1848+ GError **error)
1849+{
1850+ gboolean ret = FALSE;
1851+ pid_t pid;
1852+ uid_t uid;
1853+ gchar *user_name = NULL;
1854+ GPtrArray *groups = NULL;
1855+ struct passwd *passwd;
1856+ char *seat_str = NULL;
1857+ char *session_str = NULL;
1858+
1859+ if (!duk_get_global_string (cx, "Subject")) {
1860+ return FALSE;
1861+ }
1862+
1863+ duk_new (cx, 0);
1864+
1865+ if (POLKIT_IS_UNIX_PROCESS (subject))
1866+ {
1867+ pid = polkit_unix_process_get_pid (POLKIT_UNIX_PROCESS (subject));
1868+ }
1869+ else if (POLKIT_IS_SYSTEM_BUS_NAME (subject))
1870+ {
1871+ PolkitSubject *process;
1872+ process = polkit_system_bus_name_get_process_sync (POLKIT_SYSTEM_BUS_NAME (subject), NULL, error);
1873+ if (process == NULL)
1874+ goto out;
1875+ pid = polkit_unix_process_get_pid (POLKIT_UNIX_PROCESS (process));
1876+ g_object_unref (process);
1877+ }
1878+ else
1879+ {
1880+ g_assert_not_reached ();
1881+ }
1882+
1883+#ifdef HAVE_LIBSYSTEMD
1884+ if (sd_pid_get_session (pid, &session_str) == 0)
1885+ {
1886+ if (sd_session_get_seat (session_str, &seat_str) == 0)
1887+ {
1888+ /* do nothing */
1889+ }
1890+ }
1891+#endif /* HAVE_LIBSYSTEMD */
1892+
1893+ g_assert (POLKIT_IS_UNIX_USER (user_for_subject));
1894+ uid = polkit_unix_user_get_uid (POLKIT_UNIX_USER (user_for_subject));
1895+
1896+ groups = g_ptr_array_new_with_free_func (g_free);
1897+
1898+ passwd = getpwuid (uid);
1899+ if (passwd == NULL)
1900+ {
1901+ user_name = g_strdup_printf ("%d", (gint) uid);
1902+ g_warning ("Error looking up info for uid %d: %m", (gint) uid);
1903+ }
1904+ else
1905+ {
1906+ gid_t gids[512];
1907+ int num_gids = 512;
1908+
1909+ user_name = g_strdup (passwd->pw_name);
1910+
1911+ if (getgrouplist (passwd->pw_name,
1912+ passwd->pw_gid,
1913+ gids,
1914+ &num_gids) < 0)
1915+ {
1916+ g_warning ("Error looking up groups for uid %d: %m", (gint) uid);
1917+ }
1918+ else
1919+ {
1920+ gint n;
1921+ for (n = 0; n < num_gids; n++)
1922+ {
1923+ struct group *group;
1924+ group = getgrgid (gids[n]);
1925+ if (group == NULL)
1926+ {
1927+ g_ptr_array_add (groups, g_strdup_printf ("%d", (gint) gids[n]));
1928+ }
1929+ else
1930+ {
1931+ g_ptr_array_add (groups, g_strdup (group->gr_name));
1932+ }
1933+ }
1934+ }
1935+ }
1936+
1937+ set_property_int32 (cx, "pid", pid);
1938+ set_property_str (cx, "user", user_name);
1939+ set_property_strv (cx, "groups", groups);
1940+ set_property_str (cx, "seat", seat_str);
1941+ set_property_str (cx, "session", session_str);
1942+ set_property_bool (cx, "local", subject_is_local);
1943+ set_property_bool (cx, "active", subject_is_active);
1944+
1945+ ret = TRUE;
1946+
1947+ out:
1948+ free (session_str);
1949+ free (seat_str);
1950+ g_free (user_name);
1951+ if (groups != NULL)
1952+ g_ptr_array_unref (groups);
1953+
1954+ return ret;
1955+}
1956+
1957+/* ---------------------------------------------------------------------------------------------------- */
1958+
1959+static gboolean
1960+push_action_and_details (duk_context *cx,
1961+ const gchar *action_id,
1962+ PolkitDetails *details,
1963+ GError **error)
1964+{
1965+ gchar **keys;
1966+ guint n;
1967+
1968+ if (!duk_get_global_string (cx, "Action")) {
1969+ return FALSE;
1970+ }
1971+
1972+ duk_new (cx, 0);
1973+
1974+ set_property_str (cx, "id", action_id);
1975+
1976+ keys = polkit_details_get_keys (details);
1977+ for (n = 0; keys != NULL && keys[n] != NULL; n++)
1978+ {
1979+ gchar *key;
1980+ const gchar *value;
1981+ key = g_strdup_printf ("_detail_%s", keys[n]);
1982+ value = polkit_details_lookup (details, keys[n]);
1983+ set_property_str (cx, key, value);
1984+ g_free (key);
1985+ }
1986+ g_strfreev (keys);
1987+
1988+ return TRUE;
1989+}
1990+
1991+/* ---------------------------------------------------------------------------------------------------- */
1992+
1993+typedef struct {
1994+ PolkitBackendJsAuthority *authority;
1995+ const gchar *filename;
1996+ pthread_cond_t cond;
1997+ pthread_mutex_t mutex;
1998+ gint ret;
1999+} RunawayKillerCtx;
2000+
2001+static gpointer
2002+runaway_killer_thread_execute_js (gpointer user_data)
2003+{
2004+ RunawayKillerCtx *ctx = user_data;
2005+ duk_context *cx = ctx->authority->priv->cx;
2006+
2007+ int oldtype, pthread_err;
2008+
2009+ if ((pthread_err = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype))) {
2010+ polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (ctx->authority),
2011+ "Error setting thread cancel type: %s",
2012+ strerror(pthread_err));
2013+ goto err;
2014+ }
2015+
2016+ GFile *file = g_file_new_for_path(ctx->filename);
2017+ char *contents;
2018+ gsize len;
2019+
2020+ if (!g_file_load_contents(file, NULL, &contents, &len, NULL, NULL)) {
2021+ polkit_backend_authority_log(POLKIT_BACKEND_AUTHORITY(ctx->authority),
2022+ "Error loading script %s", ctx->filename);
2023+ g_object_unref(file);
2024+ goto err;
2025+ }
2026+
2027+ g_object_unref(file);
2028+
2029+ /* evaluate the script, trying to print context in any syntax errors
2030+ found */
2031+ if (duk_peval_lstring(cx, contents, len) != 0)
2032+ {
2033+ polkit_backend_authority_log(POLKIT_BACKEND_AUTHORITY(ctx->authority),
2034+ "Error compiling script %s: %s", ctx->filename,
2035+ duk_safe_to_string(cx, -1));
2036+ duk_pop(cx);
2037+ goto free_err;
2038+ }
2039+ g_free(contents);
2040+
2041+ ctx->ret = RUNAWAY_KILLER_THREAD_EXIT_STATUS_SUCCESS;
2042+ goto end;
2043+
2044+free_err:
2045+ g_free(contents);
2046+err:
2047+ ctx->ret = RUNAWAY_KILLER_THREAD_EXIT_STATUS_FAILURE;
2048+end:
2049+ if ((pthread_err = pthread_cond_signal(&ctx->cond))) {
2050+ polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (ctx->authority),
2051+ "Error signaling on condition variable: %s",
2052+ strerror(pthread_err));
2053+ ctx->ret = RUNAWAY_KILLER_THREAD_EXIT_STATUS_FAILURE;
2054+ }
2055+ return NULL;
2056+}
2057+
2058+static gpointer
2059+runaway_killer_thread_call_js (gpointer user_data)
2060+{
2061+ RunawayKillerCtx *ctx = user_data;
2062+ duk_context *cx = ctx->authority->priv->cx;
2063+ int oldtype, pthread_err;
2064+
2065+ if ((pthread_err = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype))) {
2066+ polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (ctx->authority),
2067+ "Error setting thread cancel type: %s",
2068+ strerror(pthread_err));
2069+ goto err;
2070+ }
2071+
2072+ if (duk_pcall_prop (cx, 0, 2) != DUK_EXEC_SUCCESS)
2073+ {
2074+ polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (ctx->authority),
2075+ "Error evaluating admin rules: ",
2076+ duk_safe_to_string (cx, -1));
2077+ goto err;
2078+ }
2079+
2080+ ctx->ret = RUNAWAY_KILLER_THREAD_EXIT_STATUS_SUCCESS;
2081+ goto end;
2082+
2083+err:
2084+ ctx->ret = RUNAWAY_KILLER_THREAD_EXIT_STATUS_FAILURE;
2085+end:
2086+ if ((pthread_err = pthread_cond_signal(&ctx->cond))) {
2087+ polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (ctx->authority),
2088+ "Error signaling on condition variable: %s",
2089+ strerror(pthread_err));
2090+ ctx->ret = RUNAWAY_KILLER_THREAD_EXIT_STATUS_FAILURE;
2091+ }
2092+ return NULL;
2093+}
2094+
2095+#if defined (HAVE_PTHREAD_CONDATTR_SETCLOCK)
2096+# if defined(CLOCK_MONOTONIC)
2097+# define PK_CLOCK CLOCK_MONOTONIC
2098+# elif defined(CLOCK_BOOTTIME)
2099+# define PK_CLOCK CLOCK_BOOTTIME
2100+# else
2101+ /* No suitable clock */
2102+# undef HAVE_PTHREAD_CONDATTR_SETCLOCK
2103+# define PK_CLOCK CLOCK_REALTIME
2104+# endif
2105+#else /* ! HAVE_PTHREAD_CONDATTR_SETCLOCK */
2106+# define PK_CLOCK CLOCK_REALTIME
2107+#endif /* ! HAVE_PTHREAD_CONDATTR_SETCLOCK */
2108+
2109+static gboolean
2110+runaway_killer_common(PolkitBackendJsAuthority *authority, RunawayKillerCtx *ctx, void *js_context_cb (void *user_data))
2111+{
2112+ int pthread_err;
2113+ gboolean cancel = FALSE;
2114+ pthread_condattr_t attr;
2115+ struct timespec abs_time;
2116+
2117+#ifdef HAVE_PTHREAD_CONDATTR_SETCLOCK
2118+ if ((pthread_err = pthread_condattr_init(&attr))) {
2119+ polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
2120+ "Error initializing condition variable attributes: %s",
2121+ strerror(pthread_err));
2122+ return FALSE;
2123+ }
2124+ if ((pthread_err = pthread_condattr_setclock(&attr, PK_CLOCK))) {
2125+ polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
2126+ "Error setting condition variable attributes: %s",
2127+ strerror(pthread_err));
2128+ goto err_clean_condattr;
2129+ }
2130+ /* Init again, with needed attr */
2131+ if ((pthread_err = pthread_cond_init(&ctx->cond, &attr))) {
2132+ polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
2133+ "Error initializing condition variable: %s",
2134+ strerror(pthread_err));
2135+ goto err_clean_condattr;
2136+ }
2137+#endif
2138+
2139+ if ((pthread_err = pthread_mutex_lock(&ctx->mutex))) {
2140+ polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
2141+ "Error locking mutex: %s",
2142+ strerror(pthread_err));
2143+ goto err_clean_cond;
2144+ }
2145+
2146+ if (clock_gettime(PK_CLOCK, &abs_time)) {
2147+ polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
2148+ "Error getting system's monotonic time: %s",
2149+ strerror(errno));
2150+ goto err_clean_cond;
2151+ }
2152+ abs_time.tv_sec += RUNAWAY_KILLER_TIMEOUT;
2153+
2154+ if ((pthread_err = pthread_create(&authority->priv->runaway_killer_thread, NULL,
2155+ js_context_cb, ctx))) {
2156+ polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
2157+ "Error creating runaway JS killer thread: %s",
2158+ strerror(pthread_err));
2159+ goto err_clean_cond;
2160+ }
2161+
2162+ while (ctx->ret == RUNAWAY_KILLER_THREAD_EXIT_STATUS_UNSET) /* loop to treat spurious wakeups */
2163+ if (pthread_cond_timedwait(&ctx->cond, &ctx->mutex, &abs_time) == ETIMEDOUT) {
2164+ cancel = TRUE;
2165+
2166+ /* Log that we are terminating the script */
2167+ polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
2168+ "Terminating runaway script after %d seconds",
2169+ RUNAWAY_KILLER_TIMEOUT);
2170+
2171+ break;
2172+ }
2173+
2174+ if ((pthread_err = pthread_mutex_unlock(&ctx->mutex))) {
2175+ polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
2176+ "Error unlocking mutex: %s",
2177+ strerror(pthread_err));
2178+ goto err_clean_cond;
2179+ }
2180+
2181+ if (cancel) {
2182+ if ((pthread_err = pthread_cancel (authority->priv->runaway_killer_thread))) {
2183+ polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
2184+ "Error cancelling runaway JS killer thread: %s",
2185+ strerror(pthread_err));
2186+ goto err_clean_cond;
2187+ }
2188+ }
2189+ if ((pthread_err = pthread_join (authority->priv->runaway_killer_thread, NULL))) {
2190+ polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
2191+ "Error joining runaway JS killer thread: %s",
2192+ strerror(pthread_err));
2193+ goto err_clean_cond;
2194+ }
2195+
2196+ return ctx->ret == RUNAWAY_KILLER_THREAD_EXIT_STATUS_SUCCESS;
2197+
2198+ err_clean_cond:
2199+#ifdef HAVE_PTHREAD_CONDATTR_SETCLOCK
2200+ pthread_cond_destroy(&ctx->cond);
2201+#endif
2202+ err_clean_condattr:
2203+#ifdef HAVE_PTHREAD_CONDATTR_SETCLOCK
2204+ pthread_condattr_destroy(&attr);
2205+#endif
2206+ return FALSE;
2207+}
2208+
2209+/* Blocking for at most RUNAWAY_KILLER_TIMEOUT */
2210+static gboolean
2211+execute_script_with_runaway_killer(PolkitBackendJsAuthority *authority,
2212+ const gchar *filename)
2213+{
2214+ RunawayKillerCtx ctx = {.authority = authority, .filename = filename,
2215+ .ret = RUNAWAY_KILLER_THREAD_EXIT_STATUS_UNSET,
2216+ .mutex = PTHREAD_MUTEX_INITIALIZER,
2217+ .cond = PTHREAD_COND_INITIALIZER};
2218+
2219+ return runaway_killer_common(authority, &ctx, &runaway_killer_thread_execute_js);
2220+}
2221+
2222+/* Calls already stacked function and args. Blocking for at most
2223+ * RUNAWAY_KILLER_TIMEOUT. If timeout is the case, ctx.ret will be
2224+ * RUNAWAY_KILLER_THREAD_EXIT_STATUS_UNSET, thus returning FALSE.
2225+ */
2226+static gboolean
2227+call_js_function_with_runaway_killer(PolkitBackendJsAuthority *authority)
2228+{
2229+ RunawayKillerCtx ctx = {.authority = authority,
2230+ .ret = RUNAWAY_KILLER_THREAD_EXIT_STATUS_UNSET,
2231+ .mutex = PTHREAD_MUTEX_INITIALIZER,
2232+ .cond = PTHREAD_COND_INITIALIZER};
2233+
2234+ return runaway_killer_common(authority, &ctx, &runaway_killer_thread_call_js);
2235+}
2236+
2237+/* ---------------------------------------------------------------------------------------------------- */
2238+
2239+GList *
2240+polkit_backend_common_js_authority_get_admin_auth_identities (PolkitBackendInteractiveAuthority *_authority,
2241+ PolkitSubject *caller,
2242+ PolkitSubject *subject,
2243+ PolkitIdentity *user_for_subject,
2244+ gboolean subject_is_local,
2245+ gboolean subject_is_active,
2246+ const gchar *action_id,
2247+ PolkitDetails *details)
2248+{
2249+ PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (_authority);
2250+ GList *ret = NULL;
2251+ guint n;
2252+ GError *error = NULL;
2253+ const char *ret_str = NULL;
2254+ gchar **ret_strs = NULL;
2255+ duk_context *cx = authority->priv->cx;
2256+
2257+ duk_set_top (cx, 0);
2258+ if (!duk_get_global_string (cx, "polkit")) {
2259+ polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
2260+ "Error deleting old rules, not loading new ones");
2261+ goto out;
2262+ }
2263+
2264+ duk_push_string (cx, "_runAdminRules");
2265+
2266+ if (!push_action_and_details (cx, action_id, details, &error))
2267+ {
2268+ polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
2269+ "Error converting action and details to JS object: %s",
2270+ error->message);
2271+ g_clear_error (&error);
2272+ goto out;
2273+ }
2274+
2275+ if (!push_subject (cx, subject, user_for_subject, subject_is_local, subject_is_active, &error))
2276+ {
2277+ polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
2278+ "Error converting subject to JS object: %s",
2279+ error->message);
2280+ g_clear_error (&error);
2281+ goto out;
2282+ }
2283+
2284+ if (!call_js_function_with_runaway_killer (authority))
2285+ goto out;
2286+
2287+ ret_str = duk_require_string (cx, -1);
2288+
2289+ ret_strs = g_strsplit (ret_str, ",", -1);
2290+ for (n = 0; ret_strs != NULL && ret_strs[n] != NULL; n++)
2291+ {
2292+ const gchar *identity_str = ret_strs[n];
2293+ PolkitIdentity *identity;
2294+
2295+ error = NULL;
2296+ identity = polkit_identity_from_string (identity_str, &error);
2297+ if (identity == NULL)
2298+ {
2299+ polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
2300+ "Identity `%s' is not valid, ignoring: %s",
2301+ identity_str, error->message);
2302+ g_clear_error (&error);
2303+ }
2304+ else
2305+ {
2306+ ret = g_list_prepend (ret, identity);
2307+ }
2308+ }
2309+ ret = g_list_reverse (ret);
2310+
2311+ out:
2312+ g_strfreev (ret_strs);
2313+ /* fallback to root password auth */
2314+ if (ret == NULL)
2315+ ret = g_list_prepend (ret, polkit_unix_user_new (0));
2316+
2317+ return ret;
2318+}
2319+
2320+/* ---------------------------------------------------------------------------------------------------- */
2321+
2322+PolkitImplicitAuthorization
2323+polkit_backend_common_js_authority_check_authorization_sync (PolkitBackendInteractiveAuthority *_authority,
2324+ PolkitSubject *caller,
2325+ PolkitSubject *subject,
2326+ PolkitIdentity *user_for_subject,
2327+ gboolean subject_is_local,
2328+ gboolean subject_is_active,
2329+ const gchar *action_id,
2330+ PolkitDetails *details,
2331+ PolkitImplicitAuthorization implicit)
2332+{
2333+ PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (_authority);
2334+ PolkitImplicitAuthorization ret = implicit;
2335+ GError *error = NULL;
2336+ gchar *ret_str = NULL;
2337+ gboolean good = FALSE;
2338+ duk_context *cx = authority->priv->cx;
2339+
2340+ duk_set_top (cx, 0);
2341+ if (!duk_get_global_string (cx, "polkit")) {
2342+ goto out;
2343+ }
2344+
2345+ duk_push_string (cx, "_runRules");
2346+
2347+ if (!push_action_and_details (cx, action_id, details, &error))
2348+ {
2349+ polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
2350+ "Error converting action and details to JS object: %s",
2351+ error->message);
2352+ g_clear_error (&error);
2353+ goto out;
2354+ }
2355+
2356+ if (!push_subject (cx, subject, user_for_subject, subject_is_local, subject_is_active, &error))
2357+ {
2358+ polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
2359+ "Error converting subject to JS object: %s",
2360+ error->message);
2361+ g_clear_error (&error);
2362+ goto out;
2363+ }
2364+
2365+ // If any error is the js context happened (ctx.ret ==
2366+ // RUNAWAY_KILLER_THREAD_EXIT_STATUS_FAILURE) or it never properly returned
2367+ // (runaway scripts or ctx.ret == RUNAWAY_KILLER_THREAD_EXIT_STATUS_UNSET),
2368+ // unauthorize
2369+ if (!call_js_function_with_runaway_killer (authority))
2370+ goto out;
2371+
2372+ if (duk_is_null(cx, -1)) {
2373+ /* this is fine, means there was no match, use implicit authorizations */
2374+ good = TRUE;
2375+ goto out;
2376+ }
2377+ ret_str = g_strdup (duk_require_string (cx, -1));
2378+ if (!polkit_implicit_authorization_from_string (ret_str, &ret))
2379+ {
2380+ polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
2381+ "Returned result `%s' is not valid",
2382+ ret_str);
2383+ goto out;
2384+ }
2385+
2386+ good = TRUE;
2387+
2388+ out:
2389+ if (!good)
2390+ ret = POLKIT_IMPLICIT_AUTHORIZATION_NOT_AUTHORIZED;
2391+ if (ret_str != NULL)
2392+ g_free (ret_str);
2393+
2394+ return ret;
2395+}
2396+
2397+/* ---------------------------------------------------------------------------------------------------- */
2398+
2399+static duk_ret_t
2400+js_polkit_log (duk_context *cx)
2401+{
2402+ const char *str = duk_require_string (cx, 0);
2403+ fprintf (stderr, "%s\n", str);
2404+ return 0;
2405+}
2406+
2407+/* ---------------------------------------------------------------------------------------------------- */
2408+
2409+static duk_ret_t
2410+js_polkit_spawn (duk_context *cx)
2411+{
2412+ duk_ret_t ret = DUK_RET_ERROR;
2413+ gchar *standard_output = NULL;
2414+ gchar *standard_error = NULL;
2415+ gint exit_status;
2416+ GError *error = NULL;
2417+ guint32 array_len;
2418+ gchar **argv = NULL;
2419+ GMainContext *context = NULL;
2420+ GMainLoop *loop = NULL;
2421+ SpawnData data = {0};
2422+ char *err_str = NULL;
2423+ guint n;
2424+
2425+ if (!duk_is_array (cx, 0))
2426+ goto out;
2427+
2428+ array_len = duk_get_length (cx, 0);
2429+
2430+ argv = g_new0 (gchar*, array_len + 1);
2431+ for (n = 0; n < array_len; n++)
2432+ {
2433+ duk_get_prop_index (cx, 0, n);
2434+ argv[n] = g_strdup (duk_to_string (cx, -1));
2435+ duk_pop (cx);
2436+ }
2437+
2438+ context = g_main_context_new ();
2439+ loop = g_main_loop_new (context, FALSE);
2440+
2441+ g_main_context_push_thread_default (context);
2442+
2443+ data.loop = loop;
2444+ polkit_backend_common_spawn ((const gchar *const *) argv,
2445+ 10, /* timeout_seconds */
2446+ NULL, /* cancellable */
2447+ polkit_backend_common_spawn_cb,
2448+ &data);
2449+
2450+ g_main_loop_run (loop);
2451+
2452+ g_main_context_pop_thread_default (context);
2453+
2454+ if (!polkit_backend_common_spawn_finish (data.res,
2455+ &exit_status,
2456+ &standard_output,
2457+ &standard_error,
2458+ &error))
2459+ {
2460+ err_str = g_strdup_printf ("Error spawning helper: %s (%s, %d)",
2461+ error->message, g_quark_to_string (error->domain), error->code);
2462+ g_clear_error (&error);
2463+ goto out;
2464+ }
2465+
2466+ if (!(WIFEXITED (exit_status) && WEXITSTATUS (exit_status) == 0))
2467+ {
2468+ GString *gstr;
2469+ gstr = g_string_new (NULL);
2470+ if (WIFEXITED (exit_status))
2471+ {
2472+ g_string_append_printf (gstr,
2473+ "Helper exited with non-zero exit status %d",
2474+ WEXITSTATUS (exit_status));
2475+ }
2476+ else if (WIFSIGNALED (exit_status))
2477+ {
2478+ g_string_append_printf (gstr,
2479+ "Helper was signaled with signal %s (%d)",
2480+ polkit_backend_common_get_signal_name (WTERMSIG (exit_status)),
2481+ WTERMSIG (exit_status));
2482+ }
2483+ g_string_append_printf (gstr, ", stdout=`%s', stderr=`%s'",
2484+ standard_output, standard_error);
2485+ err_str = g_string_free (gstr, FALSE);
2486+ goto out;
2487+ }
2488+
2489+ duk_push_string (cx, standard_output);
2490+ ret = 1;
2491+
2492+ out:
2493+ g_strfreev (argv);
2494+ g_free (standard_output);
2495+ g_free (standard_error);
2496+ g_clear_object (&data.res);
2497+ if (loop != NULL)
2498+ g_main_loop_unref (loop);
2499+ if (context != NULL)
2500+ g_main_context_unref (context);
2501+
2502+ if (err_str)
2503+ duk_error (cx, DUK_ERR_ERROR, err_str);
2504+
2505+ return ret;
2506+}
2507+
2508+/* ---------------------------------------------------------------------------------------------------- */
2509+
2510+
2511+static duk_ret_t
2512+js_polkit_user_is_in_netgroup (duk_context *cx)
2513+{
2514+ const char *user;
2515+ const char *netgroup;
2516+ gboolean is_in_netgroup = FALSE;
2517+
2518+ user = duk_require_string (cx, 0);
2519+ netgroup = duk_require_string (cx, 1);
2520+
2521+ if (innetgr (netgroup,
2522+ NULL, /* host */
2523+ user,
2524+ NULL)) /* domain */
2525+ {
2526+ is_in_netgroup = TRUE;
2527+ }
2528+
2529+ duk_push_boolean (cx, is_in_netgroup);
2530+ return 1;
2531+}
2532+
2533+/* ---------------------------------------------------------------------------------------------------- */
2534diff --git a/src/polkitbackend/polkitbackendjsauthority.cpp b/src/polkitbackend/polkitbackendjsauthority.cpp
2535index ca17108..11e91c0 100644
2536--- a/src/polkitbackend/polkitbackendjsauthority.cpp
2537+++ b/src/polkitbackend/polkitbackendjsauthority.cpp
2538@@ -19,29 +19,7 @@
2539 * Author: David Zeuthen <davidz@redhat.com>
2540 */
2541
2542-#include "config.h"
2543-#include <sys/wait.h>
2544-#include <errno.h>
2545-#include <pwd.h>
2546-#include <grp.h>
2547-#ifdef HAVE_NETGROUP_H
2548-#include <netgroup.h>
2549-#else
2550-#include <netdb.h>
2551-#endif
2552-#include <string.h>
2553-#include <glib/gstdio.h>
2554-#include <locale.h>
2555-#include <glib/gi18n-lib.h>
2556-
2557-#include <polkit/polkit.h>
2558-#include "polkitbackendjsauthority.h"
2559-
2560-#include <polkit/polkitprivate.h>
2561-
2562-#ifdef HAVE_LIBSYSTEMD
2563-#include <systemd/sd-login.h>
2564-#endif /* HAVE_LIBSYSTEMD */
2565+#include "polkitbackendcommon.h"
2566
2567 #include <js/CompilationAndEvaluation.h>
2568 #include <js/ContextOptions.h>
2569@@ -52,6 +30,7 @@
2570 #include <js/Array.h>
2571 #include <jsapi.h>
2572
2573+/* Built source and not too big to worry about deduplication */
2574 #include "initjs.h" /* init.js */
2575
2576 #ifdef JSGC_USE_EXACT_ROOTING
2577@@ -67,10 +46,9 @@
2578 * @short_description: JS Authority
2579 * @stability: Unstable
2580 *
2581- * An implementation of #PolkitBackendAuthority that reads and
2582- * evalates Javascript files and supports interaction with
2583- * authentication agents (virtue of being based on
2584- * #PolkitBackendInteractiveAuthority).
2585+ * An (SpiderMonkey-based) implementation of #PolkitBackendAuthority that reads
2586+ * and evaluates Javascript files and supports interaction with authentication
2587+ * agents (virtue of being based on #PolkitBackendInteractiveAuthority).
2588 */
2589
2590 /* ---------------------------------------------------------------------------------------------------- */
2591@@ -100,57 +78,11 @@ static bool execute_script_with_runaway_killer (PolkitBackendJsAuthority *author
2592 JS::HandleScript script,
2593 JS::MutableHandleValue rval);
2594
2595-static void utils_spawn (const gchar *const *argv,
2596- guint timeout_seconds,
2597- GCancellable *cancellable,
2598- GAsyncReadyCallback callback,
2599- gpointer user_data);
2600-
2601-gboolean utils_spawn_finish (GAsyncResult *res,
2602- gint *out_exit_status,
2603- gchar **out_standard_output,
2604- gchar **out_standard_error,
2605- GError **error);
2606-
2607-static void on_dir_monitor_changed (GFileMonitor *monitor,
2608- GFile *file,
2609- GFile *other_file,
2610- GFileMonitorEvent event_type,
2611- gpointer user_data);
2612-
2613-/* ---------------------------------------------------------------------------------------------------- */
2614-
2615-enum
2616-{
2617- PROP_0,
2618- PROP_RULES_DIRS,
2619-};
2620-
2621 /* ---------------------------------------------------------------------------------------------------- */
2622
2623 static gpointer runaway_killer_thread_func (gpointer user_data);
2624 static void runaway_killer_terminate (PolkitBackendJsAuthority *authority);
2625
2626-static GList *polkit_backend_js_authority_get_admin_auth_identities (PolkitBackendInteractiveAuthority *authority,
2627- PolkitSubject *caller,
2628- PolkitSubject *subject,
2629- PolkitIdentity *user_for_subject,
2630- gboolean subject_is_local,
2631- gboolean subject_is_active,
2632- const gchar *action_id,
2633- PolkitDetails *details);
2634-
2635-static PolkitImplicitAuthorization polkit_backend_js_authority_check_authorization_sync (
2636- PolkitBackendInteractiveAuthority *authority,
2637- PolkitSubject *caller,
2638- PolkitSubject *subject,
2639- PolkitIdentity *user_for_subject,
2640- gboolean subject_is_local,
2641- gboolean subject_is_active,
2642- const gchar *action_id,
2643- PolkitDetails *details,
2644- PolkitImplicitAuthorization implicit);
2645-
2646 G_DEFINE_TYPE (PolkitBackendJsAuthority, polkit_backend_js_authority, POLKIT_BACKEND_TYPE_INTERACTIVE_AUTHORITY);
2647
2648 /* ---------------------------------------------------------------------------------------------------- */
2649@@ -229,33 +161,6 @@ polkit_backend_js_authority_init (PolkitBackendJsAuthority *authority)
2650 PolkitBackendJsAuthorityPrivate);
2651 }
2652
2653-static gint
2654-rules_file_name_cmp (const gchar *a,
2655- const gchar *b)
2656-{
2657- gint ret;
2658- const gchar *a_base;
2659- const gchar *b_base;
2660-
2661- a_base = strrchr (a, '/');
2662- b_base = strrchr (b, '/');
2663-
2664- g_assert (a_base != NULL);
2665- g_assert (b_base != NULL);
2666- a_base += 1;
2667- b_base += 1;
2668-
2669- ret = g_strcmp0 (a_base, b_base);
2670- if (ret == 0)
2671- {
2672- /* /etc wins over /usr */
2673- ret = g_strcmp0 (a, b);
2674- g_assert (ret != 0);
2675- }
2676-
2677- return ret;
2678-}
2679-
2680 /* authority->priv->cx must be within a request */
2681 static void
2682 load_scripts (PolkitBackendJsAuthority *authority)
2683@@ -299,7 +204,7 @@ load_scripts (PolkitBackendJsAuthority *authority)
2684 }
2685 }
2686
2687- files = g_list_sort (files, (GCompareFunc) rules_file_name_cmp);
2688+ files = g_list_sort (files, (GCompareFunc) polkit_backend_common_rules_file_name_cmp);
2689
2690 for (l = files; l != NULL; l = l->next)
2691 {
2692@@ -365,8 +270,8 @@ load_scripts (PolkitBackendJsAuthority *authority)
2693 g_list_free_full (files, g_free);
2694 }
2695
2696-static void
2697-reload_scripts (PolkitBackendJsAuthority *authority)
2698+void
2699+polkit_backend_common_reload_scripts (PolkitBackendJsAuthority *authority)
2700 {
2701 JS::RootedValueArray<1> args(authority->priv->cx);
2702 JS::RootedValue rval(authority->priv->cx);
2703@@ -395,42 +300,6 @@ reload_scripts (PolkitBackendJsAuthority *authority)
2704 g_signal_emit_by_name (authority, "changed");
2705 }
2706
2707-static void
2708-on_dir_monitor_changed (GFileMonitor *monitor,
2709- GFile *file,
2710- GFile *other_file,
2711- GFileMonitorEvent event_type,
2712- gpointer user_data)
2713-{
2714- PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (user_data);
2715-
2716- /* TODO: maybe rate-limit so storms of events are collapsed into one with a 500ms resolution?
2717- * Because when editing a file with emacs we get 4-8 events..
2718- */
2719-
2720- if (file != NULL)
2721- {
2722- gchar *name;
2723-
2724- name = g_file_get_basename (file);
2725-
2726- /* g_print ("event_type=%d file=%p name=%s\n", event_type, file, name); */
2727- if (!g_str_has_prefix (name, ".") &&
2728- !g_str_has_prefix (name, "#") &&
2729- g_str_has_suffix (name, ".rules") &&
2730- (event_type == G_FILE_MONITOR_EVENT_CREATED ||
2731- event_type == G_FILE_MONITOR_EVENT_DELETED ||
2732- event_type == G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT))
2733- {
2734- polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
2735- "Reloading rules");
2736- reload_scripts (authority);
2737- }
2738- g_free (name);
2739- }
2740-}
2741-
2742-
2743 static void
2744 setup_file_monitors (PolkitBackendJsAuthority *authority)
2745 {
2746@@ -462,7 +331,7 @@ setup_file_monitors (PolkitBackendJsAuthority *authority)
2747 {
2748 g_signal_connect (monitor,
2749 "changed",
2750- G_CALLBACK (on_dir_monitor_changed),
2751+ G_CALLBACK (polkit_backend_common_on_dir_monitor_changed),
2752 authority);
2753 g_ptr_array_add (p, monitor);
2754 }
2755@@ -471,8 +340,8 @@ setup_file_monitors (PolkitBackendJsAuthority *authority)
2756 authority->priv->dir_monitors = (GFileMonitor**) g_ptr_array_free (p, FALSE);
2757 }
2758
2759-static void
2760-polkit_backend_js_authority_constructed (GObject *object)
2761+void
2762+polkit_backend_common_js_authority_constructed (GObject *object)
2763 {
2764 PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (object);
2765
2766@@ -561,8 +430,8 @@ polkit_backend_js_authority_constructed (GObject *object)
2767 g_assert_not_reached ();
2768 }
2769
2770-static void
2771-polkit_backend_js_authority_finalize (GObject *object)
2772+void
2773+polkit_backend_common_js_authority_finalize (GObject *object)
2774 {
2775 PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (object);
2776 guint n;
2777@@ -577,7 +446,7 @@ polkit_backend_js_authority_finalize (GObject *object)
2778 {
2779 GFileMonitor *monitor = authority->priv->dir_monitors[n];
2780 g_signal_handlers_disconnect_by_func (monitor,
2781- (gpointer*)G_CALLBACK (on_dir_monitor_changed),
2782+ (gpointer*)G_CALLBACK (polkit_backend_common_on_dir_monitor_changed),
2783 authority);
2784 g_object_unref (monitor);
2785 }
2786@@ -594,11 +463,11 @@ polkit_backend_js_authority_finalize (GObject *object)
2787 G_OBJECT_CLASS (polkit_backend_js_authority_parent_class)->finalize (object);
2788 }
2789
2790-static void
2791-polkit_backend_js_authority_set_property (GObject *object,
2792- guint property_id,
2793- const GValue *value,
2794- GParamSpec *pspec)
2795+void
2796+polkit_backend_common_js_authority_set_property (GObject *object,
2797+ guint property_id,
2798+ const GValue *value,
2799+ GParamSpec *pspec)
2800 {
2801 PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (object);
2802
2803@@ -615,57 +484,12 @@ polkit_backend_js_authority_set_property (GObject *object,
2804 }
2805 }
2806
2807-static const gchar *
2808-polkit_backend_js_authority_get_name (PolkitBackendAuthority *authority)
2809-{
2810- return "js";
2811-}
2812-
2813-static const gchar *
2814-polkit_backend_js_authority_get_version (PolkitBackendAuthority *authority)
2815-{
2816- return PACKAGE_VERSION;
2817-}
2818-
2819-static PolkitAuthorityFeatures
2820-polkit_backend_js_authority_get_features (PolkitBackendAuthority *authority)
2821-{
2822- return POLKIT_AUTHORITY_FEATURES_TEMPORARY_AUTHORIZATION;
2823-}
2824-
2825 static void
2826 polkit_backend_js_authority_class_init (PolkitBackendJsAuthorityClass *klass)
2827 {
2828- GObjectClass *gobject_class;
2829- PolkitBackendAuthorityClass *authority_class;
2830- PolkitBackendInteractiveAuthorityClass *interactive_authority_class;
2831-
2832-
2833- gobject_class = G_OBJECT_CLASS (klass);
2834- gobject_class->finalize = polkit_backend_js_authority_finalize;
2835- gobject_class->set_property = polkit_backend_js_authority_set_property;
2836- gobject_class->constructed = polkit_backend_js_authority_constructed;
2837-
2838- authority_class = POLKIT_BACKEND_AUTHORITY_CLASS (klass);
2839- authority_class->get_name = polkit_backend_js_authority_get_name;
2840- authority_class->get_version = polkit_backend_js_authority_get_version;
2841- authority_class->get_features = polkit_backend_js_authority_get_features;
2842-
2843- interactive_authority_class = POLKIT_BACKEND_INTERACTIVE_AUTHORITY_CLASS (klass);
2844- interactive_authority_class->get_admin_identities = polkit_backend_js_authority_get_admin_auth_identities;
2845- interactive_authority_class->check_authorization_sync = polkit_backend_js_authority_check_authorization_sync;
2846-
2847- g_object_class_install_property (gobject_class,
2848- PROP_RULES_DIRS,
2849- g_param_spec_boxed ("rules-dirs",
2850- NULL,
2851- NULL,
2852- G_TYPE_STRV,
2853- GParamFlags(G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE)));
2854-
2855+ polkit_backend_common_js_authority_class_init_common (klass);
2856
2857 g_type_class_add_private (klass, sizeof (PolkitBackendJsAuthorityPrivate));
2858-
2859 JS_Init ();
2860 }
2861
2862@@ -1005,11 +829,14 @@ runaway_killer_setup (PolkitBackendJsAuthority *authority)
2863 {
2864 g_assert (authority->priv->rkt_source == NULL);
2865
2866- /* set-up timer for runaway scripts, will be executed in runaway_killer_thread */
2867+ /* set-up timer for runaway scripts, will be executed in
2868+ runaway_killer_thread, that is one, permanent thread running a glib
2869+ mainloop (rkt_loop) whose context (rkt_context) has a timeout source
2870+ (rkt_source) */
2871 g_mutex_lock (&authority->priv->rkt_timeout_pending_mutex);
2872 authority->priv->rkt_timeout_pending = FALSE;
2873 g_mutex_unlock (&authority->priv->rkt_timeout_pending_mutex);
2874- authority->priv->rkt_source = g_timeout_source_new_seconds (15);
2875+ authority->priv->rkt_source = g_timeout_source_new_seconds (RUNAWAY_KILLER_TIMEOUT);
2876 g_source_set_callback (authority->priv->rkt_source, rkt_on_timeout, authority, NULL);
2877 g_source_attach (authority->priv->rkt_source, authority->priv->rkt_context);
2878
2879@@ -1069,6 +896,9 @@ execute_script_with_runaway_killer (PolkitBackendJsAuthority *authority,
2880 {
2881 bool ret;
2882
2883+ // tries to JS_ExecuteScript(), may hang for > RUNAWAY_KILLER_TIMEOUT,
2884+ // runaway_killer_thread makes sure the call returns, due to exception
2885+ // injection
2886 runaway_killer_setup (authority);
2887 ret = JS_ExecuteScript (authority->priv->cx,
2888 script,
2889@@ -1099,15 +929,15 @@ call_js_function_with_runaway_killer (PolkitBackendJsAuthority *authority,
2890
2891 /* ---------------------------------------------------------------------------------------------------- */
2892
2893-static GList *
2894-polkit_backend_js_authority_get_admin_auth_identities (PolkitBackendInteractiveAuthority *_authority,
2895- PolkitSubject *caller,
2896- PolkitSubject *subject,
2897- PolkitIdentity *user_for_subject,
2898- gboolean subject_is_local,
2899- gboolean subject_is_active,
2900- const gchar *action_id,
2901- PolkitDetails *details)
2902+GList *
2903+polkit_backend_common_js_authority_get_admin_auth_identities (PolkitBackendInteractiveAuthority *_authority,
2904+ PolkitSubject *caller,
2905+ PolkitSubject *subject,
2906+ PolkitIdentity *user_for_subject,
2907+ gboolean subject_is_local,
2908+ gboolean subject_is_active,
2909+ const gchar *action_id,
2910+ PolkitDetails *details)
2911 {
2912 PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (_authority);
2913 GList *ret = NULL;
2914@@ -1202,16 +1032,16 @@ polkit_backend_js_authority_get_admin_auth_identities (PolkitBackendInteractiveA
2915
2916 /* ---------------------------------------------------------------------------------------------------- */
2917
2918-static PolkitImplicitAuthorization
2919-polkit_backend_js_authority_check_authorization_sync (PolkitBackendInteractiveAuthority *_authority,
2920- PolkitSubject *caller,
2921- PolkitSubject *subject,
2922- PolkitIdentity *user_for_subject,
2923- gboolean subject_is_local,
2924- gboolean subject_is_active,
2925- const gchar *action_id,
2926- PolkitDetails *details,
2927- PolkitImplicitAuthorization implicit)
2928+PolkitImplicitAuthorization
2929+polkit_backend_common_js_authority_check_authorization_sync (PolkitBackendInteractiveAuthority *_authority,
2930+ PolkitSubject *caller,
2931+ PolkitSubject *subject,
2932+ PolkitIdentity *user_for_subject,
2933+ gboolean subject_is_local,
2934+ gboolean subject_is_active,
2935+ const gchar *action_id,
2936+ PolkitDetails *details,
2937+ PolkitImplicitAuthorization implicit)
2938 {
2939 PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (_authority);
2940 PolkitImplicitAuthorization ret = implicit;
2941@@ -1324,65 +1154,6 @@ js_polkit_log (JSContext *cx,
2942
2943 /* ---------------------------------------------------------------------------------------------------- */
2944
2945-static const gchar *
2946-get_signal_name (gint signal_number)
2947-{
2948- switch (signal_number)
2949- {
2950-#define _HANDLE_SIG(sig) case sig: return #sig;
2951- _HANDLE_SIG (SIGHUP);
2952- _HANDLE_SIG (SIGINT);
2953- _HANDLE_SIG (SIGQUIT);
2954- _HANDLE_SIG (SIGILL);
2955- _HANDLE_SIG (SIGABRT);
2956- _HANDLE_SIG (SIGFPE);
2957- _HANDLE_SIG (SIGKILL);
2958- _HANDLE_SIG (SIGSEGV);
2959- _HANDLE_SIG (SIGPIPE);
2960- _HANDLE_SIG (SIGALRM);
2961- _HANDLE_SIG (SIGTERM);
2962- _HANDLE_SIG (SIGUSR1);
2963- _HANDLE_SIG (SIGUSR2);
2964- _HANDLE_SIG (SIGCHLD);
2965- _HANDLE_SIG (SIGCONT);
2966- _HANDLE_SIG (SIGSTOP);
2967- _HANDLE_SIG (SIGTSTP);
2968- _HANDLE_SIG (SIGTTIN);
2969- _HANDLE_SIG (SIGTTOU);
2970- _HANDLE_SIG (SIGBUS);
2971-#ifdef SIGPOLL
2972- _HANDLE_SIG (SIGPOLL);
2973-#endif
2974- _HANDLE_SIG (SIGPROF);
2975- _HANDLE_SIG (SIGSYS);
2976- _HANDLE_SIG (SIGTRAP);
2977- _HANDLE_SIG (SIGURG);
2978- _HANDLE_SIG (SIGVTALRM);
2979- _HANDLE_SIG (SIGXCPU);
2980- _HANDLE_SIG (SIGXFSZ);
2981-#undef _HANDLE_SIG
2982- default:
2983- break;
2984- }
2985- return "UNKNOWN_SIGNAL";
2986-}
2987-
2988-typedef struct
2989-{
2990- GMainLoop *loop;
2991- GAsyncResult *res;
2992-} SpawnData;
2993-
2994-static void
2995-spawn_cb (GObject *source_object,
2996- GAsyncResult *res,
2997- gpointer user_data)
2998-{
2999- SpawnData *data = (SpawnData *)user_data;
3000- data->res = (GAsyncResult*)g_object_ref (res);
3001- g_main_loop_quit (data->loop);
3002-}
3003-
3004 static bool
3005 js_polkit_spawn (JSContext *cx,
3006 unsigned js_argc,
3007@@ -1440,21 +1211,21 @@ js_polkit_spawn (JSContext *cx,
3008 g_main_context_push_thread_default (context);
3009
3010 data.loop = loop;
3011- utils_spawn ((const gchar *const *) argv,
3012- 10, /* timeout_seconds */
3013- NULL, /* cancellable */
3014- spawn_cb,
3015- &data);
3016+ polkit_backend_common_spawn ((const gchar *const *) argv,
3017+ 10, /* timeout_seconds */
3018+ NULL, /* cancellable */
3019+ polkit_backend_common_spawn_cb,
3020+ &data);
3021
3022 g_main_loop_run (loop);
3023
3024 g_main_context_pop_thread_default (context);
3025
3026- if (!utils_spawn_finish (data.res,
3027- &exit_status,
3028- &standard_output,
3029- &standard_error,
3030- &error))
3031+ if (!polkit_backend_common_spawn_finish (data.res,
3032+ &exit_status,
3033+ &standard_output,
3034+ &standard_error,
3035+ &error))
3036 {
3037 JS_ReportErrorUTF8 (cx,
3038 "Error spawning helper: %s (%s, %d)",
3039@@ -1477,7 +1248,7 @@ js_polkit_spawn (JSContext *cx,
3040 {
3041 g_string_append_printf (gstr,
3042 "Helper was signaled with signal %s (%d)",
3043- get_signal_name (WTERMSIG (exit_status)),
3044+ polkit_backend_common_get_signal_name (WTERMSIG (exit_status)),
3045 WTERMSIG (exit_status));
3046 }
3047 g_string_append_printf (gstr, ", stdout=`%s', stderr=`%s'",
3048@@ -1542,381 +1313,5 @@ js_polkit_user_is_in_netgroup (JSContext *cx,
3049 return ret;
3050 }
3051
3052-
3053-
3054 /* ---------------------------------------------------------------------------------------------------- */
3055
3056-typedef struct
3057-{
3058- GSimpleAsyncResult *simple; /* borrowed reference */
3059- GMainContext *main_context; /* may be NULL */
3060-
3061- GCancellable *cancellable; /* may be NULL */
3062- gulong cancellable_handler_id;
3063-
3064- GPid child_pid;
3065- gint child_stdout_fd;
3066- gint child_stderr_fd;
3067-
3068- GIOChannel *child_stdout_channel;
3069- GIOChannel *child_stderr_channel;
3070-
3071- GSource *child_watch_source;
3072- GSource *child_stdout_source;
3073- GSource *child_stderr_source;
3074-
3075- guint timeout_seconds;
3076- gboolean timed_out;
3077- GSource *timeout_source;
3078-
3079- GString *child_stdout;
3080- GString *child_stderr;
3081-
3082- gint exit_status;
3083-} UtilsSpawnData;
3084-
3085-static void
3086-utils_child_watch_from_release_cb (GPid pid,
3087- gint status,
3088- gpointer user_data)
3089-{
3090-}
3091-
3092-static void
3093-utils_spawn_data_free (UtilsSpawnData *data)
3094-{
3095- if (data->timeout_source != NULL)
3096- {
3097- g_source_destroy (data->timeout_source);
3098- data->timeout_source = NULL;
3099- }
3100-
3101- /* Nuke the child, if necessary */
3102- if (data->child_watch_source != NULL)
3103- {
3104- g_source_destroy (data->child_watch_source);
3105- data->child_watch_source = NULL;
3106- }
3107-
3108- if (data->child_pid != 0)
3109- {
3110- GSource *source;
3111- kill (data->child_pid, SIGTERM);
3112- /* OK, we need to reap for the child ourselves - we don't want
3113- * to use waitpid() because that might block the calling
3114- * thread (the child might handle SIGTERM and use several
3115- * seconds for cleanup/rollback).
3116- *
3117- * So we use GChildWatch instead.
3118- *
3119- * Avoid taking a references to ourselves. but note that we need
3120- * to pass the GSource so we can nuke it once handled.
3121- */
3122- source = g_child_watch_source_new (data->child_pid);
3123- g_source_set_callback (source,
3124- (GSourceFunc) utils_child_watch_from_release_cb,
3125- source,
3126- (GDestroyNotify) g_source_destroy);
3127- /* attach source to the global default main context */
3128- g_source_attach (source, NULL);
3129- g_source_unref (source);
3130- data->child_pid = 0;
3131- }
3132-
3133- if (data->child_stdout != NULL)
3134- {
3135- g_string_free (data->child_stdout, TRUE);
3136- data->child_stdout = NULL;
3137- }
3138-
3139- if (data->child_stderr != NULL)
3140- {
3141- g_string_free (data->child_stderr, TRUE);
3142- data->child_stderr = NULL;
3143- }
3144-
3145- if (data->child_stdout_channel != NULL)
3146- {
3147- g_io_channel_unref (data->child_stdout_channel);
3148- data->child_stdout_channel = NULL;
3149- }
3150- if (data->child_stderr_channel != NULL)
3151- {
3152- g_io_channel_unref (data->child_stderr_channel);
3153- data->child_stderr_channel = NULL;
3154- }
3155-
3156- if (data->child_stdout_source != NULL)
3157- {
3158- g_source_destroy (data->child_stdout_source);
3159- data->child_stdout_source = NULL;
3160- }
3161- if (data->child_stderr_source != NULL)
3162- {
3163- g_source_destroy (data->child_stderr_source);
3164- data->child_stderr_source = NULL;
3165- }
3166-
3167- if (data->child_stdout_fd != -1)
3168- {
3169- g_warn_if_fail (close (data->child_stdout_fd) == 0);
3170- data->child_stdout_fd = -1;
3171- }
3172- if (data->child_stderr_fd != -1)
3173- {
3174- g_warn_if_fail (close (data->child_stderr_fd) == 0);
3175- data->child_stderr_fd = -1;
3176- }
3177-
3178- if (data->cancellable_handler_id > 0)
3179- {
3180- g_cancellable_disconnect (data->cancellable, data->cancellable_handler_id);
3181- data->cancellable_handler_id = 0;
3182- }
3183-
3184- if (data->main_context != NULL)
3185- g_main_context_unref (data->main_context);
3186-
3187- if (data->cancellable != NULL)
3188- g_object_unref (data->cancellable);
3189-
3190- g_slice_free (UtilsSpawnData, data);
3191-}
3192-
3193-/* called in the thread where @cancellable was cancelled */
3194-static void
3195-utils_on_cancelled (GCancellable *cancellable,
3196- gpointer user_data)
3197-{
3198- UtilsSpawnData *data = (UtilsSpawnData *)user_data;
3199- GError *error;
3200-
3201- error = NULL;
3202- g_warn_if_fail (g_cancellable_set_error_if_cancelled (cancellable, &error));
3203- g_simple_async_result_take_error (data->simple, error);
3204- g_simple_async_result_complete_in_idle (data->simple);
3205- g_object_unref (data->simple);
3206-}
3207-
3208-static gboolean
3209-utils_read_child_stderr (GIOChannel *channel,
3210- GIOCondition condition,
3211- gpointer user_data)
3212-{
3213- UtilsSpawnData *data = (UtilsSpawnData *)user_data;
3214- gchar buf[1024];
3215- gsize bytes_read;
3216-
3217- g_io_channel_read_chars (channel, buf, sizeof buf, &bytes_read, NULL);
3218- g_string_append_len (data->child_stderr, buf, bytes_read);
3219- return TRUE;
3220-}
3221-
3222-static gboolean
3223-utils_read_child_stdout (GIOChannel *channel,
3224- GIOCondition condition,
3225- gpointer user_data)
3226-{
3227- UtilsSpawnData *data = (UtilsSpawnData *)user_data;
3228- gchar buf[1024];
3229- gsize bytes_read;
3230-
3231- g_io_channel_read_chars (channel, buf, sizeof buf, &bytes_read, NULL);
3232- g_string_append_len (data->child_stdout, buf, bytes_read);
3233- return TRUE;
3234-}
3235-
3236-static void
3237-utils_child_watch_cb (GPid pid,
3238- gint status,
3239- gpointer user_data)
3240-{
3241- UtilsSpawnData *data = (UtilsSpawnData *)user_data;
3242- gchar *buf;
3243- gsize buf_size;
3244-
3245- if (g_io_channel_read_to_end (data->child_stdout_channel, &buf, &buf_size, NULL) == G_IO_STATUS_NORMAL)
3246- {
3247- g_string_append_len (data->child_stdout, buf, buf_size);
3248- g_free (buf);
3249- }
3250- if (g_io_channel_read_to_end (data->child_stderr_channel, &buf, &buf_size, NULL) == G_IO_STATUS_NORMAL)
3251- {
3252- g_string_append_len (data->child_stderr, buf, buf_size);
3253- g_free (buf);
3254- }
3255-
3256- data->exit_status = status;
3257-
3258- /* ok, child watch is history, make sure we don't free it in spawn_data_free() */
3259- data->child_pid = 0;
3260- data->child_watch_source = NULL;
3261-
3262- /* we're done */
3263- g_simple_async_result_complete_in_idle (data->simple);
3264- g_object_unref (data->simple);
3265-}
3266-
3267-static gboolean
3268-utils_timeout_cb (gpointer user_data)
3269-{
3270- UtilsSpawnData *data = (UtilsSpawnData *)user_data;
3271-
3272- data->timed_out = TRUE;
3273-
3274- /* ok, timeout is history, make sure we don't free it in spawn_data_free() */
3275- data->timeout_source = NULL;
3276-
3277- /* we're done */
3278- g_simple_async_result_complete_in_idle (data->simple);
3279- g_object_unref (data->simple);
3280-
3281- return FALSE; /* remove source */
3282-}
3283-
3284-static void
3285-utils_spawn (const gchar *const *argv,
3286- guint timeout_seconds,
3287- GCancellable *cancellable,
3288- GAsyncReadyCallback callback,
3289- gpointer user_data)
3290-{
3291- UtilsSpawnData *data;
3292- GError *error;
3293-
3294- data = g_slice_new0 (UtilsSpawnData);
3295- data->timeout_seconds = timeout_seconds;
3296- data->simple = g_simple_async_result_new (NULL,
3297- callback,
3298- user_data,
3299- (gpointer*)utils_spawn);
3300- data->main_context = g_main_context_get_thread_default ();
3301- if (data->main_context != NULL)
3302- g_main_context_ref (data->main_context);
3303-
3304- data->cancellable = cancellable != NULL ? (GCancellable*)g_object_ref (cancellable) : NULL;
3305-
3306- data->child_stdout = g_string_new (NULL);
3307- data->child_stderr = g_string_new (NULL);
3308- data->child_stdout_fd = -1;
3309- data->child_stderr_fd = -1;
3310-
3311- /* the life-cycle of UtilsSpawnData is tied to its GSimpleAsyncResult */
3312- g_simple_async_result_set_op_res_gpointer (data->simple, data, (GDestroyNotify) utils_spawn_data_free);
3313-
3314- error = NULL;
3315- if (data->cancellable != NULL)
3316- {
3317- /* could already be cancelled */
3318- error = NULL;
3319- if (g_cancellable_set_error_if_cancelled (data->cancellable, &error))
3320- {
3321- g_simple_async_result_take_error (data->simple, error);
3322- g_simple_async_result_complete_in_idle (data->simple);
3323- g_object_unref (data->simple);
3324- goto out;
3325- }
3326-
3327- data->cancellable_handler_id = g_cancellable_connect (data->cancellable,
3328- G_CALLBACK (utils_on_cancelled),
3329- data,
3330- NULL);
3331- }
3332-
3333- error = NULL;
3334- if (!g_spawn_async_with_pipes (NULL, /* working directory */
3335- (gchar **) argv,
3336- NULL, /* envp */
3337- GSpawnFlags(G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD),
3338- NULL, /* child_setup */
3339- NULL, /* child_setup's user_data */
3340- &(data->child_pid),
3341- NULL, /* gint *stdin_fd */
3342- &(data->child_stdout_fd),
3343- &(data->child_stderr_fd),
3344- &error))
3345- {
3346- g_prefix_error (&error, "Error spawning: ");
3347- g_simple_async_result_take_error (data->simple, error);
3348- g_simple_async_result_complete_in_idle (data->simple);
3349- g_object_unref (data->simple);
3350- goto out;
3351- }
3352-
3353- if (timeout_seconds > 0)
3354- {
3355- data->timeout_source = g_timeout_source_new_seconds (timeout_seconds);
3356- g_source_set_priority (data->timeout_source, G_PRIORITY_DEFAULT);
3357- g_source_set_callback (data->timeout_source, utils_timeout_cb, data, NULL);
3358- g_source_attach (data->timeout_source, data->main_context);
3359- g_source_unref (data->timeout_source);
3360- }
3361-
3362- data->child_watch_source = g_child_watch_source_new (data->child_pid);
3363- g_source_set_callback (data->child_watch_source, (GSourceFunc) utils_child_watch_cb, data, NULL);
3364- g_source_attach (data->child_watch_source, data->main_context);
3365- g_source_unref (data->child_watch_source);
3366-
3367- data->child_stdout_channel = g_io_channel_unix_new (data->child_stdout_fd);
3368- g_io_channel_set_flags (data->child_stdout_channel, G_IO_FLAG_NONBLOCK, NULL);
3369- data->child_stdout_source = g_io_create_watch (data->child_stdout_channel, G_IO_IN);
3370- g_source_set_callback (data->child_stdout_source, (GSourceFunc) utils_read_child_stdout, data, NULL);
3371- g_source_attach (data->child_stdout_source, data->main_context);
3372- g_source_unref (data->child_stdout_source);
3373-
3374- data->child_stderr_channel = g_io_channel_unix_new (data->child_stderr_fd);
3375- g_io_channel_set_flags (data->child_stderr_channel, G_IO_FLAG_NONBLOCK, NULL);
3376- data->child_stderr_source = g_io_create_watch (data->child_stderr_channel, G_IO_IN);
3377- g_source_set_callback (data->child_stderr_source, (GSourceFunc) utils_read_child_stderr, data, NULL);
3378- g_source_attach (data->child_stderr_source, data->main_context);
3379- g_source_unref (data->child_stderr_source);
3380-
3381- out:
3382- ;
3383-}
3384-
3385-gboolean
3386-utils_spawn_finish (GAsyncResult *res,
3387- gint *out_exit_status,
3388- gchar **out_standard_output,
3389- gchar **out_standard_error,
3390- GError **error)
3391-{
3392- GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
3393- UtilsSpawnData *data;
3394- gboolean ret = FALSE;
3395-
3396- g_return_val_if_fail (G_IS_ASYNC_RESULT (res), FALSE);
3397- g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
3398-
3399- g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == utils_spawn);
3400-
3401- if (g_simple_async_result_propagate_error (simple, error))
3402- goto out;
3403-
3404- data = (UtilsSpawnData*)g_simple_async_result_get_op_res_gpointer (simple);
3405-
3406- if (data->timed_out)
3407- {
3408- g_set_error (error,
3409- G_IO_ERROR,
3410- G_IO_ERROR_TIMED_OUT,
3411- "Timed out after %d seconds",
3412- data->timeout_seconds);
3413- goto out;
3414- }
3415-
3416- if (out_exit_status != NULL)
3417- *out_exit_status = data->exit_status;
3418-
3419- if (out_standard_output != NULL)
3420- *out_standard_output = g_strdup (data->child_stdout->str);
3421-
3422- if (out_standard_error != NULL)
3423- *out_standard_error = g_strdup (data->child_stderr->str);
3424-
3425- ret = TRUE;
3426-
3427- out:
3428- return ret;
3429-}
3430diff --git a/test/data/etc/polkit-1/rules.d/10-testing.rules b/test/data/etc/polkit-1/rules.d/10-testing.rules
3431index 98bf062..e346b5d 100644
3432--- a/test/data/etc/polkit-1/rules.d/10-testing.rules
3433+++ b/test/data/etc/polkit-1/rules.d/10-testing.rules
3434@@ -189,8 +189,10 @@ polkit.addRule(function(action, subject) {
3435 ;
3436 } catch (error) {
3437 if (error == "Terminating runaway script")
3438- return polkit.Result.YES;
3439- return polkit.Result.NO;
3440+ // Inverted logic to accomodate Duktape's model as well, which
3441+ // will always fail with negation, on timeouts
3442+ return polkit.Result.NO;
3443+ return polkit.Result.YES;
3444 }
3445 }
3446 });
3447diff --git a/test/polkitbackend/test-polkitbackendjsauthority.c b/test/polkitbackend/test-polkitbackendjsauthority.c
3448index f97e0e0..2103b17 100644
3449--- a/test/polkitbackend/test-polkitbackendjsauthority.c
3450+++ b/test/polkitbackend/test-polkitbackendjsauthority.c
3451@@ -328,7 +328,7 @@ static const RulesTestCase rules_test_cases[] = {
3452 "net.company.run_away_script",
3453 "unix-user:root",
3454 NULL,
3455- POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED,
3456+ POLKIT_IMPLICIT_AUTHORIZATION_NOT_AUTHORIZED,
3457 },
3458
3459 {
diff --git a/meta-oe/recipes-extended/polkit/polkit/0003-jsauthority-ensure-to-call-JS_Init-and-JS_ShutDown-e.patch b/meta-oe/recipes-extended/polkit/polkit/0003-jsauthority-ensure-to-call-JS_Init-and-JS_ShutDown-e.patch
deleted file mode 100644
index 9e9755e44f..0000000000
--- a/meta-oe/recipes-extended/polkit/polkit/0003-jsauthority-ensure-to-call-JS_Init-and-JS_ShutDown-e.patch
+++ /dev/null
@@ -1,63 +0,0 @@
1From 7799441b9aa55324160deefbc65f9d918b8c94c1 Mon Sep 17 00:00:00 2001
2From: Xi Ruoyao <xry111@mengyan1223.wang>
3Date: Tue, 10 Aug 2021 18:52:56 +0800
4Subject: [PATCH] jsauthority: ensure to call JS_Init() and JS_ShutDown()
5 exactly once
6
7Before this commit, we were calling JS_Init() in
8polkit_backend_js_authority_class_init and never called JS_ShutDown.
9This is actually a misusage of SpiderMonkey API. Quote from a comment
10in js/Initialization.h (both mozjs-78 and mozjs-91):
11
12 It is currently not possible to initialize SpiderMonkey multiple
13 times (that is, calling JS_Init/JSAPI methods/JS_ShutDown in that
14 order, then doing so again).
15
16This misusage does not cause severe issues with mozjs-78. However, when
17we eventually port jsauthority to use mozjs-91, bad thing will happen:
18see the test failure mentioned in #150.
19
20This commit is tested with both mozjs-78 and mozjs-91, all tests pass
21with it.
22
23Upstream-Status: Submitted [https://gitlab.freedesktop.org/polkit/polkit/-/merge_requests/91]
24Signed-off-by: Alexander Kanavin <alex@linutronix.de>
25---
26 src/polkitbackend/polkitbackendjsauthority.cpp | 10 +++++++---
27 1 file changed, 7 insertions(+), 3 deletions(-)
28
29diff --git a/src/polkitbackend/polkitbackendjsauthority.cpp b/src/polkitbackend/polkitbackendjsauthority.cpp
30index 41d8d5c..38dc001 100644
31--- a/src/polkitbackend/polkitbackendjsauthority.cpp
32+++ b/src/polkitbackend/polkitbackendjsauthority.cpp
33@@ -75,6 +75,13 @@
34
35 /* ---------------------------------------------------------------------------------------------------- */
36
37+static class JsInitHelperType
38+{
39+public:
40+ JsInitHelperType() { JS_Init(); }
41+ ~JsInitHelperType() { JS_ShutDown(); }
42+} JsInitHelper;
43+
44 struct _PolkitBackendJsAuthorityPrivate
45 {
46 gchar **rules_dirs;
47@@ -589,7 +596,6 @@ polkit_backend_js_authority_finalize (GObject *object)
48 delete authority->priv->js_polkit;
49
50 JS_DestroyContext (authority->priv->cx);
51- /* JS_ShutDown (); */
52
53 G_OBJECT_CLASS (polkit_backend_js_authority_parent_class)->finalize (object);
54 }
55@@ -665,8 +671,6 @@ polkit_backend_js_authority_class_init (PolkitBackendJsAuthorityClass *klass)
56
57
58 g_type_class_add_private (klass, sizeof (PolkitBackendJsAuthorityPrivate));
59-
60- JS_Init ();
61 }
62
63 /* ---------------------------------------------------------------------------------------------------- */
diff --git a/meta-oe/recipes-extended/polkit/polkit/0004-Make-netgroup-support-optional.patch b/meta-oe/recipes-extended/polkit/polkit/0004-Make-netgroup-support-optional.patch
deleted file mode 100644
index 181aca16ca..0000000000
--- a/meta-oe/recipes-extended/polkit/polkit/0004-Make-netgroup-support-optional.patch
+++ /dev/null
@@ -1,253 +0,0 @@
1From a334fac72112c01cd322f7c97ef7ca21457ab52f Mon Sep 17 00:00:00 2001
2From: "A. Wilcox" <AWilcox@Wilcox-Tech.com>
3Date: Sun, 15 May 2022 05:04:10 +0000
4Subject: [PATCH] Make netgroup support optional
5
6On at least Linux/musl and Linux/uclibc, netgroup support is not
7available. PolKit fails to compile on these systems for that reason.
8
9This change makes netgroup support conditional on the presence of the
10setnetgrent(3) function which is required for the support to work. If
11that function is not available on the system, an error will be returned
12to the administrator if unix-netgroup: is specified in configuration.
13
14(sam: rebased for Meson and Duktape.)
15
16Closes: https://gitlab.freedesktop.org/polkit/polkit/-/issues/14
17Closes: https://gitlab.freedesktop.org/polkit/polkit/-/issues/163
18Closes: https://gitlab.freedesktop.org/polkit/polkit/-/merge_requests/52
19Signed-off-by: A. Wilcox <AWilcox@Wilcox-Tech.com>
20
21Ported back the change in configure.ac (upstream removed autotools
22support).
23
24Upstream-Status: Backport [https://gitlab.freedesktop.org/polkit/polkit/-/commit/b57deee8178190a7ecc75290fa13cf7daabc2c66]
25Signed-off-by: Marta Rybczynska <marta.rybczynska@huawei.com>
26
27---
28 configure.ac | 2 +-
29 meson.build | 1 +
30 src/polkit/polkitidentity.c | 17 +++++++++++++++++
31 src/polkit/polkitunixnetgroup.c | 3 +++
32 .../polkitbackendinteractiveauthority.c | 14 ++++++++------
33 src/polkitbackend/polkitbackendjsauthority.cpp | 2 ++
34 test/polkit/polkitidentitytest.c | 8 +++++++-
35 test/polkit/polkitunixnetgrouptest.c | 2 ++
36 .../test-polkitbackendjsauthority.c | 2 ++
37 9 files changed, 43 insertions(+), 8 deletions(-)
38
39diff --git a/configure.ac b/configure.ac
40index ca4b9f2..4c5d596 100644
41--- a/configure.ac
42+++ b/configure.ac
43@@ -100,7 +100,7 @@ AC_CHECK_LIB(expat,XML_ParserCreate,[EXPAT_LIBS="-lexpat"],
44 [AC_MSG_ERROR([Can't find expat library. Please install expat.])])
45 AC_SUBST(EXPAT_LIBS)
46
47-AC_CHECK_FUNCS(clearenv fdatasync)
48+AC_CHECK_FUNCS(clearenv fdatasync setnetgrent)
49
50 if test "x$GCC" = "xyes"; then
51 LDFLAGS="-Wl,--as-needed $LDFLAGS"
52diff --git a/meson.build b/meson.build
53index 733bbff..d840926 100644
54--- a/meson.build
55+++ b/meson.build
56@@ -82,6 +82,7 @@ config_h.set('_GNU_SOURCE', true)
57 check_functions = [
58 'clearenv',
59 'fdatasync',
60+ 'setnetgrent',
61 ]
62
63 foreach func: check_functions
64diff --git a/src/polkit/polkitidentity.c b/src/polkit/polkitidentity.c
65index 3aa1f7f..793f17d 100644
66--- a/src/polkit/polkitidentity.c
67+++ b/src/polkit/polkitidentity.c
68@@ -182,7 +182,15 @@ polkit_identity_from_string (const gchar *str,
69 }
70 else if (g_str_has_prefix (str, "unix-netgroup:"))
71 {
72+#ifndef HAVE_SETNETGRENT
73+ g_set_error (error,
74+ POLKIT_ERROR,
75+ POLKIT_ERROR_FAILED,
76+ "Netgroups are not available on this machine ('%s')",
77+ str);
78+#else
79 identity = polkit_unix_netgroup_new (str + sizeof "unix-netgroup:" - 1);
80+#endif
81 }
82
83 if (identity == NULL && (error != NULL && *error == NULL))
84@@ -344,6 +352,14 @@ polkit_identity_new_for_gvariant (GVariant *variant,
85 GVariant *v;
86 const char *name;
87
88+#ifndef HAVE_SETNETGRENT
89+ g_set_error (error,
90+ POLKIT_ERROR,
91+ POLKIT_ERROR_FAILED,
92+ "Netgroups are not available on this machine");
93+ goto out;
94+#else
95+
96 v = lookup_asv (details_gvariant, "name", G_VARIANT_TYPE_STRING, error);
97 if (v == NULL)
98 {
99@@ -353,6 +369,7 @@ polkit_identity_new_for_gvariant (GVariant *variant,
100 name = g_variant_get_string (v, NULL);
101 ret = polkit_unix_netgroup_new (name);
102 g_variant_unref (v);
103+#endif
104 }
105 else
106 {
107diff --git a/src/polkit/polkitunixnetgroup.c b/src/polkit/polkitunixnetgroup.c
108index 8a2b369..83f8d4a 100644
109--- a/src/polkit/polkitunixnetgroup.c
110+++ b/src/polkit/polkitunixnetgroup.c
111@@ -194,6 +194,9 @@ polkit_unix_netgroup_set_name (PolkitUnixNetgroup *group,
112 PolkitIdentity *
113 polkit_unix_netgroup_new (const gchar *name)
114 {
115+#ifndef HAVE_SETNETGRENT
116+ g_assert_not_reached();
117+#endif
118 g_return_val_if_fail (name != NULL, NULL);
119 return POLKIT_IDENTITY (g_object_new (POLKIT_TYPE_UNIX_NETGROUP,
120 "name", name,
121diff --git a/src/polkitbackend/polkitbackendinteractiveauthority.c b/src/polkitbackend/polkitbackendinteractiveauthority.c
122index 056d9a8..36c2f3d 100644
123--- a/src/polkitbackend/polkitbackendinteractiveauthority.c
124+++ b/src/polkitbackend/polkitbackendinteractiveauthority.c
125@@ -2233,25 +2233,26 @@ get_users_in_net_group (PolkitIdentity *group,
126 GList *ret;
127
128 ret = NULL;
129+#ifdef HAVE_SETNETGRENT
130 name = polkit_unix_netgroup_get_name (POLKIT_UNIX_NETGROUP (group));
131
132-#ifdef HAVE_SETNETGRENT_RETURN
133+# ifdef HAVE_SETNETGRENT_RETURN
134 if (setnetgrent (name) == 0)
135 {
136 g_warning ("Error looking up net group with name %s: %s", name, g_strerror (errno));
137 goto out;
138 }
139-#else
140+# else
141 setnetgrent (name);
142-#endif
143+# endif /* HAVE_SETNETGRENT_RETURN */
144
145 for (;;)
146 {
147-#if defined(HAVE_NETBSD) || defined(HAVE_OPENBSD)
148+# if defined(HAVE_NETBSD) || defined(HAVE_OPENBSD)
149 const char *hostname, *username, *domainname;
150-#else
151+# else
152 char *hostname, *username, *domainname;
153-#endif
154+# endif /* defined(HAVE_NETBSD) || defined(HAVE_OPENBSD) */
155 PolkitIdentity *user;
156 GError *error = NULL;
157
158@@ -2282,6 +2283,7 @@ get_users_in_net_group (PolkitIdentity *group,
159
160 out:
161 endnetgrent ();
162+#endif /* HAVE_SETNETGRENT */
163 return ret;
164 }
165
166diff --git a/src/polkitbackend/polkitbackendjsauthority.cpp b/src/polkitbackend/polkitbackendjsauthority.cpp
167index 5027815..bcb040c 100644
168--- a/src/polkitbackend/polkitbackendjsauthority.cpp
169+++ b/src/polkitbackend/polkitbackendjsauthority.cpp
170@@ -1524,6 +1524,7 @@ js_polkit_user_is_in_netgroup (JSContext *cx,
171
172 JS::CallArgs args = JS::CallArgsFromVp (argc, vp);
173
174+#ifdef HAVE_SETNETGRENT
175 JS::RootedString usrstr (authority->priv->cx);
176 usrstr = args[0].toString();
177 user = JS_EncodeStringToUTF8 (cx, usrstr);
178@@ -1538,6 +1539,7 @@ js_polkit_user_is_in_netgroup (JSContext *cx,
179 {
180 is_in_netgroup = true;
181 }
182+#endif
183
184 ret = true;
185
186diff --git a/test/polkit/polkitidentitytest.c b/test/polkit/polkitidentitytest.c
187index e91967b..2635c4c 100644
188--- a/test/polkit/polkitidentitytest.c
189+++ b/test/polkit/polkitidentitytest.c
190@@ -145,11 +145,15 @@ struct ComparisonTestData comparison_test_data [] = {
191 {"unix-group:root", "unix-group:jane", FALSE},
192 {"unix-group:jane", "unix-group:jane", TRUE},
193
194+#ifdef HAVE_SETNETGRENT
195 {"unix-netgroup:foo", "unix-netgroup:foo", TRUE},
196 {"unix-netgroup:foo", "unix-netgroup:bar", FALSE},
197+#endif
198
199 {"unix-user:root", "unix-group:root", FALSE},
200+#ifdef HAVE_SETNETGRENT
201 {"unix-user:jane", "unix-netgroup:foo", FALSE},
202+#endif
203
204 {NULL},
205 };
206@@ -181,11 +185,13 @@ main (int argc, char *argv[])
207 g_test_add_data_func ("/PolkitIdentity/group_string_2", "unix-group:jane", test_string);
208 g_test_add_data_func ("/PolkitIdentity/group_string_3", "unix-group:users", test_string);
209
210+#ifdef HAVE_SETNETGRENT
211 g_test_add_data_func ("/PolkitIdentity/netgroup_string", "unix-netgroup:foo", test_string);
212+ g_test_add_data_func ("/PolkitIdentity/netgroup_gvariant", "unix-netgroup:foo", test_gvariant);
213+#endif
214
215 g_test_add_data_func ("/PolkitIdentity/user_gvariant", "unix-user:root", test_gvariant);
216 g_test_add_data_func ("/PolkitIdentity/group_gvariant", "unix-group:root", test_gvariant);
217- g_test_add_data_func ("/PolkitIdentity/netgroup_gvariant", "unix-netgroup:foo", test_gvariant);
218
219 add_comparison_tests ();
220
221diff --git a/test/polkit/polkitunixnetgrouptest.c b/test/polkit/polkitunixnetgrouptest.c
222index 3701ba1..e1d211e 100644
223--- a/test/polkit/polkitunixnetgrouptest.c
224+++ b/test/polkit/polkitunixnetgrouptest.c
225@@ -69,7 +69,9 @@ int
226 main (int argc, char *argv[])
227 {
228 g_test_init (&argc, &argv, NULL);
229+#ifdef HAVE_SETNETGRENT
230 g_test_add_func ("/PolkitUnixNetgroup/new", test_new);
231 g_test_add_func ("/PolkitUnixNetgroup/set_name", test_set_name);
232+#endif
233 return g_test_run ();
234 }
235diff --git a/test/polkitbackend/test-polkitbackendjsauthority.c b/test/polkitbackend/test-polkitbackendjsauthority.c
236index f97e0e0..fc52149 100644
237--- a/test/polkitbackend/test-polkitbackendjsauthority.c
238+++ b/test/polkitbackend/test-polkitbackendjsauthority.c
239@@ -137,12 +137,14 @@ test_get_admin_identities (void)
240 "unix-group:users"
241 }
242 },
243+#ifdef HAVE_SETNETGRENT
244 {
245 "net.company.action3",
246 {
247 "unix-netgroup:foo"
248 }
249 },
250+#endif
251 };
252 guint n;
253
diff --git a/meta-oe/recipes-extended/polkit/polkit/0005-Make-netgroup-support-optional-duktape.patch b/meta-oe/recipes-extended/polkit/polkit/0005-Make-netgroup-support-optional-duktape.patch
deleted file mode 100644
index 12988ad94f..0000000000
--- a/meta-oe/recipes-extended/polkit/polkit/0005-Make-netgroup-support-optional-duktape.patch
+++ /dev/null
@@ -1,34 +0,0 @@
1From 792f8e2151c120ec51b50a4098e4f9642409cbec Mon Sep 17 00:00:00 2001
2From: Marta Rybczynska <rybczynska@gmail.com>
3Date: Fri, 29 Jul 2022 11:52:59 +0200
4Subject: [PATCH] Make netgroup support optional
5
6This patch adds a fragment of the netgroup patch to apply on the duktape-related
7code. This change is needed to compile with duktape+musl.
8
9Upstream-Status: Backport [https://gitlab.freedesktop.org/polkit/polkit/-/commit/b57deee8178190a7ecc75290fa13cf7daabc2c66]
10Signed-off-by: Marta Rybczynska <martarybczynska@huawei.com>
11---
12 src/polkitbackend/polkitbackendduktapeauthority.c | 2 ++
13 1 file changed, 2 insertions(+)
14
15diff --git a/src/polkitbackend/polkitbackendduktapeauthority.c b/src/polkitbackend/polkitbackendduktapeauthority.c
16index c89dbcf..58a5936 100644
17--- a/src/polkitbackend/polkitbackendduktapeauthority.c
18+++ b/src/polkitbackend/polkitbackendduktapeauthority.c
19@@ -1036,6 +1036,7 @@ js_polkit_user_is_in_netgroup (duk_context *cx)
20 user = duk_require_string (cx, 0);
21 netgroup = duk_require_string (cx, 1);
22
23+#ifdef HAVE_SETNETGRENT
24 if (innetgr (netgroup,
25 NULL, /* host */
26 user,
27@@ -1043,6 +1044,7 @@ js_polkit_user_is_in_netgroup (duk_context *cx)
28 {
29 is_in_netgroup = TRUE;
30 }
31+#endif
32
33 duk_push_boolean (cx, is_in_netgroup);
34 return 1;
diff --git a/meta-oe/recipes-extended/polkit/polkit/polkit-1_pam.patch b/meta-oe/recipes-extended/polkit/polkit/polkit-1_pam.patch
deleted file mode 100644
index c491abf4ac..0000000000
--- a/meta-oe/recipes-extended/polkit/polkit/polkit-1_pam.patch
+++ /dev/null
@@ -1,35 +0,0 @@
1polkit: No system-auth in OE-Core, we can use common-* in place of it.
2
3Upstream-Status:Inappropriate [configuration]
4
5Signed-off-by: Xiaofeng Yan <xiaofeng.yan@windriver.com>
6
7Upstream-Status: Inappropriate [oe specific]
8Rebase to 0.115
9Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
10---
11 configure.ac | 8 ++++----
12 1 file changed, 4 insertions(+), 4 deletions(-)
13
14diff --git a/configure.ac b/configure.ac
15index 36df239..8b3e1b1 100644
16--- a/configure.ac
17+++ b/configure.ac
18@@ -471,10 +471,10 @@ elif test x$with_os_type = xfreebsd -o x$with_os_type = xnetbsd; then
19 PAM_FILE_INCLUDE_PASSWORD=system
20 PAM_FILE_INCLUDE_SESSION=system
21 else
22- PAM_FILE_INCLUDE_AUTH=system-auth
23- PAM_FILE_INCLUDE_ACCOUNT=system-auth
24- PAM_FILE_INCLUDE_PASSWORD=system-auth
25- PAM_FILE_INCLUDE_SESSION=system-auth
26+ PAM_FILE_INCLUDE_AUTH=common-auth
27+ PAM_FILE_INCLUDE_ACCOUNT=common-account
28+ PAM_FILE_INCLUDE_PASSWORD=common-password
29+ PAM_FILE_INCLUDE_SESSION=common-session
30 fi
31
32 AC_SUBST(PAM_FILE_INCLUDE_AUTH)
33--
342.7.4
35
diff --git a/meta-oe/recipes-extended/polkit/polkit_0.119.bb b/meta-oe/recipes-extended/polkit/polkit_0.119.bb
deleted file mode 100644
index c4d3d25afc..0000000000
--- a/meta-oe/recipes-extended/polkit/polkit_0.119.bb
+++ /dev/null
@@ -1,79 +0,0 @@
1SUMMARY = "PolicyKit Authorization Framework"
2DESCRIPTION = "The polkit package is an application-level toolkit for defining and handling the policy that allows unprivileged processes to speak to privileged processes."
3HOMEPAGE = "http://www.freedesktop.org/wiki/Software/polkit"
4LICENSE = "LGPL-2.0-or-later"
5LIC_FILES_CHKSUM = "file://COPYING;md5=155db86cdbafa7532b41f390409283eb \
6 file://src/polkit/polkit.h;beginline=1;endline=20;md5=0a8630b0133176d0504c87a0ded39db4"
7
8DEPENDS = "expat glib-2.0 intltool-native"
9
10inherit autotools gtk-doc pkgconfig useradd systemd gobject-introspection features_check
11
12REQUIRED_DISTRO_FEATURES = "polkit"
13
14PACKAGECONFIG = "${@bb.utils.filter('DISTRO_FEATURES', 'pam', d)} \
15 ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'systemd', \
16 bb.utils.contains('DISTRO_FEATURES', 'x11', 'consolekit', '', d), d)} \
17 mozjs \
18 "
19
20PACKAGECONFIG[pam] = "--with-authfw=pam,--with-authfw=shadow,libpam,libpam"
21PACKAGECONFIG[systemd] = "--enable-libsystemd-login=yes --with-systemdsystemunitdir=${systemd_unitdir}/system/,--enable-libsystemd-login=no --with-systemdsystemunitdir=,systemd"
22# there is no --enable/--disable option for consolekit and it's not picked by shlibs, so add it to RDEPENDS
23PACKAGECONFIG[consolekit] = ",,,consolekit"
24
25# Default to mozjs javascript library
26PACKAGECONFIG[mozjs] = ",,mozjs-91,,,duktape"
27# duktape javascript engine is much smaller and faster but is not compatible with
28# same javascript standards as mozjs. For example array.includes() function is not
29# supported. Test rule compatibility when switching to duktape.
30PACKAGECONFIG[duktape] = "--with-duktape,,duktape,,,mozjs"
31
32MOZJS_PATCHES = "\
33 file://0002-jsauthority-port-to-mozjs-91.patch \
34 file://0003-jsauthority-ensure-to-call-JS_Init-and-JS_ShutDown-e.patch \
35"
36DUKTAPE_PATCHES = "file://0003-Added-support-for-duktape-as-JS-engine.patch"
37DUKTAPE_NG_PATCHES = "file://0005-Make-netgroup-support-optional-duktape.patch"
38PAM_SRC_URI = "file://polkit-1_pam.patch"
39SRC_URI = "http://www.freedesktop.org/software/polkit/releases/polkit-${PV}.tar.gz \
40 ${@bb.utils.contains('DISTRO_FEATURES', 'pam', '${PAM_SRC_URI}', '', d)} \
41 ${@bb.utils.contains('PACKAGECONFIG', 'mozjs', '${MOZJS_PATCHES}', '', d)} \
42 ${@bb.utils.contains('PACKAGECONFIG', 'duktape', '${DUKTAPE_PATCHES}', '', d)} \
43 file://0001-pkexec-local-privilege-escalation-CVE-2021-4034.patch \
44 file://0002-CVE-2021-4115-GHSL-2021-077-fix.patch \
45 file://0004-Make-netgroup-support-optional.patch \
46 ${@bb.utils.contains('PACKAGECONFIG', 'duktape', '${DUKTAPE_NG_PATCHES}', '', d)} \
47 "
48SRC_URI[sha256sum] = "c8579fdb86e94295404211285fee0722ad04893f0213e571bd75c00972fd1f5c"
49
50EXTRA_OECONF = "--with-os-type=moblin \
51 --disable-man-pages \
52 --disable-libelogind \
53 "
54
55do_configure:prepend () {
56 rm -f ${S}/buildutil/lt*.m4 ${S}/buildutil/libtool.m4
57}
58
59do_compile:prepend () {
60 export GIR_EXTRA_LIBS_PATH="${B}/src/polkit/.libs"
61}
62
63PACKAGES =+ "${PN}-examples"
64
65FILES:${PN}:append = " \
66 ${libdir}/${BPN}-1 \
67 ${nonarch_libdir}/${BPN}-1 \
68 ${datadir}/dbus-1 \
69 ${datadir}/${BPN}-1 \
70 ${datadir}/gettext \
71"
72
73FILES:${PN}-examples = "${bindir}/*example*"
74
75USERADD_PACKAGES = "${PN}"
76USERADD_PARAM:${PN} = "--system --no-create-home --user-group --home-dir ${sysconfdir}/${BPN}-1 --shell /bin/nologin polkitd"
77
78SYSTEMD_SERVICE:${PN} = "${BPN}.service"
79SYSTEMD_AUTO_ENABLE = "disable"