Merge pull request #2356 from sebres/0.10-th-stack-size

default thread stack size
pull/2366/head
Sergey G. Brester 2019-03-01 12:33:03 +01:00 committed by GitHub
commit 415818d803
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 63 additions and 7 deletions

View File

@ -52,6 +52,9 @@ ver. 0.10.5-dev-1 (20??/??/??) - development edition
* `filter.d/traefik-auth.conf`: used to ban hosts, that were failed through traefik * `filter.d/traefik-auth.conf`: used to ban hosts, that were failed through traefik
### Enhancements ### Enhancements
* fail2ban.conf: introduced new section `[Thread]` and option `stacksize` to configure default size
of the stack for threads running in fail2ban (gh-2356), it could be set in `fail2ban.local` to
avoid runtime error "can't start new thread" (see gh-969);
* jail-reader extended (amend to gh-1622): actions support multi-line options now (interpolations * jail-reader extended (amend to gh-1622): actions support multi-line options now (interpolations
containing new-line); containing new-line);
* fail2ban-client: extended to ban/unban multiple tickets (see gh-2351, gh-2349); * fail2ban-client: extended to ban/unban multiple tickets (see gh-2351, gh-2349);

View File

@ -67,3 +67,11 @@ dbfile = /var/lib/fail2ban/fail2ban.sqlite3
# Notes.: Sets age at which bans should be purged from the database # Notes.: Sets age at which bans should be purged from the database
# Values: [ SECONDS ] Default: 86400 (24hours) # Values: [ SECONDS ] Default: 86400 (24hours)
dbpurgeage = 1d dbpurgeage = 1d
[Thread]
# Options: stacksize
# Notes.: Specifies the stack size (in KiB) to be used for subsequently created threads,
# and must be 0 or a positive integer value of at least 32.
# Values: [ SIZE ] Default: 0 (use platform or configured default)
#stacksize = 0

View File

@ -239,8 +239,10 @@ class ConfigReaderUnshared(SafeConfigParserWithIncludes):
try: try:
if opttype == "bool": if opttype == "bool":
v = self.getboolean(sec, optname) v = self.getboolean(sec, optname)
if v is None: continue
elif opttype == "int": elif opttype == "int":
v = self.getint(sec, optname) v = self.getint(sec, optname)
if v is None: continue
else: else:
v = self.get(sec, optname, vars=pOptions) v = self.get(sec, optname, vars=pOptions)
values[optname] = v values[optname] = v

View File

@ -60,12 +60,19 @@ class Fail2banReader(ConfigReader):
self.__opts.update(updateMainOpt) self.__opts.update(updateMainOpt)
# check given log-level: # check given log-level:
str2LogLevel(self.__opts.get('loglevel', 0)) str2LogLevel(self.__opts.get('loglevel', 0))
# thread options:
opts = [["int", "stacksize", ],
]
if self.has_section("Thread"):
thopt = ConfigReader.getOptions(self, "Thread", opts)
if thopt:
self.__opts['thread'] = thopt
def convert(self): def convert(self):
# Ensure logtarget/level set first so any db errors are captured # Ensure logtarget/level set first so any db errors are captured
# Also dbfile should be set before all other database options. # Also dbfile should be set before all other database options.
# So adding order indices into items, to be stripped after sorting, upon return # So adding order indices into items, to be stripped after sorting, upon return
order = {"syslogsocket":0, "loglevel":1, "logtarget":2, order = {"thread":0, "syslogsocket":11, "loglevel":12, "logtarget":13,
"dbfile":50, "dbpurgeage":51} "dbfile":50, "dbpurgeage":51}
stream = list() stream = list()
for opt in self.__opts: for opt in self.__opts:

View File

