]> granicus.if.org Git - pdns/commitdiff
add lua-reccord-exec-limit option to pdns_server
authorCharles-Henri Bruyand <charles-henri.bruyand@open-xchange.com>
Thu, 19 Apr 2018 10:54:47 +0000 (12:54 +0200)
committerCharles-Henri Bruyand <charles-henri.bruyand@open-xchange.com>
Thu, 19 Apr 2018 11:35:18 +0000 (13:35 +0200)
docs/settings.rst
pdns/common_startup.cc
pdns/common_startup.hh
pdns/lua-record.cc
regression-tests.auth-py/test_LuaRecords.py

index 6fb06cd24e00081329da2fc2893f48bc59298fa8..fb4cc84d8f9c39cab985d538c05a1c4f82e2f650 100644 (file)
@@ -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``
index 5854e0e7a276622c58bd89d64e43710e8e544660..6ce7ef9947f5ba5492e3896f7b4a59fd1f914b66 100644 (file)
@@ -38,6 +38,7 @@ bool g_anyToTcp;
 bool g_8bitDNS;
 #ifdef HAVE_LUA_RECORDS
 bool g_doLuaRecord;
+int g_luaRecordExecLimit;
 #endif
 typedef Distributor<DNSPacket,DNSPacket,PacketHandler> 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"));
index 66e431f77c3b9e6f1618943615c17554656f6f25..1e1290ed57f30456169f8f473d8b808ea4834f1a 100644 (file)
@@ -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
index ead2dc599be4c1a2e1b06cab13c3cd78e52d7f9b..07aecc0bbd5bf8d1bb16506d06e082b0f0e2226c 100644 (file)
@@ -31,6 +31,8 @@
    Pool checks ?
  */
 
+extern int  g_luaRecordExecLimit;
+
 using iplist_t = vector<pair<int, string> >;
 using wiplist_t = std::unordered_map<int, string>;
 using ipunitlist_t = vector<pair<int, iplist_t> >;
@@ -760,7 +762,9 @@ std::vector<shared_ptr<DNSRecordContent>> luaSynth(const std::string& code, cons
   lua.writeFunction("report", [&counter](string event, boost::optional<string> 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) {
index 5d40f37b7c93895b32e01f3d0bc1b0150086a5d1..0e046a1e0fa4e69d5d89f0074eb9fc1d04bc6884 100644 (file)
@@ -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)