From: Charles-Henri Bruyand Date: Thu, 19 Apr 2018 10:54:47 +0000 (+0200) Subject: add lua-reccord-exec-limit option to pdns_server X-Git-Tag: dnsdist-1.3.1~136^2~3 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=af68014f773bb56560c898cc246f59a8cea54c9b;p=pdns add lua-reccord-exec-limit option to pdns_server --- diff --git a/docs/settings.rst b/docs/settings.rst index 6fb06cd24..fb4cc84d8 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -544,6 +544,16 @@ disables caching. Enables EDNS subnet processing, for backends that support it. +.. _setting-enable-lua-records: + +``enable-lua-records`` +-------------------------- + +- Boolean +- Default: no + +Enable globally the LUA records feature + .. _setting-entropy-source: ``entropy-source`` @@ -690,6 +700,17 @@ Disable this if the process supervisor timestamps these lines already. .. note:: The systemd unit file supplied with the source code already disables timestamp printing +.. _setting-lua-record-exec-limit: + +``lua-record-exec-limit`` +----------------------------- + +- Integer +- Default: 1000 + +Limit LUA record scripts to ``lua-record-exec-limit`` instructions. +Setting this to any value less than or equal to 0 will set no limit. + .. _setting-non-local-bind: ``non-local-bind`` diff --git a/pdns/common_startup.cc b/pdns/common_startup.cc index 5854e0e7a..6ce7ef994 100644 --- a/pdns/common_startup.cc +++ b/pdns/common_startup.cc @@ -38,6 +38,7 @@ bool g_anyToTcp; bool g_8bitDNS; #ifdef HAVE_LUA_RECORDS bool g_doLuaRecord; +int g_luaRecordExecLimit; #endif typedef Distributor DNSDistributor; @@ -201,7 +202,10 @@ void declareArguments() ::arg().setSwitch("expand-alias", "Expand ALIAS records")="no"; ::arg().setSwitch("outgoing-axfr-expand-alias", "Expand ALIAS records during outgoing AXFR")="no"; ::arg().setSwitch("8bit-dns", "Allow 8bit dns queries")="no"; +#ifdef HAVE_LUA_RECORDS ::arg().setSwitch("enable-lua-record", "Process LUA record for all zones (metadata overrides this)")="no"; + ::arg().set("lua-record-exec-limit", "LUA record scripts execution limit (instructions count). Values <= 0 mean no limit")="1000"; +#endif ::arg().setSwitch("axfr-lower-serial", "Also AXFR a zone from a master with a lower serial")="no"; ::arg().set("lua-axfr-script", "Script to be used to edit incoming AXFRs")=""; @@ -493,6 +497,7 @@ void mainthread() g_8bitDNS = ::arg().mustDo("8bit-dns"); #ifdef HAVE_LUA_RECORDS g_doLuaRecord = ::arg().mustDo("enable-lua-record"); + g_luaRecordExecLimit = ::arg().asNum("lua-record-exec-limit"); #endif DNSPacket::s_udpTruncationThreshold = std::max(512, ::arg().asNum("udp-truncation-threshold")); diff --git a/pdns/common_startup.hh b/pdns/common_startup.hh index 66e431f77..1e1290ed5 100644 --- a/pdns/common_startup.hh +++ b/pdns/common_startup.hh @@ -55,6 +55,8 @@ extern int isGuarded( char ** ); void* carbonDumpThread(void*); extern bool g_anyToTcp; extern bool g_8bitDNS; +#ifdef HAVE_LUA_RECORDS extern bool g_doLuaRecord; +#endif // HAVE_LUA_RECORDS #endif // COMMON_STARTUP_HH diff --git a/pdns/lua-record.cc b/pdns/lua-record.cc index ead2dc599..07aecc0bb 100644 --- a/pdns/lua-record.cc +++ b/pdns/lua-record.cc @@ -31,6 +31,8 @@ Pool checks ? */ +extern int g_luaRecordExecLimit; + using iplist_t = vector >; using wiplist_t = std::unordered_map; using ipunitlist_t = vector >; @@ -760,7 +762,9 @@ std::vector> luaSynth(const std::string& code, cons lua.writeFunction("report", [&counter](string event, boost::optional line){ throw std::runtime_error("Script took too long"); }); - lua.executeCode("debug.sethook(report, '', 1000000)"); + if (g_luaRecordExecLimit > 0) { + lua.executeCode(boost::str(boost::format("debug.sethook(report, '', %d)") % g_luaRecordExecLimit)); + } // TODO: make this better. Accept netmask/CA objects; provide names for the attr constants lua.writeFunction("geoiplookup", [](const string &ip, const GeoIPInterface::GeoIPQueryAttribute attr) { diff --git a/regression-tests.auth-py/test_LuaRecords.py b/regression-tests.auth-py/test_LuaRecords.py index 5d40f37b7..0e046a1e0 100644 --- a/regression-tests.auth-py/test_LuaRecords.py +++ b/regression-tests.auth-py/test_LuaRecords.py @@ -52,6 +52,7 @@ v6-bogus.rand.example.org. 3600 IN LUA AAAA "pickrandom({{'{prefix}.101', '{ v6.rand.example.org. 3600 IN LUA AAAA "pickrandom({{'2001:db8:a0b:12f0::1', 'fe80::2a1:9bff:fe9b:f268'}})" closest.geo 3600 IN LUA A "pickclosest({{'1.1.1.2','1.2.3.4'}})" empty.rand.example.org. 3600 IN LUA A "pickrandom()" +timeout.example.org. 3600 IN LUA A "; local i = 0 ; while i < 500 do i = i + 1 end return '1.2.3.4'" wrand.example.org. 3600 IN LUA A "pickwrandom({{ {{30, '{prefix}.102'}}, {{15, '{prefix}.103'}} }})" config IN LUA LUA ("settings={{stringmatch='Programming in Lua'}} " @@ -512,6 +513,15 @@ www-balanced IN CNAME 1-1-1-3.17-1-2-4.1-2-3-5.magic.example.org. self.assertRcodeEqual(res, dns.rcode.NOERROR) self.assertRRsetInAnswer(res, first.answer[0]) + def testTimeout(self): + """ + Test if LUA scripts are aborted if script execution takes too long + """ + query = dns.message.make_query('timeout.example.org', 'A') + + first = self.sendUDPQuery(query) + self.assertRcodeEqual(first, dns.rcode.SERVFAIL) + if __name__ == '__main__': unittest.main() exit(0)