Your message dated Sat, 26 Mar 2022 11:59:13 +0000 with message-id <c4d20274f6d76a43fb574d2177f6e3af4235e4be.ca...@adam-barratt.org.uk> and subject line Closing p-u requests for updates in 11.3 has caused the Debian Bug report #1006522, regarding bullseye-pu: package djbdns/1:1.05-13+deb11u1 to be marked as done.
This means that you claim that the problem has been dealt with. If this is not the case it is now your responsibility to reopen the Bug report if necessary, and/or fix the problem forthwith. (NB: If you are a system administrator and have no idea what this message is talking about, this may indicate a serious mail system misconfiguration somewhere. Please contact ow...@bugs.debian.org immediately.) -- 1006522: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1006522 Debian Bug Tracking System Contact ow...@bugs.debian.org with problems
--- Begin Message ---Package: release.debian.org Severity: normal Tags: bullseye User: release.debian....@packages.debian.org Usertags: pu X-Debbugs-Cc: r...@debian.org This is a future unblock request before I upload djbdns-1:1.05-13+deb11u1 to fix an RC bug in stable. [ Reason ] See #996807 for more information; in short, the tinydns server program may stop responding to DNS queries because it has reached the process data size limit. The reason is that recent versions of glibc appear to need more memory, so the value of the limit that has been enough for many years now is no longer adequate. Note that this only happens on some Debian architectures. [ Impact ] The authoritative server (tinydns) from the djbdns package will stop responding to queries, thus not fulfilling its basic purpose. [ Tests ] The attached debdiff also backports some improvements to the autopkgtest suite, including a new test that sends a lot of queries to the tinydns server to make sure it keeps responding. [ Risks ] The fix itself should not pose any risk at all, except maybe when running the tinydns server in extremely resource-contstrained environments when the additional 100K now available to the tinydns process may eat into some other processes' memory. However, it is my belief that people running tinydns in such environments will use their own configuration files or at least be mindful of changes in the Debian packages. The changes to the autopkgtest suite should also not pose any risk at all: they are mostly code clean-up and simplification. If, however, it is your opinion that they are too extensive, I can prepare another upload that drops them and only adds the "raise the process data size limit" patch itself. [ Checklist ] [x] *all* changes are documented in the d/changelog [x] I reviewed all changes and I approve them [x] attach debdiff against the package in (old)stable [x] the issue is verified as fixed in unstable [ Changes ] The data limit for the djbdns services is raised by an additional 100,000 bytes to reflect the programs' needs imposed by glibc. The autopkgtest suite's Python code is cleaned up. The autopkgtest suite performs an additional check: run a lot of queries against a tinydns server to make sure it keeps responding. Thanks in advance for looking at this, and keep up the great work! G'luck, Peterdiff -Nru djbdns-1.05/debian/changelog djbdns-1.05/debian/changelog --- djbdns-1.05/debian/changelog 2020-07-28 00:03:21.000000000 +0300 +++ djbdns-1.05/debian/changelog 2022-02-26 19:29:35.000000000 +0200 @@ -1,3 +1,18 @@ +djbdns (1:1.05-13+deb11u1) bullseye; urgency=medium + + * Add the 0011-datalimit patch to catch up with recent versions of + glibc generating larger executable files. Closes: #996807 + * Several improvements to the Python tinytest autopkgtest tool: + - use "with subprocess.Popen()" + - simplify the command-line parsing a bit + - minor import statement fixes + - add a tox.ini file to make it easier to run static code checkers + - turn a class into a dataclass + - send a lot of queries to tinydns to make sure that the fix for + #996807 actually works + + -- Peter Pentchev <r...@debian.org> Sat, 26 Feb 2022 19:29:35 +0200 + djbdns (1:1.05-13) unstable; urgency=medium * Do not even consider running tinydns during the package build. diff -Nru djbdns-1.05/debian/patches/0011-datalimit.patch djbdns-1.05/debian/patches/0011-datalimit.patch --- djbdns-1.05/debian/patches/0011-datalimit.patch 1970-01-01 02:00:00.000000000 +0200 +++ djbdns-1.05/debian/patches/0011-datalimit.patch 2022-02-26 19:29:35.000000000 +0200 @@ -0,0 +1,38 @@ +Description: Raise the axfrdns, dnscache, and tinydns data limit. +Bug-Debian: https://bugs.debian.org/996807 +Author: Peter Pentchev <r...@ringlet.net> +Last-Update: 2021-11-13 + +--- a/axfrdns-conf.c ++++ b/axfrdns-conf.c +@@ -50,7 +50,7 @@ + + start("run"); + outs("#!/bin/sh\nexec 2>&1\nexec envdir ./env sh -c '\n exec envuidgid "); outs(user); +- outs(" softlimit -d300000 tcpserver -vDRHl0 -x tcp.cdb -- \"$IP\" 53 "); ++ outs(" softlimit -d400000 tcpserver -vDRHl0 -x tcp.cdb -- \"$IP\" 53 "); + outs(auto_home); outs("/sbin/axfrdns\n'\n"); + finish(); + perm(0755); +--- a/dnscache-conf.c ++++ b/dnscache-conf.c +@@ -118,7 +118,7 @@ + seed_addtime(); perm(0644); + seed_addtime(); start("env/CACHESIZE"); outs("1000000\n"); finish(); + seed_addtime(); perm(0644); +- seed_addtime(); start("env/DATALIMIT"); outs("3000000\n"); finish(); ++ seed_addtime(); start("env/DATALIMIT"); outs("4000000\n"); finish(); + seed_addtime(); perm(0644); + seed_addtime(); start("run"); + outs("#!/bin/sh\nexec 2>&1\nexec <seed\nexec envdir ./env sh -c '\n exec envuidgid "); outs(user); +--- a/tinydns-conf.c ++++ b/tinydns-conf.c +@@ -46,7 +46,7 @@ + + start("run"); + outs("#!/bin/sh\nexec 2>&1\nexec envuidgid "); outs(user); +- outs(" envdir ./env softlimit -d300000 "); ++ outs(" envdir ./env softlimit -d400000 "); + outs(auto_home); outs("/sbin/tinydns\n"); + finish(); + perm(0755); diff -Nru djbdns-1.05/debian/patches/series djbdns-1.05/debian/patches/series --- djbdns-1.05/debian/patches/series 2020-07-28 00:03:21.000000000 +0300 +++ djbdns-1.05/debian/patches/series 2022-02-26 19:29:35.000000000 +0200 @@ -7,3 +7,4 @@ 0007-dnscache-merge-similar-outgoing-udp-packets.patch 0008-Cache-SOA-records.patch 0009-usr-sbin.patch +0011-datalimit.patch diff -Nru djbdns-1.05/debian/service/dnscache/conf/DATALIMIT djbdns-1.05/debian/service/dnscache/conf/DATALIMIT --- djbdns-1.05/debian/service/dnscache/conf/DATALIMIT 2020-07-28 00:03:21.000000000 +0300 +++ djbdns-1.05/debian/service/dnscache/conf/DATALIMIT 2022-02-26 19:29:35.000000000 +0200 @@ -1 +1 @@ -3000000 +4000000 diff -Nru djbdns-1.05/debian/service/tinydns/conf/DATALIMIT djbdns-1.05/debian/service/tinydns/conf/DATALIMIT --- djbdns-1.05/debian/service/tinydns/conf/DATALIMIT 2020-07-28 00:03:21.000000000 +0300 +++ djbdns-1.05/debian/service/tinydns/conf/DATALIMIT 2022-02-26 19:29:35.000000000 +0200 @@ -1 +1 @@ -3000000 +4000000 diff -Nru djbdns-1.05/debian/tests/pyproject.toml djbdns-1.05/debian/tests/pyproject.toml --- djbdns-1.05/debian/tests/pyproject.toml 1970-01-01 02:00:00.000000000 +0200 +++ djbdns-1.05/debian/tests/pyproject.toml 2022-02-26 19:29:35.000000000 +0200 @@ -0,0 +1,2 @@ +[tool.black] +line-length = 79 diff -Nru djbdns-1.05/debian/tests/setup.cfg djbdns-1.05/debian/tests/setup.cfg --- djbdns-1.05/debian/tests/setup.cfg 1970-01-01 02:00:00.000000000 +0200 +++ djbdns-1.05/debian/tests/setup.cfg 2022-02-26 19:29:35.000000000 +0200 @@ -0,0 +1,6 @@ +[flake8] +ignore = E203,W503 + +[mypy] +python_version = 3.7 +strict = True diff -Nru djbdns-1.05/debian/tests/tinytest/defs.py djbdns-1.05/debian/tests/tinytest/defs.py --- djbdns-1.05/debian/tests/tinytest/defs.py 2020-07-28 00:03:21.000000000 +0300 +++ djbdns-1.05/debian/tests/tinytest/defs.py 2022-02-26 19:29:35.000000000 +0200 @@ -4,7 +4,7 @@ import pathlib import subprocess -from typing import Dict, List, Union +from typing import Dict, List, Union # noqa: H301 @dataclasses.dataclass(frozen=True) diff -Nru djbdns-1.05/debian/tests/tinytest/__main__.py djbdns-1.05/debian/tests/tinytest/__main__.py --- djbdns-1.05/debian/tests/tinytest/__main__.py 2020-07-28 00:03:21.000000000 +0300 +++ djbdns-1.05/debian/tests/tinytest/__main__.py 2022-02-26 19:29:35.000000000 +0200 @@ -29,14 +29,14 @@ parser.add_argument( "-b", "--bindir", - type=str, + type=pathlib.Path, required=True, help="the path to the djbdns user tools", ) parser.add_argument( "-s", "--sbindir", - type=str, + type=pathlib.Path, required=True, help="the path to the djbdns system tools", ) @@ -60,11 +60,11 @@ subenv["LANGUAGE"] = "en" return Config( - bindir=pathlib.Path(args.bindir), - sbindir=pathlib.Path(args.sbindir), - skip_run_test=bool(args.skip_run_test), + bindir=args.bindir, + sbindir=args.sbindir, + skip_run_test=args.skip_run_test, subenv=subenv, - verbose=bool(args.verbose), + verbose=args.verbose, ) @@ -80,8 +80,9 @@ if not cfg.skip_run_test: test_run.test_tinydns_run(cfg, tempd) + test_run.test_tinydns_run_udp(cfg, tempd) else: - print("\n==== Skipping test_tinydns_run") + print("\n==== Skipping test_tinydns_run*") print("\n==== All fine!") diff -Nru djbdns-1.05/debian/tests/tinytest/test_conf.py djbdns-1.05/debian/tests/tinytest/test_conf.py --- djbdns-1.05/debian/tests/tinytest/test_conf.py 2020-07-28 00:03:21.000000000 +0300 +++ djbdns-1.05/debian/tests/tinytest/test_conf.py 2022-02-26 19:29:35.000000000 +0200 @@ -5,7 +5,7 @@ import pwd import sys -from typing import List, Union +from typing import List, Union # noqa: H301 from . import defs diff -Nru djbdns-1.05/debian/tests/tinytest/test_edit.py djbdns-1.05/debian/tests/tinytest/test_edit.py --- djbdns-1.05/debian/tests/tinytest/test_edit.py 2020-07-28 00:03:21.000000000 +0300 +++ djbdns-1.05/debian/tests/tinytest/test_edit.py 2022-02-26 19:29:35.000000000 +0200 @@ -1,10 +1,10 @@ """Test the `tinydns-edit` tool and the generated data file.""" -import pathlib import os +import pathlib import sys -from typing import List, Union +from typing import List, Union # noqa: H301 from . import defs diff -Nru djbdns-1.05/debian/tests/tinytest/test_get.py djbdns-1.05/debian/tests/tinytest/test_get.py --- djbdns-1.05/debian/tests/tinytest/test_get.py 2020-07-28 00:03:21.000000000 +0300 +++ djbdns-1.05/debian/tests/tinytest/test_get.py 2022-02-26 19:29:35.000000000 +0200 @@ -5,7 +5,7 @@ import re import sys -from typing import List, Union +from typing import List, Union # noqa: H301 from . import defs diff -Nru djbdns-1.05/debian/tests/tinytest/test_run.py djbdns-1.05/debian/tests/tinytest/test_run.py --- djbdns-1.05/debian/tests/tinytest/test_run.py 2020-07-28 00:03:21.000000000 +0300 +++ djbdns-1.05/debian/tests/tinytest/test_run.py 2022-02-26 19:29:35.000000000 +0200 @@ -4,16 +4,31 @@ import enum import os import pathlib +import socket +import struct import subprocess import sys import time -from typing import Callable, Dict, List, Tuple, Union +from typing import ( + Callable, # noqa: H301 + Dict, + List, + Tuple, + Union, + TYPE_CHECKING, +) from . import defs from . import test_get +if TYPE_CHECKING: + PopenStr = subprocess.Popen[str] # pylint: disable=unsubscriptable-object +else: + PopenStr = subprocess.Popen + + class ProcessFDType(str, enum.Enum): """File descriptor types, enough for this very limited test.""" @@ -54,22 +69,15 @@ files: List[ProcessFDInfo] +@dataclasses.dataclass class ParseProcessInfo: """Parse the output of `lsof -F` for our very limited testing needs.""" cfg: defs.Config - cproc: Dict[str, str] - cfile: Dict[str, str] - cfiles: List[ProcessFDInfo] - result: Dict[int, ProcessInfo] - - def __init__(self, cfg: defs.Config) -> None: - """Initialize an empty object.""" - self.cfg = cfg - self.cproc = {} - self.cfile = {} - self.cfiles = [] - self.result = {} + cproc: Dict[str, str] = dataclasses.field(default_factory=dict) + cfile: Dict[str, str] = dataclasses.field(default_factory=dict) + cfiles: List[ProcessFDInfo] = dataclasses.field(default_factory=list) + result: Dict[int, ProcessInfo] = dataclasses.field(default_factory=dict) def finish_file_ipv4(self) -> ProcessFDInfo: """Store the information about a socket.""" @@ -188,6 +196,72 @@ return data.proto == "UDP" and data.address == ipaddr and data.port == 53 +def run_tinydns( + cfg: defs.Config, + tempd: pathlib.Path, + callback: Callable[[PopenStr, str], None], +) -> None: + """Test the `tinydns` and `dnsq` programs.""" + ipaddr = defs.RECORDS[0].address + svcdir = tempd / defs.SVCDIR + if not svcdir.is_dir(): + sys.exit(f"Expected {svcdir} to be a directory") + os.chdir(svcdir) + + with subprocess.Popen( + ["./run"], + shell=False, + env=cfg.subenv, + bufsize=0, + encoding=defs.MINENC, + stdout=subprocess.PIPE, + ) as proc: + try: + print(f"- spawned process {proc.pid}") + assert proc.stdout is not None + print("- waiting for the 'starting tinydns' line") + line = proc.stdout.readline() + print(f"- got line {line!r}") + if line != "starting tinydns\n": + sys.exit(f"Unexpected first line from tinydns: {line!r}") + + lines = cfg.check_output( + [ + "lsof", + "-a", + "-n", + "-P", + "-p", + str(proc.pid), + "-F", + "-i4udp:53", + ] + ).splitlines() + cfg.diag(f"lsof output: {lines!r}") + processes = ParseProcessInfo(cfg).parse(lines) + if not check_single_udp_socket(processes, proc.pid, ipaddr): + sys.exit( + f"tinydns should listen on a single UDP socket: " + f"{processes!r}" + ) + print(f"- tinydns is listening at {ipaddr}:53") + callback(proc, ipaddr) + finally: + print("- we spawned a process, checking if it has exited") + res = proc.poll() + if res is None: + print(f"Terminating process {proc.pid}") + proc.terminate() + time.sleep(0.5) + res = proc.poll() + if res is None: + print(f"Killing process {proc.pid}") + proc.kill() + + res = proc.wait() + print(f"Process {proc.pid}: exit code {res}") + + def test_tinydns_run(cfg: defs.Config, tempd: pathlib.Path) -> None: """Test the `tinydns` and `dnsq` programs.""" print("\n==== test_tinydns_run") @@ -199,40 +273,9 @@ if not dnsq.is_file() or not os.access(dnsq, os.X_OK): sys.exit(f"Not an executable file: {dnsq}") - ipaddr = defs.RECORDS[0].address - svcdir = tempd / defs.SVCDIR - if not svcdir.is_dir(): - sys.exit(f"Expected {svcdir} to be a directory") - os.chdir(svcdir) - - proc = None - try: - proc = subprocess.Popen( - ["./run"], - shell=False, - env=cfg.subenv, - bufsize=0, - encoding=defs.MINENC, - stdout=subprocess.PIPE, - ) - print(f"- spawned process {proc.pid}") + def test_dnsq(proc: PopenStr, ipaddr: str) -> None: + """Run `dnsq` against the specified `tinydns` instance.""" assert proc.stdout is not None - print("- waiting for the 'starting tinydns' line") - line = proc.stdout.readline() - print(f"- got line {line!r}") - if line != "starting tinydns\n": - sys.exit(f"Unexpected first line from tinydns: {line!r}") - - lines = cfg.check_output( - ["lsof", "-a", "-n", "-P", "-p", str(proc.pid), "-F", "-i4udp:53"] - ).splitlines() - cfg.diag(f"lsof output: {lines!r}") - processes = ParseProcessInfo(cfg).parse(lines) - if not check_single_udp_socket(processes, proc.pid, ipaddr): - sys.exit( - f"tinydns should listen on a single UDP socket: {processes!r}" - ) - print(f"- tinydns is listening at {ipaddr}:53") for rec in defs.RECORDS: rdef = defs.TYPES[rec.rtype] @@ -256,17 +299,68 @@ print(" - there should be a single line of output from tinydns") line = proc.stdout.readline() cfg.diag(f"line: {line!r}") - finally: - if proc is not None: - print("- we spawned a process, checking if it has exited") - res = proc.poll() - if res is None: - print(f"Terminating process {proc.pid}") - proc.terminate() - time.sleep(0.5) - res = proc.poll() - if res is None: - print(f"Killing process {proc.pid}") - proc.kill() - res = proc.wait() - print(f"Process {proc.pid}: exit code {res}") + + run_tinydns(cfg, tempd, test_dnsq) + + +def test_tinydns_run_udp(cfg: defs.Config, tempd: pathlib.Path) -> None: + """Test the `tinydns` program by sending UDP packets.""" + print("\n==== test_tinydns_run_udp") + if os.geteuid() != 0: + print("- not running as root, skipped") + return + + def test_dnsq(proc: PopenStr, ipaddr: str) -> None: + """Run `dnsq` against the specified `tinydns` instance.""" + assert proc.stdout is not None + + pkt = struct.pack( + ">HHHHHH8p4p1pHH", + 17, + 0, + 1, + 0, + 0, + 0, + "example".encode("us-ascii"), + "com".encode("us-ascii"), + b"", + 1, + 1, + ) + print(f"- query packet: {pkt!r}") + + sock = socket.socket( + socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP + ) + sock.connect((ipaddr, 53)) + + for idx in range(1000000): + pkt = struct.pack(">H", (idx + 17) % 65536) + pkt[2:] + sent = sock.send(pkt) + if sent != len(pkt): + sys.exit(f"Only sent {sent} of {len(pkt)} bytes") + + line = proc.stdout.readline() + if "+" not in line: + sys.exit( + f"Query {idx + 1}: expected a '+' in " + f"the tinydns log line {line!r}" + ) + + resp = sock.recv(4096) + if resp[:2] != pkt[:2]: + sys.exit( + f"Query {idx + 1}: unexpected ID: " + f"query {pkt!r} response {resp!r}" + ) + if resp[4:8] != b"\x00\x01\x00\x01": + sys.exit( + f"Query {idx + 1}: unexpected query/response count: " + f"query {pkt!r} response {resp!r}" + ) + + if (idx % 10000) == 9999: + print(f"- sent {idx + 1} queries to {ipaddr}") + + run_tinydns(cfg, tempd, test_dnsq) diff -Nru djbdns-1.05/debian/tests/tox.ini djbdns-1.05/debian/tests/tox.ini --- djbdns-1.05/debian/tests/tox.ini 1970-01-01 02:00:00.000000000 +0200 +++ djbdns-1.05/debian/tests/tox.ini 2022-02-26 19:29:35.000000000 +0200 @@ -0,0 +1,55 @@ +[tox] +envlist = + black + pep8 + pep8h + mypy + pylint +skipsdist = True + +[defs] +pyfiles = + tinytest + +[testenv:black] +skipinstall = True +deps = + black >= 21b0, < 22b0 +commands = + black --check {[defs]pyfiles} + +[testenv:black-reformat] +skipinstall = True +deps = + black >= 21b0, < 22b0 +commands = + black {[defs]pyfiles} + +[testenv:pep8] +skipinstall = True +deps = + flake8 +commands = + flake8 {[defs]pyfiles} + +[testenv:pep8h] +skipinstall = True +deps = + flake8 + hacking >= 4 +commands = + flake8 {[defs]pyfiles} + +[testenv:mypy] +skipinstall = True +deps = + mypy +commands = + mypy {[defs]pyfiles} + +[testenv:pylint] +skipinstall = True +deps = + pylint +commands = + pylint {[defs]pyfiles}signature.asc
Description: PGP signature
--- End Message ---
--- Begin Message ---Package: release.debian.org Version: 11.3 Hi, The updates referenced by these bugs were included in stable as part of this morning's 11.3 point release. Regards, Adam
--- End Message ---