[Libreoffice-commits] online.git: 7 commits - common/Protocol.hpp common/Seccomp.cpp common/Seccomp.hpp kit/ForKit.cpp kit/Kit.cpp loleaflet/admin.strings.js loleaflet/dist loleaflet/src loolwsd.xml.in wsd/Admin.cpp wsd/Admin.hpp wsd/AdminModel.hpp wsd/LOOLWSD.cpp wsd/LOOLWSD.hpp
Ashod Nakashian
ashod.nakashian at collabora.co.uk
Mon Jun 12 05:08:00 UTC 2017
common/Protocol.hpp | 15 ++++
common/Seccomp.cpp | 89 +++++++++++++++++++++++++++--
common/Seccomp.hpp | 4 +
kit/ForKit.cpp | 28 +++++++++
kit/Kit.cpp | 33 ++++++++++
loleaflet/admin.strings.js | 4 +
loleaflet/dist/admin/adminSettings.html | 8 ++
loleaflet/src/admin/AdminSocketSettings.js | 4 +
loolwsd.xml.in | 4 +
wsd/Admin.cpp | 78 +++++++++++++++++++------
wsd/Admin.hpp | 15 ++++
wsd/AdminModel.hpp | 14 ++++
wsd/LOOLWSD.cpp | 39 ++++++++++--
wsd/LOOLWSD.hpp | 2
14 files changed, 307 insertions(+), 30 deletions(-)
New commits:
commit 459249b17759d5f15fe17b96bdd7897b0c8b47ba
Author: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
Date: Sun Jun 11 23:47:48 2017 -0400
wsd: apply rlimits set from Admin Console to ForKit
Change-Id: I425c28ce08c5ecd659c4fe8eaa1a7ed3634e7f18
Reviewed-on: https://gerrit.libreoffice.org/38678
Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>
Tested-by: Ashod Nakashian <ashnakash at gmail.com>
diff --git a/wsd/Admin.cpp b/wsd/Admin.cpp
index 0fc64aaa..ca1bc950 100644
--- a/wsd/Admin.cpp
+++ b/wsd/Admin.cpp
@@ -331,6 +331,7 @@ Admin::Admin() :
SocketPoll("admin"),
_model(AdminModel()),
_forKitPid(-1),
+ _forKitWritePipe(-1),
_lastTotalMemory(0),
_lastJiffies(0),
_memStatsTaskIntervalMs(5000),
@@ -497,6 +498,16 @@ void Admin::addBytes(const std::string& docKey, uint64_t sent, uint64_t recv)
{ _model.addBytes(docKey, sent, recv); });
}
+void Admin::notifyForkit()
+{
+ std::ostringstream oss;
+ oss << "setconfig limit_virt_mem_mb " << _defDocProcSettings.LimitVirtMemMb << '\n'
+ << "setconfig limit_data_mem_kb " << _defDocProcSettings.LimitDataMemKb << '\n'
+ << "setconfig limit_stack_mem_kb " << _defDocProcSettings.LimitStackMemKb << '\n'
+ << "setconfig limit_file_size_mb " << _defDocProcSettings.LimitFileSizeMb << '\n';
+ IoUtil::writeToPipe(_forKitWritePipe, oss.str());
+}
+
void Admin::dumpState(std::ostream& os)
{
// FIXME: be more helpful ...
diff --git a/wsd/Admin.hpp b/wsd/Admin.hpp
index 4faa3df2..5ca87572 100644
--- a/wsd/Admin.hpp
+++ b/wsd/Admin.hpp
@@ -86,6 +86,7 @@ public:
void rmDoc(const std::string& docKey);
void setForKitPid(const int forKitPid) { _forKitPid = forKitPid; }
+ void setForKitWritePipe(const int forKitWritePipe) { _forKitWritePipe = forKitWritePipe; }
/// Callers must ensure that modelMutex is acquired
AdminModel& getModel();
@@ -105,13 +106,22 @@ public:
void dumpState(std::ostream& os) override;
const DocProcSettings& getDefDocProcSettings() const { return _defDocProcSettings; }
- void setDefDocProcSettings(const DocProcSettings& docProcSettings) { _defDocProcSettings = docProcSettings; }
+ void setDefDocProcSettings(const DocProcSettings& docProcSettings)
+ {
+ _defDocProcSettings = docProcSettings;
+ notifyForkit();
+ }
+
+private:
+ /// Notify Forkit of changed settings.
+ void notifyForkit();
private:
/// The model is accessed only during startup & in
/// the Admin Poll thread.
AdminModel _model;
int _forKitPid;
+ int _forKitWritePipe;
size_t _lastTotalMemory;
size_t _lastJiffies;
diff --git a/wsd/LOOLWSD.cpp b/wsd/LOOLWSD.cpp
index bdc10893..0aead10a 100644
--- a/wsd/LOOLWSD.cpp
+++ b/wsd/LOOLWSD.cpp
@@ -807,6 +807,13 @@ void LOOLWSD::initialize(Application& self)
ServerApplication::initialize(self);
+ DocProcSettings docProcSettings;
+ docProcSettings.LimitVirtMemMb = getConfigValue<int>("per_document.limit_virt_mem_mb", 0);
+ docProcSettings.LimitDataMemKb = getConfigValue<int>("per_document.limit_data_mem_kb", 0);
+ docProcSettings.LimitStackMemKb = getConfigValue<int>("per_document.limit_stack_mem_kb", 0);
+ docProcSettings.LimitFileSizeMb = getConfigValue<int>("per_document.limit_file_size_mb", 0);
+ Admin::instance().setDefDocProcSettings(docProcSettings);
+
#if ENABLE_DEBUG
std::cerr << "\nLaunch this in your browser:\n\n"
<< getLaunchURI() << '\n' << std::endl;
@@ -1163,13 +1170,7 @@ bool LOOLWSD::createForKit()
args.push_back("--clientport=" + std::to_string(ClientPortNumber));
args.push_back("--masterport=" + std::to_string(MasterPortNumber));
- DocProcSettings docProcSettings;
- docProcSettings.LimitVirtMemMb = getConfigValue<int>("per_document.limit_virt_mem_mb", 0);
- docProcSettings.LimitDataMemKb = getConfigValue<int>("per_document.limit_data_mem_kb", 0);
- docProcSettings.LimitStackMemKb = getConfigValue<int>("per_document.limit_stack_mem_kb", 0);
- docProcSettings.LimitFileSizeMb = getConfigValue<int>("per_document.limit_file_size_mb", 0);
- Admin::instance().setDefDocProcSettings(docProcSettings);
-
+ const DocProcSettings& docProcSettings = Admin::instance().getDefDocProcSettings();
std::ostringstream ossRLimits;
ossRLimits << "limit_virt_mem_mb:" << docProcSettings.LimitVirtMemMb;
ossRLimits << ";limit_data_mem_kb:" << docProcSettings.LimitDataMemKb;
@@ -1199,14 +1200,20 @@ bool LOOLWSD::createForKit()
std::unique_lock<std::mutex> newChildrenLock(NewChildrenMutex);
// Always reap first, in case we haven't done so yet.
- int status;
- waitpid(ForKitProcId, &status, WUNTRACED | WNOHANG);
- ForKitProcId = -1;
- Admin::instance().setForKitPid(ForKitProcId);
+ if (ForKitProcId != -1)
+ {
+ int status;
+ waitpid(ForKitProcId, &status, WUNTRACED | WNOHANG);
+ ForKitProcId = -1;
+ Admin::instance().setForKitPid(ForKitProcId);
+ }
if (ForKitWritePipe != -1)
+ {
close(ForKitWritePipe);
- ForKitWritePipe = -1;
+ ForKitWritePipe = -1;
+ Admin::instance().setForKitWritePipe(ForKitWritePipe);
+ }
// ForKit always spawns one.
++OutstandingForks;
@@ -1227,6 +1234,7 @@ bool LOOLWSD::createForKit()
// Init the Admin manager
Admin::instance().setForKitPid(ForKitProcId);
+ Admin::instance().setForKitWritePipe(ForKitWritePipe);
return ForKitProcId != -1;
#endif
commit 9e11cd7db711b86fadbc0a2d00920268779233d2
Author: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
Date: Sun Jun 11 22:51:38 2017 -0400
Support setting rlimits from Admin Console
Change-Id: Ia0d45948998d7a5612a1828a90ad20908d07639e
Reviewed-on: https://gerrit.libreoffice.org/38677
Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>
Tested-by: Ashod Nakashian <ashnakash at gmail.com>
diff --git a/loleaflet/admin.strings.js b/loleaflet/admin.strings.js
index 9bc38b29..0850a61a 100644
--- a/loleaflet/admin.strings.js
+++ b/loleaflet/admin.strings.js
@@ -32,6 +32,10 @@ l10nstrings.strMemoryStatsCachesize = _('Cache size of memory statistics');
l10nstrings.strMemoryStatsInterval = _('Time interval of memory statistics (in ms)');
l10nstrings.strCpuStatsCachesize = _('Cache size of CPU statistics');
l10nstrings.strCpuStatsInterval = _('Time interval of CPU statistics (in ms)');
+l10nstrings.strLimitVirtMemMb = _('Maximum Document process virtual memory (in MB)');
+l10nstrings.strLimitDataMemKb = _('Maximum Document process data memory (in KB)');
+l10nstrings.strLimitStackMemKb = _('Maximum Document process stack memory (in KB)');
+l10nstrings.strLimitFileSizeMb = _('Maximum file size allowed to write to disk (in MB)');
if (module) {
module.exports = l10nstrings;
diff --git a/loleaflet/dist/admin/adminSettings.html b/loleaflet/dist/admin/adminSettings.html
index baaeac99..668c67d9 100644
--- a/loleaflet/dist/admin/adminSettings.html
+++ b/loleaflet/dist/admin/adminSettings.html
@@ -84,6 +84,14 @@
<input type="text" id="cpu_stats_size" name="Cpu Stats Size"><br/>
<label for="cpu_stats_interval"><script>document.write(l10nstrings.strCpuStatsInterval)</script></label>
<input type="text" id="cpu_stats_interval" name="Cpu Stats Interval"><br/>
+ <label for="limit_virt_mem_mb"><script>document.write(l10nstrings.strLimitVirtMemMb)</script></label>
+ <input type="text" id="limit_virt_mem_mb" name="Max Document Virtual Memory MB"><br/>
+ <label for="limit_data_mem_kb"><script>document.write(l10nstrings.strLimitDataMemKb)</script></label>
+ <input type="text" id="limit_data_mem_kb" name="Max Document Data Memory KB"><br/>
+ <label for="limit_stack_mem_kb"><script>document.write(l10nstrings.strLimitStackMemKb)</script></label>
+ <input type="text" id="limit_stack_mem_kb" name="Max Document Stack Memory Kb"><br/>
+ <label for="limit_file_size_mb"><script>document.write(l10nstrings.strLimitFileSizeMb)</script></label>
+ <input type="text" id="limit_file_size_mb" name="Max File Write Size Mb"><br/>
<script>document.write('<input type="submit" value="' + l10nstrings.strSave + '"/><br/>')</script>
</form>
<br />
diff --git a/loleaflet/src/admin/AdminSocketSettings.js b/loleaflet/src/admin/AdminSocketSettings.js
index c03a05ba..27c0be90 100644
--- a/loleaflet/src/admin/AdminSocketSettings.js
+++ b/loleaflet/src/admin/AdminSocketSettings.js
@@ -23,6 +23,10 @@ var AdminSocketSettings = AdminSocketBase.extend({
command += ' mem_stats_interval=' + memStatsInterval;
command += ' cpu_stats_size=' + cpuStatsSize;
command += ' cpu_stats_interval=' + cpuStatsInterval;
+ command += ' limit_virt_mem_mb=' + $('#limit_virt_mem_mb').val();
+ command += ' limit_data_mem_kb=' + $('#limit_data_mem_kb').val();
+ command += ' limit_stack_mem_kb=' + $('#limit_stack_mem_kb').val();
+ command += ' limit_file_size_mb=' + $('#limit_file_size_mb').val();
socketSettings.send(command);
});
diff --git a/wsd/Admin.cpp b/wsd/Admin.cpp
index 425a352d..0fc64aaa 100644
--- a/wsd/Admin.cpp
+++ b/wsd/Admin.cpp
@@ -166,14 +166,19 @@ void AdminSocketHandler::handleMessage(bool /* fin */, WSOpCode /* code */,
{
// for now, we have only these settings
std::ostringstream oss;
- oss << tokens[0] << " "
- << "mem_stats_size=" << model.query("mem_stats_size") << " "
- << "mem_stats_interval=" << std::to_string(_admin->getMemStatsInterval()) << " "
- << "cpu_stats_size=" << model.query("cpu_stats_size") << " "
- << "cpu_stats_interval=" << std::to_string(_admin->getCpuStatsInterval());
-
- std::string responseFrame = oss.str();
- sendTextFrame(responseFrame);
+ oss << "settings "
+ << "mem_stats_size=" << model.query("mem_stats_size") << ' '
+ << "mem_stats_interval=" << std::to_string(_admin->getMemStatsInterval()) << ' '
+ << "cpu_stats_size=" << model.query("cpu_stats_size") << ' '
+ << "cpu_stats_interval=" << std::to_string(_admin->getCpuStatsInterval()) << ' ';
+
+ const DocProcSettings& docProcSettings = _admin->getDefDocProcSettings();
+ oss << "limit_virt_mem_mb=" << docProcSettings.LimitVirtMemMb << ' '
+ << "limit_data_mem_kb=" << docProcSettings.LimitDataMemKb << ' '
+ << "limit_stack_mem_kb=" << docProcSettings.LimitStackMemKb << ' '
+ << "limit_file_size_mb=" << docProcSettings.LimitFileSizeMb << ' ';
+
+ sendTextFrame(oss.str());
}
else if (tokens[0] == "shutdown")
{
@@ -187,7 +192,7 @@ void AdminSocketHandler::handleMessage(bool /* fin */, WSOpCode /* code */,
for (size_t i = 1; i < tokens.count(); i++)
{
StringTokenizer setting(tokens[i], "=", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
- unsigned settingVal = 0;
+ int settingVal = 0;
try
{
settingVal = std::stoi(setting[1]);
@@ -199,38 +204,66 @@ void AdminSocketHandler::handleMessage(bool /* fin */, WSOpCode /* code */,
return;
}
- if (setting[0] == "mem_stats_size")
+ const std::string settingName = setting[0];
+ if (settingName == "mem_stats_size")
{
- if (settingVal != static_cast<unsigned>(std::stoi(model.query(setting[0]))))
+ if (settingVal != std::stoi(model.query(settingName)))
{
model.setMemStatsSize(settingVal);
}
}
- else if (setting[0] == "mem_stats_interval")
+ else if (settingName == "mem_stats_interval")
{
- if (settingVal != _admin->getMemStatsInterval())
+ if (settingVal != static_cast<int>(_admin->getMemStatsInterval()))
{
_admin->rescheduleMemTimer(settingVal);
model.clearMemStats();
model.notify("settings mem_stats_interval=" + std::to_string(settingVal));
}
}
- else if (setting[0] == "cpu_stats_size")
+ else if (settingName == "cpu_stats_size")
{
- if (settingVal != static_cast<unsigned>(std::stoi(model.query(setting[0]))))
+ if (settingVal != std::stoi(model.query(settingName)))
{
model.setCpuStatsSize(settingVal);
}
}
- else if (setting[0] == "cpu_stats_interval")
+ else if (settingName == "cpu_stats_interval")
{
- if (settingVal != _admin->getCpuStatsInterval())
+ if (settingVal != static_cast<int>(_admin->getCpuStatsInterval()))
{
_admin->rescheduleCpuTimer(settingVal);
model.clearCpuStats();
model.notify("settings cpu_stats_interval=" + std::to_string(settingVal));
}
}
+ else if (LOOLProtocol::matchPrefix("limit_", settingName))
+ {
+ DocProcSettings docProcSettings = _admin->getDefDocProcSettings();
+ if (settingName == "limit_virt_mem_mb")
+ {
+ docProcSettings.LimitVirtMemMb = settingVal;
+ }
+ else if (settingName == "limit_data_mem_kb")
+ {
+ docProcSettings.LimitDataMemKb = settingVal;
+ }
+ else if (settingName == "limit_stack_mem_kb")
+ {
+ docProcSettings.LimitStackMemKb = settingVal;
+ }
+ else if (settingName == "limit_file_size_mb")
+ {
+ docProcSettings.LimitFileSizeMb = settingVal;
+ }
+ else
+ {
+ LOG_ERR("Unknown limit: " << settingName);
+ }
+
+ model.notify("settings " + settingName + '=' + std::to_string(settingVal));
+ _admin->setDefDocProcSettings(docProcSettings);
+ }
}
}
}
diff --git a/wsd/Admin.hpp b/wsd/Admin.hpp
index 91df8108..4faa3df2 100644
--- a/wsd/Admin.hpp
+++ b/wsd/Admin.hpp
@@ -104,6 +104,9 @@ public:
void dumpState(std::ostream& os) override;
+ const DocProcSettings& getDefDocProcSettings() const { return _defDocProcSettings; }
+ void setDefDocProcSettings(const DocProcSettings& docProcSettings) { _defDocProcSettings = docProcSettings; }
+
private:
/// The model is accessed only during startup & in
/// the Admin Poll thread.
@@ -114,6 +117,8 @@ private:
std::atomic<int> _memStatsTaskIntervalMs;
std::atomic<int> _cpuStatsTaskIntervalMs;
+
+ DocProcSettings _defDocProcSettings;
};
#endif
diff --git a/wsd/AdminModel.hpp b/wsd/AdminModel.hpp
index 90716964..96231bda 100644
--- a/wsd/AdminModel.hpp
+++ b/wsd/AdminModel.hpp
@@ -43,6 +43,14 @@ private:
std::time_t _end = 0;
};
+struct DocProcSettings
+{
+ size_t LimitVirtMemMb;
+ size_t LimitDataMemKb;
+ size_t LimitStackMemKb;
+ size_t LimitFileSizeMb;
+};
+
/// A document in Admin controller.
class Document
{
@@ -100,6 +108,9 @@ public:
_recvBytes += recv;
}
+ const DocProcSettings& getDocProcSettings() const { return _docProcSettings; }
+ void setDocProcSettings(const DocProcSettings& docProcSettings) { _docProcSettings = docProcSettings; }
+
std::string to_string() const;
private:
@@ -124,6 +135,9 @@ private:
/// Total bytes sent and recv'd by this document.
uint64_t _sentBytes, _recvBytes;
+
+ /// Per-doc kit process settings.
+ DocProcSettings _docProcSettings;
};
/// An Admin session subscriber.
diff --git a/wsd/LOOLWSD.cpp b/wsd/LOOLWSD.cpp
index 4033a876..bdc10893 100644
--- a/wsd/LOOLWSD.cpp
+++ b/wsd/LOOLWSD.cpp
@@ -811,7 +811,7 @@ void LOOLWSD::initialize(Application& self)
std::cerr << "\nLaunch this in your browser:\n\n"
<< getLaunchURI() << '\n' << std::endl;
- std::string adminURI = getAdminURI(config());
+ const std::string adminURI = getAdminURI(config());
if (!adminURI.empty())
std::cerr << "\nOr for the Admin Console:\n\n"
<< adminURI << '\n' << std::endl;
@@ -1163,11 +1163,18 @@ bool LOOLWSD::createForKit()
args.push_back("--clientport=" + std::to_string(ClientPortNumber));
args.push_back("--masterport=" + std::to_string(MasterPortNumber));
+ DocProcSettings docProcSettings;
+ docProcSettings.LimitVirtMemMb = getConfigValue<int>("per_document.limit_virt_mem_mb", 0);
+ docProcSettings.LimitDataMemKb = getConfigValue<int>("per_document.limit_data_mem_kb", 0);
+ docProcSettings.LimitStackMemKb = getConfigValue<int>("per_document.limit_stack_mem_kb", 0);
+ docProcSettings.LimitFileSizeMb = getConfigValue<int>("per_document.limit_file_size_mb", 0);
+ Admin::instance().setDefDocProcSettings(docProcSettings);
+
std::ostringstream ossRLimits;
- ossRLimits << "limit_virt_mem_mb:" << getConfigValue<int>("per_document.limit_virt_mem_mb", 0);
- ossRLimits << ";limit_data_mem_kb:" << getConfigValue<int>("per_document.limit_data_mem_kb", 0);
- ossRLimits << ";limit_stack_mem_kb:" << getConfigValue<int>("per_document.limit_stack_mem_kb", 0);
- ossRLimits << ";limit_file_size_mb:" << getConfigValue<int>("per_document.limit_file_size_mb", 0);
+ ossRLimits << "limit_virt_mem_mb:" << docProcSettings.LimitVirtMemMb;
+ ossRLimits << ";limit_data_mem_kb:" << docProcSettings.LimitDataMemKb;
+ ossRLimits << ";limit_stack_mem_kb:" << docProcSettings.LimitStackMemKb;
+ ossRLimits << ";limit_file_size_mb:" << docProcSettings.LimitFileSizeMb;
args.push_back("--rlimits=" + ossRLimits.str());
if (UnitWSD::get().hasKitHooks())
commit 36fb1e64f0b707420ed9cc775af8b10767375746
Author: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
Date: Sun Jun 11 11:54:46 2017 -0400
wsd: new internal command to change config values
Change-Id: I8b4a573ba7b01ee6e7b3b91a00e12cc744f85fa8
Reviewed-on: https://gerrit.libreoffice.org/38676
Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>
Tested-by: Ashod Nakashian <ashnakash at gmail.com>
diff --git a/kit/ForKit.cpp b/kit/ForKit.cpp
index 9aa83a20..ed3d2f2a 100644
--- a/kit/ForKit.cpp
+++ b/kit/ForKit.cpp
@@ -111,6 +111,18 @@ public:
LOG_WRN("Cannot spawn " << tokens[1] << " children as requested.");
}
}
+ else if (tokens.size() == 3 && tokens[0] == "setconfig")
+ {
+ // Currently onlly rlimit entries are supported.
+ if (!Seccomp::handleSetrlimitCommand(tokens))
+ {
+ LOG_ERR("Unknown setconfig command: " << message);
+ }
+ }
+ else
+ {
+ LOG_ERR("Unknown command: " << message);
+ }
}
catch (const std::exception& exc)
{
diff --git a/kit/Kit.cpp b/kit/Kit.cpp
index e6c56b5e..b445c31f 100644
--- a/kit/Kit.cpp
+++ b/kit/Kit.cpp
@@ -1831,7 +1831,7 @@ void lokit_main(const std::string& childRoot,
#endif
LOG_DBG(socketName << ": recv [" << LOOLProtocol::getAbbreviatedMessage(message) << "].");
- StringTokenizer tokens(message, " ", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
+ std::vector<std::string> tokens = LOOLProtocol::tokenize(message);
// Note: Syntax or parsing errors here are unexpected and fatal.
if (TerminationFlag)
@@ -1877,6 +1877,14 @@ void lokit_main(const std::string& childRoot,
LOG_WRN("No document while processing " << tokens[0] << " request.");
}
}
+ else if (tokens.size() == 3 && tokens[0] == "setconfig")
+ {
+ // Currently onlly rlimit entries are supported.
+ if (!Seccomp::handleSetrlimitCommand(tokens))
+ {
+ LOG_ERR("Unknown setconfig command: " << message);
+ }
+ }
else
{
LOG_ERR("Bad or unknown token [" << tokens[0] << "]");
commit 6de3adcf9ce385152412a7a062245cb751a69cb6
Author: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
Date: Sun Jun 11 11:48:24 2017 -0400
wsd: pass default rlimits to forkit from config
Change-Id: I84d271f460f0fb1d03a973107c32265d84bf2841
Reviewed-on: https://gerrit.libreoffice.org/38675
Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>
Tested-by: Ashod Nakashian <ashnakash at gmail.com>
diff --git a/common/Protocol.hpp b/common/Protocol.hpp
index cae54d46..e26703d5 100644
--- a/common/Protocol.hpp
+++ b/common/Protocol.hpp
@@ -161,6 +161,21 @@ namespace LOOLProtocol
return std::string(message, size);
}
+ /// Split a string in two at the delimeter, removing it.
+ inline
+ std::pair<std::string, std::string> split(const char* s, const int length, const char delimeter = ' ')
+ {
+ const auto size = getDelimiterPosition(s, length, delimeter);
+ return std::make_pair(std::string(s, size), std::string(s+size+1));
+ }
+
+ /// Split a string in two at the delimeter, removing it.
+ inline
+ std::pair<std::string, std::string> split(const std::string& s, const char delimeter = ' ')
+ {
+ return split(s.c_str(), s.size(), delimeter);
+ }
+
/// Returns the first token of a message.
inline
std::string getFirstToken(const char *message, const int length, const char delim = ' ')
diff --git a/kit/ForKit.cpp b/kit/ForKit.cpp
index ab11f626..9aa83a20 100644
--- a/kit/ForKit.cpp
+++ b/kit/ForKit.cpp
@@ -37,6 +37,7 @@
#include "Util.hpp"
#include "common/FileUtil.hpp"
+#include "common/Seccomp.hpp"
#include "common/SigUtil.hpp"
#include "security.h"
@@ -419,6 +420,21 @@ int main(int argc, char** argv)
std::cout << "loolforkit version details: " << version << " - " << hash << std::endl;
DisplayVersion = true;
}
+ else if (std::strstr(cmd, "--rlimits") == cmd)
+ {
+ eq = std::strchr(cmd, '=');
+ const std::string rlimits = std::string(eq+1);
+ std::vector<std::string> tokens = LOOLProtocol::tokenize(rlimits, ';');
+ for (const std::string& cmdLimit : tokens)
+ {
+ const auto pair = LOOLProtocol::split(cmdLimit, ':');
+ std::vector<std::string> tokensLimit = { "setconfig", pair.first, pair.second };
+ if (!Seccomp::handleSetrlimitCommand(tokensLimit))
+ {
+ LOG_ERR("Unknown rlimits command: " << cmdLimit);
+ }
+ }
+ }
#if ENABLE_DEBUG
// this process has various privileges - don't run arbitrary code.
else if (std::strstr(cmd, "--unitlib=") == cmd)
diff --git a/wsd/LOOLWSD.cpp b/wsd/LOOLWSD.cpp
index e8e3acc2..4033a876 100644
--- a/wsd/LOOLWSD.cpp
+++ b/wsd/LOOLWSD.cpp
@@ -1162,6 +1162,14 @@ bool LOOLWSD::createForKit()
args.push_back("--childroot=" + ChildRoot);
args.push_back("--clientport=" + std::to_string(ClientPortNumber));
args.push_back("--masterport=" + std::to_string(MasterPortNumber));
+
+ std::ostringstream ossRLimits;
+ ossRLimits << "limit_virt_mem_mb:" << getConfigValue<int>("per_document.limit_virt_mem_mb", 0);
+ ossRLimits << ";limit_data_mem_kb:" << getConfigValue<int>("per_document.limit_data_mem_kb", 0);
+ ossRLimits << ";limit_stack_mem_kb:" << getConfigValue<int>("per_document.limit_stack_mem_kb", 0);
+ ossRLimits << ";limit_file_size_mb:" << getConfigValue<int>("per_document.limit_file_size_mb", 0);
+ args.push_back("--rlimits=" + ossRLimits.str());
+
if (UnitWSD::get().hasKitHooks())
{
args.push_back("--unitlib=" + UnitTestLibrary);
diff --git a/wsd/LOOLWSD.hpp b/wsd/LOOLWSD.hpp
index a608c6c1..d98ecebe 100644
--- a/wsd/LOOLWSD.hpp
+++ b/wsd/LOOLWSD.hpp
@@ -166,7 +166,7 @@ private:
ConfigValueGetter(config, name)(value);
return true;
}
- catch (const Poco::SyntaxException&)
+ catch (const std::exception&)
{
}
commit 42969b732c312215a2955f3b85139a9e7e2fab19
Author: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
Date: Sun Jun 11 11:47:23 2017 -0400
wsd: log the relevant rlimits at Kit startup
Change-Id: I6ada56d9bda80301ab55de2c831452b21aa362c1
Reviewed-on: https://gerrit.libreoffice.org/38674
Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>
Tested-by: Ashod Nakashian <ashnakash at gmail.com>
diff --git a/kit/Kit.cpp b/kit/Kit.cpp
index 0358e7f9..e6c56b5e 100644
--- a/kit/Kit.cpp
+++ b/kit/Kit.cpp
@@ -19,6 +19,8 @@
#include <sys/capability.h>
#include <unistd.h>
#include <utime.h>
+#include <sys/time.h>
+#include <sys/resource.h>
#include <atomic>
#include <cassert>
@@ -1764,6 +1766,27 @@ void lokit_main(const std::string& childRoot,
std::_Exit(Application::EXIT_SOFTWARE);
}
+ rlimit rlim = { 0, 0 };
+ if (getrlimit(RLIMIT_AS, &rlim) == 0)
+ LOG_INF("RLIMIT_AS is " << rlim.rlim_max << " bytes.");
+ else
+ LOG_SYS("Failed to get RLIMIT_AS.");
+
+ if (getrlimit(RLIMIT_DATA, &rlim) == 0)
+ LOG_INF("RLIMIT_DATA is " << rlim.rlim_max << " bytes.");
+ else
+ LOG_SYS("Failed to get RLIMIT_DATA.");
+
+ if (getrlimit(RLIMIT_STACK, &rlim) == 0)
+ LOG_INF("RLIMIT_STACK is " << rlim.rlim_max << " bytes.");
+ else
+ LOG_SYS("Failed to get RLIMIT_STACK.");
+
+ if (getrlimit(RLIMIT_NOFILE, &rlim) == 0)
+ LOG_INF("RLIMIT_NOFILE is " << rlim.rlim_max << " bytes.");
+ else
+ LOG_SYS("Failed to get RLIMIT_NOFILE.");
+
assert(loKit);
LOG_INF("Process is ready.");
commit 9cb82cebe3edf1e6d9c6cac6e433abbc638c26f6
Author: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
Date: Sun Jun 11 11:39:15 2017 -0400
wsd: add rlimit config entries and defaults
Change-Id: I8cb498d01bc1a7a55d168e49c754bb1bba80aea1
Reviewed-on: https://gerrit.libreoffice.org/38673
Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>
Tested-by: Ashod Nakashian <ashnakash at gmail.com>
diff --git a/loolwsd.xml.in b/loolwsd.xml.in
index eed51283..8ec29c82 100644
--- a/loolwsd.xml.in
+++ b/loolwsd.xml.in
@@ -15,6 +15,10 @@
<per_document desc="Document-specific settings, including LO Core settings.">
<max_concurrency desc="The maximum number of threads to use while processing a document." type="uint" default="4">4</max_concurrency>
<idle_timeout_secs desc="The maximum number of seconds before unloading an idle document. Defaults to 1 hour." type="uint" default="3600">3600</idle_timeout_secs>
+ <limit_virt_mem_kb desc="The maximum virtual memory allowed to each document process. 0 for unlimited, 1700 min." type="uint">0</limit_virt_mem_kb>
+ <limit_data_mem_kb desc="The maximum memory data segment allowed to each document process. 0 for unlimited." type="uint">0</limit_data_mem_kb>
+ <limit_stack_mem_kb desc="The maximum stack size allowed to each document process. 0 for unlimited." type="uint">8000</limit_stack_mem_kb>
+ <limit_file_size_mb desc="The maximum file size allowed to each documen process to write. 0 for unlimited." type="uint">50</limit_file_size_mb>
</per_document>
<per_view desc="View-specific settings.">
diff --git a/wsd/LOOLWSD.cpp b/wsd/LOOLWSD.cpp
index 07d371c8..e8e3acc2 100644
--- a/wsd/LOOLWSD.cpp
+++ b/wsd/LOOLWSD.cpp
@@ -624,6 +624,10 @@ void LOOLWSD::initialize(Application& self)
{ "num_prespawn_children", "1" },
{ "per_document.max_concurrency", "4" },
{ "per_document.idle_timeout_secs", "3600" },
+ { "per_document.limit_virt_mem_mb", "0" },
+ { "per_document.limit_data_mem_kb", "0" },
+ { "per_document.limit_stack_mem_kb", "8000" },
+ { "per_document.limit_file_size_mb", "50" },
{ "per_view.out_of_focus_timeout_secs", "60" },
{ "per_view.idle_timeout_secs", "900" },
{ "loleaflet_html", "loleaflet.html" },
commit 92d29b1ce752f9562d6a98e5219bbcac6197d431
Author: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
Date: Sat Jun 10 20:41:30 2017 -0400
wsd: support setting process rlimits
Change-Id: I7117e6843d2ebc919d7d2303cc593de888cc54b1
Reviewed-on: https://gerrit.libreoffice.org/38672
Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>
Tested-by: Ashod Nakashian <ashnakash at gmail.com>
diff --git a/common/Seccomp.cpp b/common/Seccomp.cpp
index 092f1a5d..52fedb01 100644
--- a/common/Seccomp.cpp
+++ b/common/Seccomp.cpp
@@ -15,15 +15,17 @@
#include <dlfcn.h>
#include <ftw.h>
+#include <linux/audit.h>
+#include <linux/filter.h>
+#include <linux/seccomp.h>
#include <malloc.h>
+#include <signal.h>
#include <sys/capability.h>
+#include <sys/prctl.h>
+#include <sys/resource.h>
+#include <sys/time.h>
#include <unistd.h>
#include <utime.h>
-#include <signal.h>
-#include <sys/prctl.h>
-#include <linux/audit.h>
-#include <linux/filter.h>
-#include <linux/seccomp.h>
#include <common/Log.hpp>
#include <common/SigUtil.hpp>
@@ -214,6 +216,83 @@ bool lockdown(Type type)
return true;
}
+bool handleSetrlimitCommand(const std::vector<std::string>& tokens)
+{
+ if (tokens.size() == 3 && tokens[0] == "setconfig")
+ {
+ if (tokens[1] == "limit_virt_mem_mb")
+ {
+ rlim_t lim = std::stoi(tokens[2]) * 1024 * 1024;
+ if (lim <= 0)
+ lim = RLIM_INFINITY;
+
+ rlimit rlim = { lim, lim };
+ if (setrlimit(RLIMIT_AS, &rlim) != 0)
+ LOG_SYS("Failed to set RLIMIT_AS to " << lim << " bytes.");
+
+ if (getrlimit(RLIMIT_AS, &rlim) == 0)
+ LOG_INF("RLIMIT_AS is " << rlim.rlim_max << " bytes after setting it to " << lim << " bytes.");
+ else
+ LOG_SYS("Failed to get RLIMIT_AS.");
+
+ return true;
+ }
+ else if (tokens[1] == "limit_data_mem_kb")
+ {
+ rlim_t lim = std::stoi(tokens[2]) * 1024;
+ if (lim <= 0)
+ lim = RLIM_INFINITY;
+
+ rlimit rlim = { lim, lim };
+ if (setrlimit(RLIMIT_DATA, &rlim) != 0)
+ LOG_SYS("Failed to set RLIMIT_DATA to " << lim << " bytes.");
+
+ if (getrlimit(RLIMIT_DATA, &rlim) == 0)
+ LOG_INF("RLIMIT_DATA is " << rlim.rlim_max << " bytes after setting it to " << lim << " bytes.");
+ else
+ LOG_SYS("Failed to get RLIMIT_DATA.");
+
+ return true;
+ }
+ else if (tokens[1] == "limit_stack_mem_kb")
+ {
+ rlim_t lim = std::stoi(tokens[2]) * 1024;
+ if (lim <= 0)
+ lim = RLIM_INFINITY;
+
+ rlimit rlim = { lim, lim };
+ if (setrlimit(RLIMIT_STACK, &rlim) != 0)
+ LOG_SYS("Failed to set RLIMIT_STACK to " << lim << " bytes.");
+
+ if (getrlimit(RLIMIT_STACK, &rlim) == 0)
+ LOG_INF("RLIMIT_STACK is " << rlim.rlim_max << " bytes after setting it to " << lim << " bytes.");
+ else
+ LOG_SYS("Failed to get RLIMIT_STACK.");
+
+ return true;
+ }
+ else if (tokens[1] == "limit_file_size_mb")
+ {
+ rlim_t lim = std::stoi(tokens[2]) * 1024 * 1024;
+ if (lim <= 0)
+ lim = RLIM_INFINITY;
+
+ rlimit rlim = { lim, lim };
+ if (setrlimit(RLIMIT_NOFILE, &rlim) != 0)
+ LOG_SYS("Failed to set RLIMIT_NOFILE to " << lim << " bytes.");
+
+ if (getrlimit(RLIMIT_NOFILE, &rlim) == 0)
+ LOG_INF("RLIMIT_NOFILE is " << rlim.rlim_max << " bytes after setting it to " << lim << " bytes.");
+ else
+ LOG_SYS("Failed to get RLIMIT_NOFILE.");
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
} // namespace Seccomp
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/common/Seccomp.hpp b/common/Seccomp.hpp
index 865b5c91..f6d1a130 100644
--- a/common/Seccomp.hpp
+++ b/common/Seccomp.hpp
@@ -14,6 +14,10 @@ namespace Seccomp {
/// Lock-down a process hard - @returns true on success.
bool lockdown(Type type);
+
+ /// Handles setconfig command with limit_... subcommands.
+ /// Returns true iff it handled the command, regardless of success/failure.
+ bool handleSetrlimitCommand(const std::vector<std::string>& tokens);
};
#endif
More information about the Libreoffice-commits
mailing list