On 07/11/2016 00:57, Tommaso Cucinotta wrote:
if I run:

  lyxwrap rm /home/tommaso/whatever

it says "Permission denied" :-)!
So, the idea is to wrap execution of any external converter/plotter/etc., so 
that they can only write into the /tmp/ folder, except for the case of 
exporting to .pdf, .tex, etc.

The idea has become a working patchset (see attachments below).

commit c2d3d491
Author: Tommaso Cucinotta <tomm...@lyx.org>
Date:   Fri Nov 11 23:42:11 2016 +0100

    Hardening, calling all external tools through lyxwrap.
Addressing #10481.

commit 6a3fdab0
Author: Tommaso Cucinotta <tomm...@lyx.org>
Date:   Mon Nov 7 00:39:33 2016 +0100

    Added lyxwrap wrapper along with apparmor.d script for safe execution of 
external converters.
Addressing #10481.

        T.
--

>From 6a3fdab046100b222c49d8ab0abe735f8e0687e5 Mon Sep 17 00:00:00 2001
From: Tommaso Cucinotta <tomm...@lyx.org>
Date: Mon, 7 Nov 2016 00:39:33 +0100
Subject: [PATCH 1/2] Added lyxwrap wrapper along with apparmor.d script for
 safe execution of external converters.

Addressing #10481.
---
 configure.ac           |  1 +
 lib/Makefile.am        |  3 +++
 lib/usr.bin.lyxwrap.in | 15 +++++++++++++++
 src/Makefile.am        |  5 ++++-
 4 files changed, 23 insertions(+), 1 deletion(-)
 create mode 100644 lib/usr.bin.lyxwrap.in

