Skip to content

Commit

Permalink
Disable NSS modules when using the leakchecker
Browse files Browse the repository at this point in the history
The leakchecker will report leaked file descriptors when tests do things
like access `Etc.getgrgid`, for example, if NSS modules (like `sss`)
handle these lookups by connecting to a daemon like `sssd` and leave the
connection open.

To address this, we can call glibc's `__nss_configure_lookup` to
override NSS modules configured in /etc/nsswitch.conf and only use
ordinary file/DNS lookups.

(This is a cherry-pick of a patch applied to ruby/mspec here:
ruby/mspec#62)
  • Loading branch information
KJTsanaktsidis committed Jan 21, 2024
1 parent e2e15dd commit 6528f89
Showing 1 changed file with 55 additions and 0 deletions.
55 changes: 55 additions & 0 deletions spec/mspec/lib/mspec/runner/actions/leakchecker.rb
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@ def register
end

def start
disable_nss_modules
@checker = LeakChecker.new
end

Expand All @@ -316,4 +317,58 @@ def after(state)
end
end
end

private

# This function is intended to disable all NSS modules when ruby is compiled
# against glibc. NSS modules allow the system administrator to load custom
# shared objects into all processes using glibc, and use them to customise
# the behaviour of username, groupname, hostname, etc lookups. This is
# normally configured in the file /etc/nsswitch.conf.
# These modules often do things like open cache files or connect to system
# daemons like sssd or dbus, which of course means they have open file
# descriptors of their own. This can cause the leak-checking functionality
# in this file to report that such descriptors have been leaked, and fail
# the test suite.
# This function uses glibc's __nss_configure_lookup function to override any
# configuration in /etc/nsswitch.conf, and just use the built in files/dns
# name lookup functionality (which is of course perfectly sufficient for
# running ruby/spec).
def disable_nss_modules
begin
require 'fiddle'
rescue LoadError
# Make sure it's possible to run the test suite on a ruby implementation
# which does not (yet?) have Fiddle.
return
end

begin
libc = Fiddle.dlopen(nil)
nss_configure_lookup = Fiddle::Function.new(
libc['__nss_configure_lookup'],
[Fiddle::Types::CONST_STRING, Fiddle::Types::CONST_STRING],
Fiddle::Types::INT
)
rescue Fiddle::DLError
# We're not running with glibc - no need to do this.
return
end

nss_configure_lookup.call 'passwd', 'files'
nss_configure_lookup.call 'shadow', 'files'
nss_configure_lookup.call 'group', 'files'
nss_configure_lookup.call 'hosts', 'files dns myhostname'
nss_configure_lookup.call 'services', 'files'
nss_configure_lookup.call 'netgroup', 'files'
nss_configure_lookup.call 'automount', 'files'
nss_configure_lookup.call 'aliases', 'files'
nss_configure_lookup.call 'ethers', 'files'
nss_configure_lookup.call 'gshadow', 'files'
nss_configure_lookup.call 'initgroups', 'files'
nss_configure_lookup.call 'networks', 'files dns'
nss_configure_lookup.call 'protocols', 'files'
nss_configure_lookup.call 'publickey', 'files'
nss_configure_lookup.call 'rpc', 'files'
end
end

0 comments on commit 6528f89

Please sign in to comment.