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