diff --git a/configure.ac b/configure.ac
index 05e73285..773fe002 100644
--- a/configure.ac
+++ b/configure.ac
@@ -387,6 +387,7 @@ AC_CONFIG_FILES([Makefile \
       development/lyx.spec \
       lib/lyx.desktop-temp:lib/lyx.desktop.in
       lib/Makefile \
+      lib/usr.bin.lyxwrap \
       lib/doc/Makefile \
       lib/lyx2lyx/lyx2lyx_version.py \
       lib/lyx2lyx/Makefile \
diff --git a/lib/Makefile.am b/lib/Makefile.am
index a19d4f2c..4b2fedf6 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -2485,6 +2485,9 @@ install-data-hook:
 			chmod 644 "$(DESTDIR)$(pkgdatadir)/$$i"; \
 		fi; \
 	done
+if INSTALL_POSIX
+	cp usr.bin.lyxwrap /etc/apparmor.d/
+endif
 
 alltests: check alltests-recursive
 
diff --git a/lib/usr.bin.lyxwrap.in b/lib/usr.bin.lyxwrap.in
new file mode 100644
index 00000000..dd990d25
--- /dev/null
+++ b/lib/usr.bin.lyxwrap.in
@@ -0,0 +1,15 @@
+# vim:syntax=apparmor
+# Author: Tommaso Cucinotta <tomm...@lyx.org>
+
+#include <tunables/global>
+
+@prefix@/bin/lyxwrap {
+  /tmp/** ixrw,
+  @{HOME}/** ixr,
+  / ixr,
+  /** ixr,
+  deny /etc/security/ xrw,
+  deny /etc/security/** xrw,
+  deny /etc/passwd* xrw,
+  deny /etc/shadow* xrw,
+}
diff --git a/src/Makefile.am b/src/Makefile.am
index 8ac13067..4e51ba5b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -25,7 +25,7 @@ OTHERLIBS = $(BOOST_LIBS) $(MYTHES_LIBS) $(ENCHANT_LIBS) $(HUNSPELL_LIBS) \
 	    $(LIBSHLWAPI) $(LIBPSAPI)
 
 noinst_LIBRARIES = liblyxcore.a
-bin_PROGRAMS = lyx
+bin_PROGRAMS = lyx lyxwrap
 
 lyx_LDADD = \
 	liblyxcore.a \
@@ -100,6 +100,9 @@ if LYX_WIN_RESOURCE
 lyx_SOURCES += lyxwinres.rc
 endif
 
+lyxwrap_SOURCES = \
+	lyxwrap.cpp
+
 SOURCEFILESCORE = \
 	Author.cpp \
 	boost.cpp \
-- 
2.9.3

>From c2d3d4910705b97048e7c66a5bc218df247b31c6 Mon Sep 17 00:00:00 2001
From: Tommaso Cucinotta <tomm...@lyx.org>
Date: Fri, 11 Nov 2016 23:42:11 +0100
Subject: [PATCH 2/2] Hardening, calling all external tools through lyxwrap.

Addressing #10481.
---
 lib/configure.py          |  2 +-
 lib/usr.bin.lyxwrap.in    | 20 ++++++++++++++------
 src/LyXRC.cpp             | 19 +++++++++++++++++++
 src/LyXRC.h               |  3 +++
 src/support/filetools.cpp | 16 +++++++++++++++-
 5 files changed, 52 insertions(+), 8 deletions(-)

diff --git a/lib/configure.py b/lib/configure.py
index 705aed6c..b72032e8 100644
--- a/lib/configure.py
+++ b/lib/configure.py
@@ -1020,7 +1020,7 @@ def checkConverterEntries():
     #
     checkProg('Gnuplot', ['gnuplot'], 
         rc_entry = [ r'''\Format gnuplot     "gp, gnuplot"    "Gnuplot"     "" "" ""  "vector"	"text/plain"
-\converter gnuplot      pdf6      "python -tt $$s/scripts/gnuplot2pdf.py $$i $$o"    ""''' ])
+\converter gnuplot      pdf6      "python -tt $$s/scripts/gnuplot2pdf.py $$i $$o"    "needauth"''' ])
     #
     # gnumeric/xls/ods to tex
     checkProg('a spreadsheet -> latex converter', ['ssconvert'],
diff --git a/lib/usr.bin.lyxwrap.in b/lib/usr.bin.lyxwrap.in
index dd990d25..e7fc6e36 100644
--- a/lib/usr.bin.lyxwrap.in
+++ b/lib/usr.bin.lyxwrap.in
@@ -3,13 +3,21 @@
 
 #include <tunables/global>
 
-@prefix@/bin/lyxwrap {
-  /tmp/** ixrw,
+@prefix@/bin/lyxwrap@version_suffix@ {
+  #include <abstractions/dbus>
+  #include <abstractions/dbus-session>
+  #include <abstractions/dbus-accessibility>
+  #include <abstractions/X>
+  #include <abstractions/gnome>
+
+  owner /tmp/** ixrwl,
   @{HOME}/** ixr,
+  @{HOME}/.lyx@version_suffix@** ixrwl,
+  @{HOME}/.config/LyX** ixrwl,
   / ixr,
   /** ixr,
-  deny /etc/security/ xrw,
-  deny /etc/security/** xrw,
-  deny /etc/passwd* xrw,
-  deny /etc/shadow* xrw,
+  deny /etc/security/ xrwl,
+  deny /etc/security/** xrwl,
+  deny /etc/passwd* xrwl,
+  deny /etc/shadow* xrwl,
 }
diff --git a/src/LyXRC.cpp b/src/LyXRC.cpp
index b16ed6a8..df55c6b0 100644
--- a/src/LyXRC.cpp
+++ b/src/LyXRC.cpp
@@ -189,6 +189,7 @@ LexerKeyword lyxrcTags[] = {
 	{ "\\thesaurusdir_path", LyXRC::RC_THESAURUSDIRPATH },
 	{ "\\ui_file", LyXRC::RC_UIFILE },
 	{ "\\use_converter_cache", LyXRC::RC_USE_CONVERTER_CACHE },
+	{ "\\use_converter_hardening", LyXRC::RC_USE_CONVERTER_HARDENING },
 	{ "\\use_lastfilepos", LyXRC::RC_USELASTFILEPOS },
 	{ "\\use_pixmap_cache", LyXRC::RC_USE_PIXMAP_CACHE },
 	{ "\\use_qimage", LyXRC::RC_USE_QIMAGE },
@@ -317,6 +318,7 @@ void LyXRC::setDefaults()
 	preview_hashed_labels  = false;
 	preview_scale_factor = 1.0;
 	use_converter_cache = true;
+	use_converter_hardening = true;
 	use_system_colors = false;
 	use_tooltip = true;
 	use_pixmap_cache = false;
@@ -1116,6 +1118,9 @@ LyXRC::ReturnValues LyXRC::read(Lexer & lexrc, bool check_format)
 		case RC_USE_CONVERTER_CACHE:
 			lexrc >> use_converter_cache;
 			break;
+		case RC_USE_CONVERTER_HARDENING:
+			lexrc >> use_converter_hardening;
+			break;
 		case RC_CONVERTER_CACHE_MAXAGE:
 			lexrc >> converter_cache_maxage;
 			break;
@@ -1602,6 +1607,15 @@ void LyXRC::write(ostream & os, bool ignore_system_lyxrc, string const & name) c
 		if (tag != RC_LAST)
 			break;
 
+	case RC_USE_CONVERTER_HARDENING:
+		if (ignore_system_lyxrc ||
+		    use_converter_hardening != system_lyxrc.use_converter_hardening) {
+			os << "\\use_converter_hardening "
+			   << convert<string>(use_converter_hardening) << '\n';
+		}
+		if (tag != RC_LAST)
+			break;
+
 	case RC_CONVERTER_CACHE_MAXAGE:
 		if (ignore_system_lyxrc ||
 		    converter_cache_maxage != system_lyxrc.converter_cache_maxage) {
@@ -2843,6 +2857,7 @@ void actOnUpdatedPrefs(LyXRC const & lyxrc_orig, LyXRC const & lyxrc_new)
 	case LyXRC::RC_USER_EMAIL:
 	case LyXRC::RC_USER_NAME:
 	case LyXRC::RC_USE_CONVERTER_CACHE:
+	case LyXRC::RC_USE_CONVERTER_HARDENING:
 	case LyXRC::RC_USE_SYSTEM_COLORS:
 	case LyXRC::RC_USE_TOOLTIP:
 	case LyXRC::RC_USE_PIXMAP_CACHE:
@@ -2935,6 +2950,10 @@ string const LyXRC::getDescription(LyXRCTags tag)
 	case RC_CONVERTER:
 		break;
 
+	case RC_CONVERTER_HARDENING:
+		str = _("Apply hardening techniques when calling external converters to prevent undesired effects.");
+		break;
+
 	case RC_COPIER:
 		break;
 
diff --git a/src/LyXRC.h b/src/LyXRC.h
index f3202f89..4d9beb12 100644
--- a/src/LyXRC.h
+++ b/src/LyXRC.h
@@ -168,6 +168,7 @@ public:
 		RC_USER_EMAIL,
 		RC_USER_NAME,
 		RC_USE_CONVERTER_CACHE,
+		RC_USE_CONVERTER_HARDENING,
 		RC_USE_SYSTEM_COLORS,
 		RC_USE_TOOLTIP,
 		RC_USE_PIXMAP_CACHE,
@@ -446,6 +447,8 @@ public:
 	std::string texinputs_prefix;
 	/// Use the cache for file converters?
 	bool use_converter_cache;
+	/// Apply hardening when calling external converters
+	bool use_converter_hardening;
 	/// The maximum age of cache files in seconds
 	unsigned int converter_cache_maxage;
 	/// Sort layouts alphabetically
diff --git a/src/support/filetools.cpp b/src/support/filetools.cpp
index 12457cb3..d9e7ef76 100644
--- a/src/support/filetools.cpp
+++ b/src/support/filetools.cpp
@@ -417,7 +417,7 @@ FileName const imageLibFileSearch(string & dir, string const & name,
 }
 
 
-string const commandPrep(string const & command_in)
+static string const commandPrepAux(string const & command_in)
 {
 	static string const token_scriptpath = "$$s/";
 	string const python_call = "python -tt";
@@ -458,6 +458,20 @@ string const commandPrep(string const & command_in)
 }
 
 
+string const commandPrep(string const & cmd)
+{
+	if (os::shell() == os::UNIX && lyxrc.use_converter_hardening) {
+		string const wrap_cmd = string("lyxwrap") + PROGRAM_SUFFIX + " " + commandPrepAux(cmd);
+		LYXERR(Debug::FILES, "commandPrep(): " + wrap_cmd);
+		return wrap_cmd;
+	} else {
+		string const cmd_aux = commandPrepAux(cmd);
+		LYXERR(Debug::FILES, "commandPrep(): " + cmd_aux);
+		return cmd_aux;
+	}
+}
+
+
 static string createTempFile(QString const & mask)
 {
 	// FIXME: This is not safe. QTemporaryFile creates a file in open(),
-- 
2.9.3

Reply via email to