@ -709,6 +709,16 @@ class Server:
logSys.info("flush performed on %s" % self.__logTarget) logSys.info("flush performed on %s" % self.__logTarget)
return "flushed" return "flushed"
def setThreadOptions(self, value):
for o, v in value.iteritems():
if o == 'stacksize':
threading.stack_size(int(v)*1024)
else: # pragma: no cover
raise KeyError("unknown option %r" % o)
def getThreadOptions(self):
return {'stacksize': threading.stack_size() // 1024}
def setDatabase(self, filename): def setDatabase(self, filename):
# if not changed - nothing to do # if not changed - nothing to do
if self.__db and self.__db.filename == filename: if self.__db and self.__db.filename == filename:

View File

@ -170,6 +170,10 @@ class Transmitter:
return self.__server.getSyslogSocket() return self.__server.getSyslogSocket()
else: else:
raise Exception("Failed to change syslog socket") raise Exception("Failed to change syslog socket")
#Thread
elif name == "thread":
value = command[1]
return self.__server.setThreadOptions(value)
#Database #Database
elif name == "dbfile": elif name == "dbfile":
self.__server.setDatabase(command[1]) self.__server.setDatabase(command[1])
@ -384,6 +388,9 @@ class Transmitter:
return self.__server.getLogTarget() return self.__server.getLogTarget()
elif name == "syslogsocket": elif name == "syslogsocket":
return self.__server.getSyslogSocket() return self.__server.getSyslogSocket()
#Thread
elif name == "thread":
return self.__server.getThreadOptions()
#Database #Database
elif name == "dbfile": elif name == "dbfile":
db = self.__server.getDatabase() db = self.__server.getDatabase()

View File

@ -140,7 +140,8 @@ def _read_file(fn):
def _start_params(tmp, use_stock=False, use_stock_cfg=None, def _start_params(tmp, use_stock=False, use_stock_cfg=None,
logtarget="/dev/null", db=":memory:", jails=("",), create_before_start=None logtarget="/dev/null", db=":memory:", f2b_local=(), jails=("",),
create_before_start=None,
): ):
cfg = pjoin(tmp, "config") cfg = pjoin(tmp, "config")
if db == 'auto': if db == 'auto':
@ -190,6 +191,9 @@ def _start_params(tmp, use_stock=False, use_stock_cfg=None,
if unittest.F2B.log_level < logging.DEBUG: # pragma: no cover if unittest.F2B.log_level < logging.DEBUG: # pragma: no cover
_out_file(pjoin(cfg, "fail2ban.conf")) _out_file(pjoin(cfg, "fail2ban.conf"))
_out_file(pjoin(cfg, "jail.conf")) _out_file(pjoin(cfg, "jail.conf"))
if f2b_local:
_write_file(pjoin(cfg, "fail2ban.local"), "w", *f2b_local)
# link stock actions and filters: # link stock actions and filters:
if use_stock_cfg and STOCK: if use_stock_cfg and STOCK:
for n in use_stock_cfg: for n in use_stock_cfg:
@ -431,8 +435,16 @@ class Fail2banClientServerBase(LogCaptureTestCase):
phase['end'] = True phase['end'] = True
logSys.debug("end of test worker") logSys.debug("end of test worker")
@with_foreground_server_thread() @with_foreground_server_thread(startextra={'f2b_local':(
"[Thread]",
"stacksize = 32"
"",
)})
def testStartForeground(self, tmp, startparams): def testStartForeground(self, tmp, startparams):
# check thread options were set:
self.pruneLog()
self.execCmd(SUCCESS, startparams, "get", "thread")
self.assertLogged("{'stacksize': 32}")
# several commands to server: # several commands to server:
self.execCmd(SUCCESS, startparams, "ping") self.execCmd(SUCCESS, startparams, "ping")
self.execCmd(FAILED, startparams, "~~unknown~cmd~failed~~") self.execCmd(FAILED, startparams, "~~unknown~cmd~failed~~")

View File

@ -127,9 +127,7 @@ Comments: use '#' for comment lines and '; ' (space is important) for inline com
.SH "FAIL2BAN CONFIGURATION FILE(S) (\fIfail2ban.conf\fB)" .SH "FAIL2BAN CONFIGURATION FILE(S) (\fIfail2ban.conf\fB)"
These files have one section, [Definition]. The items that can be set in section [Definition] are:
The items that can be set are:
.TP .TP
.B loglevel .B loglevel
verbosity level of log output: CRITICAL, ERROR, WARNING, NOTICE, INFO, DEBUG, TRACEDEBUG, HEAVYDEBUG or corresponding numeric value (50-5). Default: ERROR (equal 40) verbosity level of log output: CRITICAL, ERROR, WARNING, NOTICE, INFO, DEBUG, TRACEDEBUG, HEAVYDEBUG or corresponding numeric value (50-5). Default: ERROR (equal 40)
@ -163,6 +161,15 @@ Database purge age in seconds. Default: 86400 (24hours)
.br .br
This sets the age at which bans should be purged from the database. This sets the age at which bans should be purged from the database.
.RE
The config parameters of section [Thread] are:
.TP
.B stacksize
Stack size of each thread in fail2ban. Default: 0 (platform or configured default)
.br
This specifies the stack size (in KiB) to be used for subsequently created threads, and must be 0 or a positive integer value of at least 32.
.SH "JAIL CONFIGURATION FILE(S) (\fIjail.conf\fB)" .SH "JAIL CONFIGURATION FILE(S) (\fIjail.conf\fB)"
The following options are applicable to any jail. They appear in a section specifying the jail name or in the \fI[DEFAULT]\fR section which defines default values to be used if not specified in the individual section. The following options are applicable to any jail. They appear in a section specifying the jail name or in the \fI[DEFAULT]\fR section which defines default values to be used if not specified in the individual section.
.TP .TP