From: Gary Lockyer Date: Mon, 17 Sep 2018 23:21:40 +0000 (+1200) Subject: s4 smbd standard tests: limit forked processes X-Git-Tag: tdb-1.3.17~533 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=2381b4ff6794ba514cca57d3995459bc2cef8352;p=thirdparty%2Fsamba.git s4 smbd standard tests: limit forked processes Tests to confirm the standard process model honours the smbd.conf variable "max smbd processes", when forking a new process on accept. Signed-off-by: Gary Lockyer Reviewed-by: Andrew Bartlett --- diff --git a/python/samba/tests/process_limits.py b/python/samba/tests/process_limits.py new file mode 100644 index 00000000000..b62906e294f --- /dev/null +++ b/python/samba/tests/process_limits.py @@ -0,0 +1,78 @@ +# Tests for limiting processes forked on accept by the standard process model +# +# Copyright (C) Andrew Bartlett 2018 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +from __future__ import print_function +"""Tests limits on processes forked by fork on accept in the standard process + model. + NOTE: This test runs in an environment with an artificially low setting for + smbd max processes +""" + + +import os +from samba.tests import TestCase +from samba.samdb import SamDB +from ldb import LdbError, ERR_OPERATIONS_ERROR + + +class StandardModelProcessLimitTests(TestCase): + + def setUp(self): + super(StandardModelProcessLimitTests, self).setUp() + + def tearDown(self): + super(StandardModelProcessLimitTests, self).tearDown() + + def simple_bind(self): + creds = self.insta_creds(template=self.get_credentials()) + creds.set_bind_dn("%s\\%s" % (creds.get_domain(), + creds.get_username())) + + return SamDB(url="ldaps://%s" % os.environ["SERVER"], + lp=self.get_loadparm(), + credentials=creds) + + def test_process_limits(self): + creds = self.insta_creds(template=self.get_credentials()) + creds.set_bind_dn("%s\\%s" % (creds.get_domain(), + creds.get_username())) + + connections = [] + try: + # Open a series of LDAP connections, the maximum number of + # active connections should be 20, so the 21st should fail. + # But as it is possible that there may be other processes holding + # connections, need to allow for earlier connection failures. + for _ in range(21): + connections.append(self.simple_bind()) + self.fail( + "Processes not limited, able to make more than 20 connections") + except LdbError as e: + (errno, estr) = e.args + if errno != ERR_OPERATIONS_ERROR: + raise + if not (estr.endswith("NT_STATUS_CONNECTION_DISCONNECTED") or + estr.endswith("NT_STATUS_CONNECTION_RESET")): + raise + pass + # + # Clean up the connections we've just opened, by deleting the + # connection in python. This should invoke the talloc destructor to + # release any resources and close the actual connection to the server. + for c in connections: + del c diff --git a/selftest/knownfail.d/process_limit b/selftest/knownfail.d/process_limit new file mode 100644 index 00000000000..db34dae23ca --- /dev/null +++ b/selftest/knownfail.d/process_limit @@ -0,0 +1 @@ +^samba.tests.process_limits.samba.tests.process_limits.StandardModelProcessLimitTests.test_process_limits diff --git a/selftest/target/README b/selftest/target/README index b25dbab97da..36b68d5dd24 100644 --- a/selftest/target/README +++ b/selftest/target/README @@ -108,3 +108,10 @@ preforkrestartdc testenv Used to test killing and restarting processes under the pre-fork model. Due to the destructive nature of the tests, it's not recommended to use this testenv for anything else. + +proclimitdc testenv +------------------- +Used to test process limits on the standard model. It sets the number of +allowed processes artificially low, to test that new connections are refused +correctly. Due to the limited number of connections accepted, it's not +recommended to use this testenv for anything else. diff --git a/selftest/target/Samba.pm b/selftest/target/Samba.pm index f5c490fb05b..4820f987fd7 100644 --- a/selftest/target/Samba.pm +++ b/selftest/target/Samba.pm @@ -425,6 +425,7 @@ sub get_interface($) $interfaces{"offlinebackupdc"} = 44; $interfaces{"customdc"} = 45; $interfaces{"prockilldc"} = 46; + $interfaces{"proclimitdc"} = 47; # update lib/socket_wrapper/socket_wrapper.c # #define MAX_WRAPPED_INTERFACES 64 diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm index 0a6c85d1ba7..c54942b61fd 100755 --- a/selftest/target/Samba4.pm +++ b/selftest/target/Samba4.pm @@ -2228,6 +2228,7 @@ sub check_env($$) renamedc => ["backupfromdc"], offlinebackupdc => ["backupfromdc"], labdc => ["backupfromdc"], + proclimitdc => [], none => [], ); @@ -2688,6 +2689,44 @@ sub setup_preforkrestartdc return $env; } +# +# ad_dc test environment used solely to test standard process model connection +# process limits. As the limit is set artificially low it should not be used +# for other tests. +sub setup_proclimitdc +{ + my ($self, $path) = @_; + + # If we didn't build with ADS, pretend this env was never available + if (not $self->{target3}->have_ads()) { + return "UNKNOWN"; + } + + my $env = $self->provision_ad_dc( + $path, + "proclimitdc", + "PROCLIMITDOM", + "proclimit.samba.example.com", + "max smbd processes = 20"); + unless ($env) { + return undef; + } + + $env->{NSS_WRAPPER_MODULE_SO_PATH} = undef; + $env->{NSS_WRAPPER_MODULE_FN_PREFIX} = undef; + + if (not defined($self->check_or_start($env, "standard"))) { + return undef; + } + + my $upn_array = ["$env->{REALM}.upn"]; + my $spn_array = ["$env->{REALM}.spn"]; + + $self->setup_namespaces($env, $upn_array, $spn_array); + + return $env; +} + # Sets up a DC that's solely used to do a domain backup from. We then use the # backupfrom-DC to create the restore-DC - this proves that the backup/restore # process will create a Samba DC that will actually start up. diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 972f65307d8..575c14b8be2 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -1249,3 +1249,12 @@ planoldpythontestsuite("preforkrestartdc:local", extra_args=['-U"$USERNAME%$PASSWORD"'], name="samba.tests.prefork_restart", py3_compatible=True) +planoldpythontestsuite("proclimitdc:local", + "samba.tests.process_limits", + extra_path=[ + os.path.join(srcdir(), 'python/samba/tests')], + extra_args=['-U"$USERNAME%$PASSWORD"'], + environ={'CLIENT_IP': '127.0.0.11', + 'SOCKET_WRAPPER_DEFAULT_IFACE': 11}, + name="samba.tests.process_limits", + py3_compatible=True)