Linux bluetooth development
 help / color / mirror / Atom feed
* [bluez/bluez] 13b4ac: emulator: btvirt: support debug for -s socket server
From: Pauli Virtanen @ 2026-06-13 16:14 UTC (permalink / raw)
  To: linux-bluetooth

  Branch: refs/heads/1111062
  Home:   https://github.com/bluez/bluez
  Commit: 13b4acfd7e2369e64d7b4e8d0f7b6c029d7768d0
      https://github.com/bluez/bluez/commit/13b4acfd7e2369e64d7b4e8d0f7b6c029d7768d0
  Author: Pauli Virtanen <pav@iki.fi>
  Date:   2026-06-13 (Sat, 13 Jun 2026)

  Changed paths:
    M emulator/main.c
    M emulator/server.c
    M emulator/server.h

  Log Message:
  -----------
  emulator: btvirt: support debug for -s socket server

Support btdev debug -d when using socket server -s.

$ btvirt -d -s
...
bredrle: host10: > 01 13 0c f8 00 00 00 00 00 00 00 00 00 00 00 00  ................
bredrle: host10:   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
...



To unsubscribe from these emails, change your notification settings at https://github.com/bluez/bluez/settings/notifications

^ permalink raw reply

* [PATCH BlueZ v6 6/6] test: functional: add basic obex file transfer tests
From: Pauli Virtanen @ 2026-06-13 15:48 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Pauli Virtanen
In-Reply-To: <cover.1781365708.git.pav@iki.fi>

Add tests for Obex DBus API and obexctl

test/functional/test_obex.py::test_obex_ftp_get
test/functional/test_obex.py::test_obex_ftp_list
test/functional/test_obex.py::test_obexctl_list
---
 test/functional/test_obex.py | 285 +++++++++++++++++++++++++++++++++++
 1 file changed, 285 insertions(+)
 create mode 100644 test/functional/test_obex.py

diff --git a/test/functional/test_obex.py b/test/functional/test_obex.py
new file mode 100644
index 000000000..fcb9105e5
--- /dev/null
+++ b/test/functional/test_obex.py
@@ -0,0 +1,285 @@
+# -*- coding: utf-8; mode: python; eval: (blacken-mode); -*-
+# SPDX-License-Identifier: LGPL-2.1-or-later
+"""
+Tests for Obex
+"""
+import sys
+import os
+import re
+import pytest
+import subprocess
+import tempfile
+import time
+import logging
+import json
+import dbus
+import threading
+from pathlib import Path
+
+import pytest
+
+from pytest_bluezenv import (
+    HostPlugin,
+    Agent,
+    host_config,
+    find_exe,
+    Bluetoothd,
+    Bluetoothctl,
+    Obexd,
+    LogStream,
+    wait_until,
+    mainloop_wrap,
+    mainloop_assert,
+    Event,
+    EventPluginMixin,
+    dbus_service_event_method,
+    Pexpect,
+    utils,
+)
+
+pytestmark = [pytest.mark.vm]
+
+log = logging.getLogger(__name__)
+
+
+BUS_NAME = "org.bluez.obex"
+PATH = "/org/bluez/obex"
+AGENT_MANAGER_INTERFACE = "org.bluez.obex.AgentManager1"
+AGENT_INTERFACE = "org.bluez.obex.Agent1"
+CLIENT_INTERFACE = "org.bluez.obex.Client1"
+SESSION_INTERFACE = "org.bluez.obex.Session1"
+FILE_TRANSFER_INTERFACE = "org.bluez.obex.FileTransfer1"
+TRANSFER_INTERFACE = "org.bluez.obex.Transfer1"
+
+FTP_UUID = "00001106-0000-1000-8000-00805f9b34fb"
+
+
+class ObexAgent(HostPlugin, EventPluginMixin):
+    depends = [Bluetoothd()]
+    name = "obex_agent"
+
+    def __init__(self, path="/obexagent"):
+        self.path = path
+
+    @mainloop_wrap
+    def setup(self, impl):
+        EventPluginMixin.setup(self, impl)
+
+        self.bus = dbus.SessionBus()
+        self.bus.set_exit_on_disconnect(False)
+
+        self.agent = ObexAgentObject(self.bus, self.path, self.events)
+
+        bluez = self.bus.get_object(BUS_NAME, PATH)
+        self.manager = dbus.Interface(bluez, AGENT_MANAGER_INTERFACE)
+        self.manager.RegisterAgent(self.path)
+
+        log.info("Obex agent registered")
+
+    def cleanup(self):
+        path = Path("/run/obex")
+        for f in path.iterdir():
+            f.unlink()
+
+
+def agent_method(*a, **kw):
+    return dbus_service_event_method(AGENT_INTERFACE, *a, **kw)
+
+
+class ObexAgentObject(dbus.service.Object):
+    @mainloop_assert
+    def __init__(self, bus, path, events):
+        self.events = events
+        super().__init__(bus, path)
+
+    AuthorizePush = agent_method("AuthorizePush", ("path",), "o", "s", sync=False)
+    Cancel = agent_method("Cancel")
+
+
+def write_obex_file(name, content):
+    with open(f"/run/obex/{name}", "w") as f:
+        f.write(content)
+
+
+def read_file(name):
+    with open(name, "r") as f:
+        return f.read()
+
+
+#
+# Direct Obex Python client API tests
+#
+
+
+class ObexClient(HostPlugin, EventPluginMixin):
+    name = "obex"
+
+    @mainloop_wrap
+    def setup(self, impl):
+        EventPluginMixin.setup(self, impl)
+
+        self.transferred = 0
+        self.transfer_path = None
+        self.transfer_size = 0
+
+        self.bus = dbus.SessionBus()
+        self.bus.set_exit_on_disconnect(False)
+        self.log = logging.getLogger(self.name)
+        self.client = dbus.Interface(
+            self.bus.get_object(BUS_NAME, PATH), CLIENT_INTERFACE
+        )
+
+        self.bus.add_signal_receiver(
+            self.properties_changed,
+            dbus_interface="org.freedesktop.DBus.Properties",
+            signal_name="PropertiesChanged",
+            path_keyword="path",
+        )
+
+    @mainloop_wrap
+    def connect(self, bdaddr):
+        def reply(path):
+            obj = self.bus.get_object(BUS_NAME, path)
+            self.session = dbus.Interface(obj, SESSION_INTERFACE)
+            self.ftp = dbus.Interface(obj, FILE_TRANSFER_INTERFACE)
+
+        self._object_method(
+            self.client, "CreateSession", bdaddr, {"Target": "ftp"}, reply_handler=reply
+        )
+
+    @mainloop_assert
+    def properties_changed(self, interface, properties, invalidated, path):
+        if path != self.transfer_path:
+            return
+
+        if "Status" in properties and (
+            properties["Status"] == "complete" or properties["Status"] == "error"
+        ):
+            self.events.put(
+                Event(
+                    f"{FILE_TRANSFER_INTERFACE}:{properties['Status']}",
+                    properties=properties,
+                )
+            )
+            self.log.debug(f"Transfer {properties['Status']}")
+
+        if "Transferred" not in properties:
+            return
+
+        value = properties["Transferred"]
+        speed = (value - self.transferred) / 1000
+        self.log.debug(
+            f"Transfer progress {value}/{self.transfer_size} at {speed} kBps"
+        )
+        self.transferred = value
+
+    @mainloop_wrap
+    def ftp_list_folder(self):
+        return self.ftp.ListFolder()
+
+    @mainloop_wrap
+    def ftp_get_file(self, dst, src):
+        path, properties = self.ftp.GetFile(dst, src)
+        self.transfer_path = path
+        self.transfer_size = properties["Size"]
+        return properties["Filename"]
+
+
+@pytest.fixture
+def paired_hosts(hosts):
+    from .test_agent import test_agent_pair_bredr
+
+    if hosts[0].agent.has_device(hosts[1].bdaddr):
+        return hosts
+
+    test_agent_pair_bredr(hosts, True)
+    return hosts
+
+
+obex_host_config = host_config(
+    [Agent(), Obexd(), ObexClient(), Pexpect()],
+    [Agent(), Obexd(), ObexAgent()],
+    reuse=True,
+)
+
+
+@pytest.fixture
+def obex_hosts(paired_hosts):
+    host0, host1 = paired_hosts
+
+    if hasattr(host0, "session"):
+        return paired_hosts
+
+    host0.obex.connect(host1.bdaddr)
+
+    service = host1.agent.expect("org.bluez.Agent1.AuthorizeService")
+    assert service.uuid == FTP_UUID
+    host1.agent.reply()
+
+    host0.obex.expect("org.bluez.obex.Client1.CreateSession:reply")
+
+    yield paired_hosts
+
+    host1.obex_agent.cleanup()
+
+
+@obex_host_config
+def test_obex_ftp_list(obex_hosts):
+    host0, host1 = obex_hosts
+
+    host1.call(write_obex_file, "test", "1234")
+
+    (item,) = host0.obex.ftp_list_folder()
+    assert item["Type"] == "file"
+    assert item["Name"] == "test"
+    assert item["Size"] == 4
+
+
+@obex_host_config
+def test_obex_ftp_get(obex_hosts):
+    host0, host1 = obex_hosts
+
+    host1.call(write_obex_file, "test", "1234")
+
+    filename = host0.obex.ftp_get_file("", "test")
+    host0.obex.expect("org.bluez.obex.FileTransfer1:complete")
+    assert host0.call(read_file, filename) == "1234"
+
+
+#
+# obexctl tests
+#
+
+
+@pytest.fixture
+def obexctl(obex_hosts):
+    host0, host1 = obex_hosts
+
+    exe = find_exe("tools", "obexctl")
+    obexctl = host0.pexpect.spawn([exe])
+
+    obexctl.expect("Client /org/bluez/obex")
+    obexctl.send(f"connect {host1.bdaddr} {FTP_UUID}\n")
+
+    service = host1.agent.expect("org.bluez.Agent1.AuthorizeService")
+    assert service.uuid == FTP_UUID
+    host1.agent.reply()
+
+    obexctl.expect("Connection successful")
+    obexctl.send(f"select /org/bluez/obex/client/session1\n")
+
+    yield obexctl
+
+    obexctl.close()
+
+
+@obex_host_config
+def test_obexctl_list(obex_hosts, obexctl):
+    host0, host1 = obex_hosts
+
+    host1.call(write_obex_file, "test", "1234")
+
+    obexctl.send(f"ls\n")
+    obexctl.expect(f"Type: file")
+    obexctl.expect(f"Name: test")
+    obexctl.expect(f"Size: 4")
-- 
2.54.0


^ permalink raw reply related

* [PATCH BlueZ v6 5/6] test: functional: add some Agent1 interface tests
From: Pauli Virtanen @ 2026-06-13 15:48 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Pauli Virtanen
In-Reply-To: <cover.1781365708.git.pav@iki.fi>

Add test

test/functional/test_agent.py::test_agent_pair_bredr
---
 test/functional/test_agent.py | 46 +++++++++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)
 create mode 100644 test/functional/test_agent.py

diff --git a/test/functional/test_agent.py b/test/functional/test_agent.py
new file mode 100644
index 000000000..24593090b
--- /dev/null
+++ b/test/functional/test_agent.py
@@ -0,0 +1,46 @@
+# -*- coding: utf-8; mode: python; eval: (blacken-mode); -*-
+# SPDX-License-Identifier: GPL-2.0-or-later
+"""
+Tests for bluetoothctl using VM instances
+"""
+import sys
+import re
+import pytest
+import subprocess
+import tempfile
+
+import time
+import logging
+
+
+from pytest_bluezenv import host_config, Agent, wait_until
+
+pytestmark = [pytest.mark.vm]
+
+
+@host_config([Agent()], [Agent()])
+@pytest.mark.parametrize("success", [True, False], ids=["accept", "reject"])
+def test_agent_pair_bredr(hosts, success):
+    host0, host1 = hosts
+
+    host0.agent.adapter_method("StartDiscovery")
+    host0.agent.expect("org.bluez.Adapter1.StartDiscovery:reply")
+
+    host1.agent.adapter_set("Pairable", True)
+    host1.agent.adapter_set("Discoverable", True)
+
+    wait_until(host0.agent.has_device, host1.bdaddr)
+
+    host0.agent.device_method(host1.bdaddr, "Pair")
+
+    confirm_0 = host0.agent.expect("org.bluez.Agent1.RequestConfirmation")
+    confirm_1 = host1.agent.expect("org.bluez.Agent1.RequestConfirmation")
+    assert confirm_0.passkey == confirm_1.passkey
+    host0.agent.reply()
+
+    if success:
+        host1.agent.reply()
+        host0.agent.expect("org.bluez.Device1.Pair:reply")
+    else:
+        host1.agent.reply_error()
+        host0.agent.expect("org.bluez.Device1.Pair:error")
-- 
2.54.0


^ permalink raw reply related

* [PATCH BlueZ v6 4/6] test: functional: impose Python code formatting
From: Pauli Virtanen @ 2026-06-13 15:48 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Pauli Virtanen
In-Reply-To: <cover.1781365708.git.pav@iki.fi>

Check Python code formatting of the functional test suite.
---
 test/functional/test_tests.py | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)
 create mode 100644 test/functional/test_tests.py

diff --git a/test/functional/test_tests.py b/test/functional/test_tests.py
new file mode 100644
index 000000000..561b04703
--- /dev/null
+++ b/test/functional/test_tests.py
@@ -0,0 +1,23 @@
+# -*- coding: utf-8; mode: python; eval: (blacken-mode); -*-
+# SPDX-License-Identifier: GPL-2.0-or-later
+"""
+Tests for the test suite itself
+"""
+import sys
+import subprocess
+import warnings
+from pathlib import Path
+
+import pytest
+
+
+def test_formatting():
+    pytest.importorskip("black")
+
+    result = subprocess.run(
+        [sys.executable, "-mblack", "--check", "--diff", "-q", Path(__file__).parent],
+        stdout=subprocess.PIPE,
+        encoding="utf-8",
+    )
+    if result.returncode != 0:
+        warnings.warn(f"Formatting incorrect:\n{result.stdout}")
-- 
2.54.0


^ permalink raw reply related

* [PATCH BlueZ v6 3/6] build: add functional testing target
From: Pauli Virtanen @ 2026-06-13 15:48 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Pauli Virtanen
In-Reply-To: <cover.1781365708.git.pav@iki.fi>

This adds check-functional: target that runs the functional test suite.

Also add a --enable-functional-testing=<kernel-image> argument for
configure that can be used to include it in the check: make target,
possibly with a predefined kernel image.
---
 Makefile.am  | 10 ++++++++++
 configure.ac | 22 ++++++++++++++++++++++
 2 files changed, 32 insertions(+)

diff --git a/Makefile.am b/Makefile.am
index 76c4ab5d4..7920cae68 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -812,6 +812,16 @@ endif
 TESTS = $(unit_tests)
 AM_TESTS_ENVIRONMENT = MALLOC_CHECK_=3 MALLOC_PERTURB_=69
 
+check-functional: all
+	python3 -m pytest "$(srcdir)/test/functional" -v \
+		--kernel="$(FUNCTIONAL_TESTING_KERNEL)" \
+		--bluez-build-dir="$(top_builddir)" \
+		--bluez-src-dir="$(srcdir)"
+
+if FUNCTIONAL_TESTING
+check: check-functional
+endif
+
 if DBUS_RUN_SESSION
 AM_TESTS_ENVIRONMENT += dbus-run-session --
 endif
diff --git a/configure.ac b/configure.ac
index 1cdd551f6..f50d8c9b3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -407,6 +407,28 @@ if (test "${enable_testing}" = "yes"); then
 		#include <linux/net_tstamp.h>]])
 fi
 
+AC_ARG_ENABLE(functional-testing, AS_HELP_STRING([--enable-functional-testing],
+			[enable functional testing tools]),
+			[enable_functional_testing=yes; functional_testing_kernel=${enableval}],
+                        [enable_functional_testing=no])
+AM_CONDITIONAL(FUNCTIONAL_TESTING, test "${enable_functional_testing}" = "yes")
+AC_ARG_VAR(FUNCTIONAL_TESTING_KERNEL, [vmlinux image to use for functional testing])
+FUNCTIONAL_TESTING_KERNEL=${functional_testing_kernel}
+
+if (test "${enable_functional_testing}" = "yes"); then
+  if (test "${enable_client}" = "no" || \
+      test "${enable_tools}" != "yes" || \
+      test "${enable_testing}" != "yes"); then
+    AC_MSG_ERROR([--enable-functional-testing requires --enable-client --enable-tools --enable-testing])
+  fi
+  AC_MSG_CHECKING([pytest and dependencies])
+  python3 -m pip install --dry-run --no-index -r "${srcdir}/test/functional/requirements.txt" >/dev/null
+  if (test "$?" != "0"); then
+    AC_MSG_ERROR([pytest or dependencies missing])
+  fi
+  AC_MSG_RESULT([ok])
+fi
+
 AC_ARG_ENABLE(experimental, AS_HELP_STRING([--enable-experimental],
 			[enable experimental tools]),
 					[enable_experimental=${enableval}])
-- 
2.54.0


^ permalink raw reply related

* [PATCH BlueZ v6 2/6] test: add functional/integration testing framework
From: Pauli Virtanen @ 2026-06-13 15:48 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Pauli Virtanen
In-Reply-To: <cover.1781365708.git.pav@iki.fi>

Add framework for writing tests simulating "real" environments where
BlueZ and other parts of the stack run on different virtual machine
hosts that communicate with each other.

Add some smoke tests for bluetoothctl and btmgmt.

The implementation for the VM setup is maintained separately in the
pytest-bluezenv plugin, https://pypi.org/project/pytest-bluezenv

Implements:

- RPC communication with tester instances running each of the VM hosts,
  so that tests can be written on the parent host which coordinates the
  execution.

- Extensible way to add stateful test-specific code inside the VM
  instances

- Logging control: output from different processes running inside the VM
  are separated and can be filtered.

- Test runner framework with Pytest, factored into a pytest plugin

- Grouping tests to minimize VM reboots

- Redirecting USB controllers to use for testing

There is no requirement that the tests spawn VM instances.
---
 test/functional/__init__.py             |   2 +
 test/functional/conftest.py             |  48 ++++++++
 test/functional/requirements.txt        |   2 +
 test/functional/test_bluetoothctl_vm.py | 152 ++++++++++++++++++++++++
 test/functional/test_btmgmt_vm.py       |  30 +++++
 test/pytest.ini                         |  17 +++
 test/test-functional                    |  21 ++++
 test/test-functional-attach             |   7 ++
 8 files changed, 279 insertions(+)
 create mode 100644 test/functional/__init__.py
 create mode 100644 test/functional/conftest.py
 create mode 100644 test/functional/requirements.txt
 create mode 100644 test/functional/test_bluetoothctl_vm.py
 create mode 100644 test/functional/test_btmgmt_vm.py
 create mode 100644 test/pytest.ini
 create mode 100755 test/test-functional
 create mode 100755 test/test-functional-attach

diff --git a/test/functional/__init__.py b/test/functional/__init__.py
new file mode 100644
index 000000000..fe1c85178
--- /dev/null
+++ b/test/functional/__init__.py
@@ -0,0 +1,2 @@
+# -*- coding: utf-8; mode: python; eval: (blacken-mode); -*-
+# SPDX-License-Identifier: GPL-2.0-or-later
diff --git a/test/functional/conftest.py b/test/functional/conftest.py
new file mode 100644
index 000000000..196afa08d
--- /dev/null
+++ b/test/functional/conftest.py
@@ -0,0 +1,48 @@
+# -*- coding: utf-8; mode: python; eval: (blacken-mode); -*-
+# SPDX-License-Identifier: GPL-2.0-or-later
+import os
+import re
+from pathlib import Path
+
+
+def pytest_addoption(parser):
+    parser.addoption(
+        "--list",
+        action="store_true",
+        default=None,
+        help=("List tests"),
+    )
+
+
+def pytest_configure(config):
+    if config.option.list:
+        config.option.reportchars = "A"
+        config.option.no_header = True
+        config.option.verbose = -2
+
+
+COLLECT_ERRORS = []
+
+
+def pytest_collectreport(report):
+    if report.outcome != "passed":
+        COLLECT_ERRORS.append((report.outcome, report.fspath))
+
+
+def pytest_collection_finish(session):
+    if session.config.option.list:
+        cwd = Path(".").resolve()
+        root = session.config.rootpath.absolute()
+
+        regex = re.compile(r"\[.*")
+        names = set(
+            (root.joinpath(item.location[0]), regex.sub("", item.location[2]))
+            for item in session.items
+        )
+
+        for path, name in sorted(names):
+            print(f"{path.resolve().relative_to(cwd, walk_up=True)}::{name}")
+        for outcome, name in COLLECT_ERRORS:
+            print(f"{outcome.upper()} {name}")
+        print()
+        os._exit(0)
diff --git a/test/functional/requirements.txt b/test/functional/requirements.txt
new file mode 100644
index 000000000..cd66e74a8
--- /dev/null
+++ b/test/functional/requirements.txt
@@ -0,0 +1,2 @@
+pytest>=8
+pytest-bluezenv==0.1.6
diff --git a/test/functional/test_bluetoothctl_vm.py b/test/functional/test_bluetoothctl_vm.py
new file mode 100644
index 000000000..0ba75e9a9
--- /dev/null
+++ b/test/functional/test_bluetoothctl_vm.py
@@ -0,0 +1,152 @@
+# -*- coding: utf-8; mode: python; eval: (blacken-mode); -*-
+# SPDX-License-Identifier: GPL-2.0-or-later
+"""
+Tests for bluetoothctl using VM instances
+"""
+import sys
+import re
+import pytest
+import subprocess
+import tempfile
+import warnings
+
+import time
+import logging
+
+
+from pytest_bluezenv import host_config, find_exe, run, Bluetoothd, Bluetoothctl
+
+pytestmark = [pytest.mark.vm]
+
+bluetoothctl = find_exe("client", "bluetoothctl")
+
+bluetoothd_reuse_config = host_config([Bluetoothd()], reuse=True)
+
+
+@host_config(
+    [Bluetoothctl()],
+    [Bluetoothctl()],
+)
+def test_bluetoothctl_pair_bredr(hosts):
+    host0, host1 = hosts
+
+    host0.bluetoothctl.send("scan on\n")
+    host0.bluetoothctl.expect(f"Controller {host0.bdaddr.upper()} Discovering: yes")
+
+    host1.bluetoothctl.send("pairable on\n")
+    host1.bluetoothctl.expect("Changing pairable on succeeded")
+    host1.bluetoothctl.send("discoverable on\n")
+    host1.bluetoothctl.expect(f"Controller {host1.bdaddr.upper()} Discoverable: yes")
+
+    host0.bluetoothctl.expect(f"Device {host1.bdaddr.upper()}")
+    host0.bluetoothctl.send(f"pair {host1.bdaddr}\n")
+
+    idx, m = host0.bluetoothctl.expect(r"Confirm passkey (\d+).*:")
+    key = m[0].decode("utf-8")
+
+    host1.bluetoothctl.expect(f"Confirm passkey {key}")
+
+    host0.bluetoothctl.send("yes\n")
+    host1.bluetoothctl.send("yes\n")
+
+    host0.bluetoothctl.expect("Pairing successful")
+
+
+@host_config(
+    [Bluetoothd(conf="[General]\nControllerMode = le\n"), Bluetoothctl()],
+    [Bluetoothd(conf="[General]\nControllerMode = le\n"), Bluetoothctl()],
+)
+def test_bluetoothctl_pair_le(hosts):
+    host0, host1 = hosts
+
+    host0.bluetoothctl.send("scan on\n")
+    host0.bluetoothctl.expect(f"Controller {host0.bdaddr.upper()} Discovering: yes")
+
+    host1.bluetoothctl.send("advertise on\n")
+    host1.bluetoothctl.expect("Advertising object registered")
+
+    host0.bluetoothctl.expect(f"Device {host1.bdaddr.upper()}")
+    host0.bluetoothctl.send(f"pair {host1.bdaddr.upper()}\n")
+
+    # BUG!: if controller is power cycled off/on at boot (before bluetoothd)
+    # BUG!: which is what the tester here does,
+    # BUG!: bluetoothd MGMT command to enable Secure Connections Host Support
+    # BUG!: fails and we are left with legacy passkey. It seems we get randomly
+    # BUG!: one of these depending on what state controller/kernel were before
+    # BUG!: btmgmt power off/on
+
+    idx, m = host0.bluetoothctl.expect(
+        [r"\[agent\].*Passkey:.*m(\d+)", r"Confirm passkey (\d+).*:"]
+    )
+    key = m[0].decode("utf-8")
+
+    if idx == 0:
+        warnings.warn(
+            "BUG: we got passkey authentication, bluetoothd/kernel should be fixed"
+        )
+        host1.bluetoothctl.expect(r"\[agent\] Enter passkey \(number in 0-999999\):")
+        host1.bluetoothctl.send(f"{key}\n")
+    else:
+        host1.bluetoothctl.expect(f"Confirm passkey {key}")
+
+        host0.bluetoothctl.send("yes\n")
+        host1.bluetoothctl.send("yes\n")
+
+    host0.bluetoothctl.expect("Pairing successful")
+
+
+def run_bluetoothctl(*args):
+    return run(
+        [bluetoothctl] + list(args),
+        stdout=subprocess.PIPE,
+        stdin=subprocess.DEVNULL,
+        encoding="utf-8",
+    )
+
+
+def run_bluetoothctl_script(script):
+    with tempfile.NamedTemporaryFile(mode="w", encoding="utf-8") as f:
+        f.write(script)
+        f.write("\nquit")
+        f.flush()
+        return run_bluetoothctl("--init-script", f.name)
+
+
+@bluetoothd_reuse_config
+def test_bluetoothctl_show(hosts):
+    (host,) = hosts
+
+    result = host.call(run_bluetoothctl, f"show")
+    assert result.returncode == 0
+    assert f"Controller {host.bdaddr.upper()}" in result.stdout
+    assert "Powered: " in result.stdout
+    assert "Discoverable: no" in result.stdout
+
+
+@bluetoothd_reuse_config
+def test_bluetoothctl_list(hosts):
+    (host,) = hosts
+
+    result = host.call(run_bluetoothctl, "list")
+    assert result.returncode == 0
+    assert re.search(rf"{host.bdaddr.upper()}.*\[default\]", result.stdout)
+
+
+@bluetoothd_reuse_config
+def test_bluetoothctl_script_show(hosts):
+    (host,) = hosts
+
+    result = host.call(run_bluetoothctl_script, f"show")
+    assert result.returncode == 0
+    assert f"Controller {host.bdaddr.upper()}" in result.stdout
+    assert "Powered: " in result.stdout
+    assert "Discoverable: no" in result.stdout
+
+
+@bluetoothd_reuse_config
+def test_bluetoothctl_script_list(hosts):
+    (host,) = hosts
+
+    result = host.call(run_bluetoothctl_script, f"list")
+    assert result.returncode == 0
+    assert re.search(rf"{host.bdaddr.upper()}.*\[default\]", result.stdout)
diff --git a/test/functional/test_btmgmt_vm.py b/test/functional/test_btmgmt_vm.py
new file mode 100644
index 000000000..3d11d7616
--- /dev/null
+++ b/test/functional/test_btmgmt_vm.py
@@ -0,0 +1,30 @@
+# -*- coding: utf-8; mode: python; eval: (blacken-mode); -*-
+# SPDX-License-Identifier: GPL-2.0-or-later
+"""
+Tests for btmgmt using VM instances
+"""
+import sys
+import pytest
+import subprocess
+import tempfile
+
+from pytest_bluezenv import host_config, find_exe, run
+
+pytestmark = [pytest.mark.vm]
+
+btmgmt = find_exe("tools", "btmgmt")
+
+
+@host_config([])
+def test_btmgmt_info(hosts):
+    (host,) = hosts
+
+    result = host.call(
+        run,
+        [btmgmt, "--index", "0", "info"],
+        stdout=subprocess.PIPE,
+        stdin=subprocess.DEVNULL,
+        encoding="utf-8",
+    )
+    assert result.returncode == 0
+    assert f"addr {host.bdaddr.upper()}" in result.stdout
diff --git a/test/pytest.ini b/test/pytest.ini
new file mode 100644
index 000000000..0d4e48d69
--- /dev/null
+++ b/test/pytest.ini
@@ -0,0 +1,17 @@
+[pytest]
+log_format = %(asctime)s %(levelname)-6s %(name)-20s:  %(message)s
+log_date_format = %Y-%m-%d %H:%M:%S.%f
+log_level = 0
+log_file = test-functional.log
+markers =
+    vm: tests requiring VM image
+
+addopts =
+    -p pytest_bluezenv
+
+# Default timeout
+vm_timeout = 30
+
+# Default sources for kernel-build when requested
+kernel_upstream = https://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git/
+kernel_branch = master
diff --git a/test/test-functional b/test/test-functional
new file mode 100755
index 000000000..95f5c57e9
--- /dev/null
+++ b/test/test-functional
@@ -0,0 +1,21 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# See doc/test-functional.rst
+#
+TESTDIR="$(dirname "$0")"
+SRCDIR="$TESTDIR/.."
+
+BUILDDIR=
+for d in "$SRCDIR" "$SRCDIR/build" "$SRCDIR/builddir"; do
+    if [ -f "$d/src/bluetoothd" ]; then
+        BUILDDIR="$d"
+        break
+    fi
+done
+
+if [ -n "$BUILDDIR" ] && [ -d "$BUILDDIR" ]; then
+    exec python3 -m pytest "$TESTDIR/functional" --bluez-src-dir "$SRCDIR" --bluez-build-dir "$BUILDDIR" "$@"
+else
+    exec python3 -m pytest "$TESTDIR/functional" --bluez-src-dir "$SRCDIR" "$@"
+fi
diff --git a/test/test-functional-attach b/test/test-functional-attach
new file mode 100755
index 000000000..6e65464f7
--- /dev/null
+++ b/test/test-functional-attach
@@ -0,0 +1,7 @@
+#!/bin/sh
+#
+# test-functional-attach
+#
+# Start Tmux and connect to active test-functional VM hosts.
+#
+exec python3 -mpytest_bluezenv attach "$@"
-- 
2.54.0


^ permalink raw reply related

* [PATCH BlueZ v6 0/6] Functional/integration testing
From: Pauli Virtanen @ 2026-06-13 15:48 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Pauli Virtanen

Add framework for writing tests simulating "real" environments where
BlueZ and other parts of the stack run on different virtual machine
hosts that communicate with each other.

*** v6 ***

* Fix minor issues in documentation and shellcheck warnings.

* Bump to latest pytest-bluezenv==0.1.6

* NOTE: hci_uart is partly broken in current bluetooth-next / 7.1 kernel,
  which causes some of the tests here fail sporadically. Needs the following patch:

  https://lore.kernel.org/linux-bluetooth/6888691461070a011d31632e6dcbfd73016dcc6e.1781364475.git.pav@iki.fi/

*** v5 ***

https://github.com/pv/bluez/compare/func-test-v4-r..func-test-v5

* Factor out the pytest-bluezenv plugin, to be maintained separately.
  https://pypi.org/project/pytest-bluezenv/

  It could in principle be moved under the BlueZ organization, but
  there's no particular reason why it should be in bluez repository.

  Generally, it's better to have the pytest plugin separate so it's
  easier to reuse and can have its own version cycle.

* Pipewire tests are moved to pipewire repository where they probably
  belong to.

  They can be run easily vs. given BlueZ build dir.

  We are currently running them in Pipewire CI, but at frozen
  kernel/BlueZ version, so it is not testing BlueZ/kernel upstream
  development.

* No changes in the emulator/test-runner patches since v4

  They are stand-alone bug fixes / improvements, and make sense
  also separately from the rest.

*** v4 ***

https://github.com/pv/bluez/compare/func-test-v3-r..func-test-v4

* Use virtconsole for simpler HCI forwarding to the vm

* Fix typoed vm_module -> vm_once

* Skip tests for some pipewire versions

*** v3 ***

https://github.com/pv/bluez/compare/func-test-v2-r..func-test-v3

* fix configure.ac openpty() detection to match TOOLS conditional,
  to fix make distcheck

* properly retry virtio RPC connection if it fails initially

* properly restart VM if previous test hangs

* allow custom parent host side proxy objects, use them for pexpect

* improve --list with out-of-tree test files

* fix missing bus.set_exit_on_disconnect(False) for obex tests

* have --vm-timeout etc. change values also on VM host side

* use larger-memory VM instances for Pipewire, in case ASAN enabled

* set reasonable inside-VM ASAN_OPTION default values

* don't run btvirt under stdbuf, since not compatible with ASAN

*** v2 ***

https://github.com/pv/bluez/compare/func-test-v1-r..func-test-v2

* move unit/func_test -> test/functional & test/pytest_bluez

  The pytest_bluez plugin is in principle reusable for other projects,
  so we can eg. have more complete Pipewire integration tests that can
  live in Pipewire repository.

* openpty() is in -lutil on some platforms, detect this in autoconf

* more emulator adjustments:

  - fix SCO data packet support in btvirt
  - more complete Reset command

* improve logging: get timestamps from kernel, and reorder logs
  to timestamp order, so that lines from different hosts, btmon,
  and parent tester appear in right order regardless of whether
  VM console / btmon is lagging

  - this requires accurate clock sync in the VM, so enable KVM PTP in
    config and run chronyd inside the VMs
  - use virtio port instead of qemu console to export logs, since the
    console has fixed baud rate and is too slow

* add --btmon & export btsnoop dumps from VM hosts

* fix compatibility with older Python versions

* add parametrized_host_config()

* split Pipewire test to A2DP/BAP/HFP and really stream audio.
  These catch the 5.86 regression fixed in 066a164a524e498 and
  the 5.84 one in 6b0a08776a

* add support for tests that reuse tester environment, so they can run
  faster without needing Bluetoothd teardown/setup in between

* add HostPlugin.presetup (mainly for test skipping)

* deal with RPC virtio port buffer possibly containing unflushed
  commands from previous failed test

* add some Agent1 interface tests

* add basic Obex file transfer tests

* add support for logging in to a running test instance (for gdb etc)

* export any core dumps out from test environ

Some bells & whistles:

* add --kernel-build for kernel image build

* test suite Python code formatting checks

***

Implements:

- RPC communication with tester instances running each of the VM hosts.
  Tests run on parent host, which instructs VM hosts what to do.

- Extensible way to add stateful test-specific code inside the VM
  instances

- Logging control: output from different processes running inside the VM
  are separated and can be filtered.

- Test runner framework with Pytest (more convenient than Python/unittest)

- Automatic grouping of tests to minimize VM reboots

- Redirecting USB controllers to use for testing in addition to btvirt

- Fairly straightforward, ~1600 sloc for the framework

There is no requirement that the tests spawn VM instances, the test
runner can be used for any tests written in Python.

See doc/test-functional.rst for various examples.

Also test/functional/test_bluetoothctl_vm.py has some simple cases, and
test/functional/test_pipewire.py for a more complicated setup

    host0(qemu): Pipewire <-> BlueZ <-> kernel
    <-> btvirt
    host1(qemu): kernel <-> BlueZ <-> Pipewire

The framework allows easily passing any data and code between the parent
and VM hosts, so writing tests is straightforward.

***

Some examples:

$ test/test-functional --list

test/functional/lib/tests/test_rpc.py::test_basic
test/functional/test_bluetoothctl_vm.py::test_bluetoothctl_pair[hosts0-vm2]
test/functional/test_bluetoothctl_vm.py::test_bluetoothctl_script_show[hosts1-vm1]
test/functional/test_btmgmt_vm.py::test_btmgmt_info[hosts2-vm1]
test/functional/test_pipewire.py::test_pipewire[hosts3-vm2]

$ test/test-functional --kernel=../linux
============================= test session starts ==============================
platform linux -- Python 3.14.3, pytest-8.3.5, pluggy-1.6.0
rootdir: /home/pauli/prj/external/bluez/unit
configfile: pytest.ini
plugins: cov-5.0.0, forked-1.6.0, rerunfailures-15.0, timeout-2.4.0, xdist-3.7.0, hypothesis-6.123.0, flaky-3.8.1, anyio-4.12.1
collected 5 items

test/functional/lib/tests/test_rpc.py .                                   [ 20%]
test/functional/test_bluetoothctl_vm.py .                                 [ 40%]
test/functional/test_btmgmt_vm.py .                                       [ 60%]
test/functional/test_bluetoothctl_vm.py .                                 [ 80%]
test/functional/test_pipewire.py .                                        [100%]

============================== 5 passed in 41.92s ==============================

$ test/test-functional --kernel=../linux -k test_btmgmt
============================= test session starts ==============================
platform linux -- Python 3.14.3, pytest-8.3.5, pluggy-1.6.0
rootdir: /home/pauli/prj/external/bluez/unit
configfile: pytest.ini
plugins: cov-5.0.0, forked-1.6.0, rerunfailures-15.0, timeout-2.4.0, xdist-3.7.0, hypothesis-6.123.0, flaky-3.8.1, anyio-4.12.1
collected 5 items / 4 deselected / 1 selected

test/functional/test_btmgmt_vm.py .                                       [100%]

======================= 1 passed, 4 deselected in 9.15s ========================

$ grep btmgmt test-functional.log
13:15:42 INFO   rpc.host.0.0        :  client: call_plugin ('call', '__call__', <function run at 0x7f27b81ce140>, ['/home/pauli/prj/external/bluez/build/tools/btmgmt', '--index', '0', 'info']) {'stdout': -1, 'stdin': -3, 'encoding': 'utf-8'}
13:15:42 INFO   host.0.0.rpc        :  server: call_plugin ('call', '__call__', <function run at 0x7fd5e35a1010>, ['/home/pauli/prj/external/bluez/build/tools/btmgmt', '--index', '0', 'info']) {'stdout': -1, 'stdin': -3, 'encoding': 'utf-8'}
13:15:42 INFO   host.0.0.run        :      $ /home/pauli/prj/external/bluez/build/tools/btmgmt --index 0 info

$ test/test-functional --kernel=../linux -k test_btmgmt --log-cli-level=0
============================= test session starts ==============================
platform linux -- Python 3.14.3, pytest-8.3.5, pluggy-1.6.0
rootdir: /home/pauli/prj/external/bluez/unit
configfile: pytest.ini
plugins: cov-5.0.0, forked-1.6.0, rerunfailures-15.0, timeout-2.4.0, xdist-3.7.0, hypothesis-6.123.0, flaky-3.8.1, anyio-4.12.1
collected 5 items / 4 deselected / 1 selected

test/functional/test_btmgmt_vm.py::test_btmgmt_info[hosts2-vm1]
-------------------------------- live log setup --------------------------------
13:00:31 INFO   func_test.lib.env   :  Starting btvirt: /usr/bin/stdbuf -o L -e L /home/pauli/prj/external/bluez/build/emulator/btvirt --server=/tmp/bluez-func-test-8t6ychy8
13:00:31 OUT    btvirt              :  Bluetooth emulator ver 5.86
13:00:31 INFO   func_test.lib.env   :  Starting host: /home/pauli/prj/external/bluez/build/tools/test-runner --kernel=../linux/arch/x86/boot/bzImage -u/tmp/bluez-func-test-8t6ychy8/bt-server-bredrle -o -chardev -o socket,id=ser0,path=/tmp/bluez-func-test-8t6ychy8/bluez-func-test-rpc-0,server=on,wait=off -o -device -o virtio-serial -o -device -o virtserialport,chardev=ser0,name=bluez-func-test-rpc -H -- /usr/bin/python3 -P /home/pauli/prj/external/bluez/test/functional/lib/runner.py /dev/ttyS2
13:00:31 OUT    btvirt              :  Request for /tmp/bluez-func-test-8t6ychy8/bt-server-bredrle
13:00:32 OUT    host.0.0            :  early console in extract_kernel
13:00:32 OUT    host.0.0            :  input_data: 0x000000000425c2c4
...
13:00:39 INFO   rpc.host.0.0        :  client: call_plugin ('call', '__call__', <function run at 0x7f7547472140>, ['/home/pauli/prj/external/bluez/build/tools/btmgmt', '--index', '0', 'info']) {'stdout': -1, 'stdin': -3, 'encoding': 'utf-8'}
13:00:39 DEBUG  host.0.0.rpc        :  server: done
13:00:39 INFO   host.0.0.rpc        :  server: call_plugin ('call', '__call__', <function run at 0x7f77dcc81010>, ['/home/pauli/prj/external/bluez/build/tools/btmgmt', '--index', '0', 'info']) {'stdout': -1, 'stdin': -3, 'encoding': 'utf-8'}
13:00:39 INFO   host.0.0.run        :      $ /home/pauli/prj/external/bluez/build/tools/btmgmt --index 0 info
13:00:40 OUT    host.0.0.run.out    :  hci0:	Primary controller
13:00:40 OUT    host.0.0.run.out    :  	addr 00:AA:01:00:00:42 version 11 manufacturer 1521 class 0x000000
13:00:40 OUT    host.0.0.run.out    :  	supported settings: powered connectable fast-connectable discoverable bondable link-security ssp br/edr le advertising secure-conn debug-keys privacy static-addr phy-configuration cis-central cis-peripheral iso-broadcaster sync-receiver ll-privacy past-sender past-receiver
13:00:40 OUT    host.0.0.run.out    :  	current settings: br/edr
13:00:40 OUT    host.0.0.run.out    :  	name
13:00:40 OUT    host.0.0.run.out    :  	short name
13:00:40 INFO   host.0.0.run        :  (return code 0)
13:00:40 DEBUG  rpc.host.0.0        :  client-reply
PASSED                                                                   [100%]
13:00:40 OUT    host.0.0            :  qemu-system-x86_64: terminating on signal 15 from pid 149047 (python3)
======================= 1 passed, 4 deselected in 8.84s ========================

$ test/test-functional --kernel=../linux -k test_bluetoothctl_pair --log-cli-level=0 --log-filter=*.bluetoothctl,rpc.* --force-usb
============================= test session starts ==============================
platform linux -- Python 3.14.3, pytest-8.3.5, pluggy-1.6.0
rootdir: /home/pauli/prj/external/bluez/unit
configfile: pytest.ini
plugins: cov-5.0.0, forked-1.6.0, rerunfailures-15.0, timeout-2.4.0, xdist-3.7.0, hypothesis-6.123.0, flaky-3.8.1, anyio-4.12.1
collected 5 items / 4 deselected / 1 selected

test/functional/test_bluetoothctl_vm.py::test_bluetoothctl_pair[hosts0-vm2]
-------------------------------- live log setup --------------------------------
13:03:20 INFO   rpc.host.0.0        :  client: start_load (<func_test.lib.host_plugins.Bdaddr object at 0x7f268712d160>,) {}
13:03:20 INFO   rpc.host.0.0        :  client: start_load (<func_test.lib.host_plugins.Call object at 0x7f268712d2b0>,) {}
13:03:20 INFO   rpc.host.0.0        :  client: start_load (<func_test.lib.host_plugins.DbusSystem object at 0x7f2687aa30e0>,) {}
13:03:20 INFO   rpc.host.0.0        :  client: start_load (<func_test.lib.host_plugins.Bluetoothd object at 0x7f2687aa3230>,) {}
13:03:20 INFO   rpc.host.0.0        :  client: start_load (<func_test.lib.host_plugins.Bluetoothctl object at 0x7f268712d010>,) {}
13:03:20 INFO   rpc.host.0.1        :  client: start_load (<func_test.lib.host_plugins.Bdaddr object at 0x7f26871542d0>,) {}
13:03:20 INFO   rpc.host.0.1        :  client: start_load (<func_test.lib.host_plugins.Call object at 0x7f2687154410>,) {}
13:03:20 INFO   rpc.host.0.1        :  client: start_load (<func_test.lib.host_plugins.DbusSystem object at 0x7f2687aa30e0>,) {}
13:03:20 INFO   rpc.host.0.1        :  client: start_load (<func_test.lib.host_plugins.Bluetoothd object at 0x7f2687aa3230>,) {}
13:03:20 INFO   rpc.host.0.1        :  client: start_load (<func_test.lib.host_plugins.Bluetoothctl object at 0x7f2687154190>,) {}
13:03:20 INFO   rpc.host.0.0        :  client: wait_load () {}
13:03:21 DEBUG  rpc.host.0.0        :  client-reply
13:03:21 INFO   rpc.host.0.1        :  client: wait_load () {}
13:03:21 DEBUG  rpc.host.0.1        :  client-reply
-------------------------------- live log call ---------------------------------
13:03:21 INFO   rpc.host.0.0        :  client: call_plugin ('bluetoothctl', 'send', 'show\n') {}
13:03:21 DEBUG  rpc.host.0.0        :  client-reply
13:03:21 INFO   rpc.host.0.0        :  client: call_plugin ('bluetoothctl', 'expect', 'Powered: yes') {}
...
13:03:23 INFO   rpc.host.0.0        :  client: call_plugin ('bluetoothctl', 'send', 'pair 70:1a:b8:73:99:bb\n') {}
13:03:23 OUT    host.0.0.bluetoothctl:  pair 70:1a:b8:73:99:bb
13:03:23 DEBUG  rpc.host.0.0        :  client-reply
13:03:23 INFO   rpc.host.0.0        :  client: call_plugin ('bluetoothctl', 'expect', 'Confirm passkey (\\d+).*:') {}
13:03:23 OUT    host.0.0.bluetoothctl:  [bluetoothctl]> pair 70:1a:b8:73:99:bb
13:03:23 OUT    host.0.0.bluetoothctl:  Attempting to pair with 70:1A:B8:73:99:BB
13:03:23 OUT    host.0.0.bluetoothctl:  [bluetoothctl]> hci0 device_flags_changed: 70:1A:B8:73:99:BB (BR/EDR)
13:03:23 OUT    host.0.0.bluetoothctl:  [bluetoothctl]>      supp: 0x00000007  curr: 0x00000000
13:03:23 OUT    host.0.0.bluetoothctl:  [bluetoothctl]> hci0 type 7 discovering off
13:03:25 OUT    host.0.0.bluetoothctl:  [bluetoothctl]> hci0 70:1A:B8:73:99:BB type BR/EDR connected eir_len 12
13:03:25 OUT    host.0.0.bluetoothctl:  [bluetoothctl]> [BlueZ 5.86]> [CHG] Device 70:1A:B8:73:99:BB Connected: yes
13:03:25 OUT    host.0.0.bluetoothctl:  [BlueZ 5.86]> Request confirmation
13:03:25 DEBUG  rpc.host.0.0        :  client-reply
13:03:25 INFO   rpc.host.0.1        :  client: call_plugin ('bluetoothctl', 'expect', 'Confirm passkey 237345') {}
13:03:25 OUT    host.0.1.bluetoothctl:  [bluetoothctl]> hci0 84:5C:F3:77:31:19 type BR/EDR connected eir_len 12
13:03:25 OUT    host.0.1.bluetoothctl:  [bluetoothctl]> [NEW] Device 84:5C:F3:77:31:19 BlueZ 5.86
13:03:25 DEBUG  rpc.host.0.1        :  client-reply
13:03:25 INFO   rpc.host.0.0        :  client: call_plugin ('bluetoothctl', 'send', 'yes\n') {}
13:03:25 OUT    host.0.1.bluetoothctl:  [bluetoothctl]> [BlueZ 5.86]> Request confirmation
13:03:25 OUT    host.0.0.bluetoothctl:  [BlueZ 5.86]> [agent] Confirm passkey 237345 (yes/no): yes
13:03:25 DEBUG  rpc.host.0.0        :  client-reply
13:03:25 INFO   rpc.host.0.1        :  client: call_plugin ('bluetoothctl', 'send', 'yes\n') {}
13:03:25 OUT    host.0.1.bluetoothctl:  [BlueZ 5.86]> [agent] Confirm passkey 237345 (yes/no): yes
13:03:25 DEBUG  rpc.host.0.1        :  client-reply
13:03:25 INFO   rpc.host.0.0        :  client: call_plugin ('bluetoothctl', 'expect', 'Pairing successful') {}
13:03:25 OUT    host.0.0.bluetoothctl:  yes
13:03:25 OUT    host.0.0.bluetoothctl:  [BlueZ 5.86]> hci0 new_link_key 70:1A:B8:73:99:BB type 0x08 pin_len 0 store_hint 1
13:03:25 OUT    host.0.0.bluetoothctl:  [BlueZ 5.86]> [CHG] Device 70:1A:B8:73:99:BB Bonded: yes
13:03:26 OUT    host.0.0.bluetoothctl:  [BlueZ 5.86]> [CHG] Device 70:1A:B8:73:99:BB AddressType: public
13:03:26 OUT    host.0.0.bluetoothctl:  [BlueZ 5.86]> [CHG] Device 70:1A:B8:73:99:BB UUIDs: 0000110c-0000-1000-8000-00805f9b34fb
13:03:26 OUT    host.0.0.bluetoothctl:  [BlueZ 5.86]> [CHG] Device 70:1A:B8:73:99:BB UUIDs: 0000110e-0000-1000-8000-00805f9b34fb
13:03:26 DEBUG  rpc.host.0.0        :  client-reply
PASSED                                                                   [100%]
------------------------------ live log teardown -------------------------------
13:03:26 OUT    host.0.0.bluetoothctl:  [BlueZ 5.86]> [CHG] Device 70:1A:B8:98:FF:qemu-system-x86_64: terminating on signal 15 from pid 149357 (python3)

======================= 1 passed, 4 deselected in 13.22s =======================

$ test/test-functional -k test_btmgmt --kernel=../linux --trace
============================= test session starts ==============================
platform linux -- Python 3.14.3, pytest-8.3.5, pluggy-1.6.0
rootdir: /home/pauli/prj/external/bluez/unit
configfile: pytest.ini
plugins: cov-5.0.0, forked-1.6.0, rerunfailures-15.0, timeout-2.4.0, xdist-3.7.0, hypothesis-6.123.0, flaky-3.8.1, anyio-4.12.1
collected 5 items / 4 deselected / 1 selected

test/functional/test_btmgmt_vm.py
>>>>>>>>>>>>>>>>>>>> PDB runcall (IO-capturing turned off) >>>>>>>>>>>>>>>>>>>>>
> /home/pauli/prj/external/bluez/test/functional/test_btmgmt_vm.py(19)test_btmgmt_info()
-> (host,) = hosts
(Pdb) n
> /home/pauli/prj/external/bluez/test/functional/test_btmgmt_vm.py(21)test_btmgmt_info()
-> result = host.call(
(Pdb) p host.bdaddr
'00:aa:01:00:00:42'
(Pdb) n
> /home/pauli/prj/external/bluez/test/functional/test_btmgmt_vm.py(22)test_btmgmt_info()
-> run,
(Pdb) n
> /home/pauli/prj/external/bluez/test/functional/test_btmgmt_vm.py(23)test_btmgmt_info()
-> [btmgmt, "--index", "0", "info"],
(Pdb) n
> /home/pauli/prj/external/bluez/test/functional/test_btmgmt_vm.py(24)test_btmgmt_info()
-> stdout=subprocess.PIPE,
(Pdb) n
> /home/pauli/prj/external/bluez/test/functional/test_btmgmt_vm.py(25)test_btmgmt_info()
-> stdin=subprocess.DEVNULL,
(Pdb) n
> /home/pauli/prj/external/bluez/test/functional/test_btmgmt_vm.py(26)test_btmgmt_info()
-> encoding="utf-8",
(Pdb) n
> /home/pauli/prj/external/bluez/test/functional/test_btmgmt_vm.py(21)test_btmgmt_info()
-> result = host.call(
(Pdb) n
> /home/pauli/prj/external/bluez/test/functional/test_btmgmt_vm.py(28)test_btmgmt_info()
-> assert result.returncode == 0
(Pdb) p result
CompletedProcess(args=['/home/pauli/prj/external/bluez/build/tools/btmgmt', '--index', '0', 'info'], returncode=0, stdout='hci0:\tPrimary controller\n\taddr 00:AA:01:00:00:42 version 11 manufacturer 1521 class 0x000000\n\tsupported settings: powered connectable fast-connectable discoverable bondable link-security ssp br/edr le advertising secure-conn debug-keys privacy static-addr phy-configuration cis-central cis-peripheral iso-broadcaster sync-receiver ll-privacy past-sender past-receiver \n\tcurrent settings: br/edr \n\tname \n\tshort name \n')
(Pdb) print(result.stdout)
hci0:	Primary controller
	addr 00:AA:01:00:00:42 version 11 manufacturer 1521 class 0x000000
	supported settings: powered connectable fast-connectable discoverable bondable link-security ssp br/edr le advertising secure-conn debug-keys privacy static-addr phy-configuration cis-central cis-peripheral iso-broadcaster sync-receiver ll-privacy past-sender past-receiver
	current settings: br/edr
	name
	short name
(Pdb) q

!!!!!!!!!!!!!!!!!!! _pytest.outcomes.Exit: Quitting debugger !!!!!!!!!!!!!!!!!!!
======================= 4 deselected in 75.91s (0:01:15) =======================

Pauli Virtanen (6):
  doc: add functional/integration testing documentation
  test: add functional/integration testing framework
  build: add functional testing target
  test: functional: impose Python code formatting
  test: functional: add some Agent1 interface tests
  test: functional: add basic obex file transfer tests

 Makefile.am                             |  10 +
 configure.ac                            |  22 ++
 doc/test-functional.rst                 | 313 ++++++++++++++++++++++++
 test/functional/__init__.py             |   2 +
 test/functional/conftest.py             |  48 ++++
 test/functional/requirements.txt        |   2 +
 test/functional/test_agent.py           |  46 ++++
 test/functional/test_bluetoothctl_vm.py | 152 ++++++++++++
 test/functional/test_btmgmt_vm.py       |  30 +++
 test/functional/test_obex.py            | 285 +++++++++++++++++++++
 test/functional/test_tests.py           |  23 ++
 test/pytest.ini                         |  17 ++
 test/test-functional                    |  21 ++
 test/test-functional-attach             |   7 +
 14 files changed, 978 insertions(+)
 create mode 100644 doc/test-functional.rst
 create mode 100644 test/functional/__init__.py
 create mode 100644 test/functional/conftest.py
 create mode 100644 test/functional/requirements.txt
 create mode 100644 test/functional/test_agent.py
 create mode 100644 test/functional/test_bluetoothctl_vm.py
 create mode 100644 test/functional/test_btmgmt_vm.py
 create mode 100644 test/functional/test_obex.py
 create mode 100644 test/functional/test_tests.py
 create mode 100644 test/pytest.ini
 create mode 100755 test/test-functional
 create mode 100755 test/test-functional-attach

-- 
2.54.0


^ permalink raw reply

* [PATCH BlueZ v6 1/6] doc: add functional/integration testing documentation
From: Pauli Virtanen @ 2026-06-13 15:48 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Pauli Virtanen
In-Reply-To: <cover.1781365708.git.pav@iki.fi>

Add documentation for functional/integration test suite.
---
 doc/test-functional.rst | 313 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 313 insertions(+)
 create mode 100644 doc/test-functional.rst

diff --git a/doc/test-functional.rst b/doc/test-functional.rst
new file mode 100644
index 000000000..35245da72
--- /dev/null
+++ b/doc/test-functional.rst
@@ -0,0 +1,313 @@
+===============
+test-functional
+===============
+
+**test-functional** [*OPTIONS*]
+
+DESCRIPTION
+===========
+
+**test-functional(1)** is used for functional testing of BlueZ and
+kernel using multiple virtual machine environments, connected by real
+or virtual controllers.
+
+It uses https://pypi.org/project/pytest-bluezenv as VM-based test
+framework. For details, see its documentation.
+
+QUICK EXAMPLE
+=============
+
+Install `qemu-system-x86_64` first. Then,
+
+.. code-block::
+
+   $ ./configure --enable-functional-testing --enable-testing --enable-tools
+   $ make -j8
+   $ python3 -mpip install -r test/functional/requirements.txt
+   $ test/test-functional --kernel-build -v
+
+OPTIONS
+=======
+
+The `test-functional` script simply runs `Pytest
+<https://pytest.org>`__ which can take the following options:
+https://docs.pytest.org/en/stable/reference/reference.html#command-line-flags
+
+The following additional options apply:
+
+``--list``
+	Output brief lists of existing tests.
+
+``--kernel=<image>``
+        Kernel image (or built Linux source tree root) to
+	use.  See **test-runner(1)** and `tester.config` for required
+	kernel config.
+
+	If not provided, value from `FUNCTIONAL_TESTING_KERNEL`
+	environment variable is used. If none, no image is used.
+
+``--usb=hci0,hci1``
+        USB controllers to use in tests that require use of
+	real controllers.
+
+	If not provided, value from `FUNCTIONAL_TESTING_CONTROLLERS`
+	environment variable is used. If none, all USB controllers
+	with suitable permissions are considered.
+
+``--force-usb``
+        Force tests to use USB controllers instead of `btvirt`.
+
+``--bluez-build-dir=<path>``
+        Path to build directory where to search for BlueZ
+        executables.
+
+``--bluez-src-dir=<path>``
+        Path to build BlueZ source directory.
+
+``--log-filter=[+-]<pattern>,[+-]<pattern>,...``
+        Allow/deny lists
+	for filtering logging output. The pattern is a shell glob matching
+	to the logger names.
+
+``--no-log-reorder``
+	Don't reorder logs to timestamp order.
+
+``--vm-timeout=<seconds>``
+        Specify timeout for communication with VM hosts.
+
+``--btmon``
+        Launch btmon on all hosts to log events, and dump traffic to
+	test-bluezenv-\*.btsnoop
+
+``--kernel-build=no/use/auto/force``
+        Build a suitable kernel image from source.
+
+``--kernel-upstream=<GIT_URL>``
+        URL for Git clone of kernel sources.
+
+``--kernel-branch=<GIT_BRANCH>``
+        Git branch to build from.
+
+
+Tests that require kernel image or USB controllers are skipped if none
+are available. Normally, tests use `btvirt`.
+
+VM instances share a directory ``/run/shared`` with host machine,
+located on host usually in ``/tmp/bluez-func-test-*/shared-*``.  Core
+dumps etc. are copied out from it before test instance is shut down.
+
+REQUIREMENTS
+============
+
+General
+-------
+
+The following are needed:
+
+- QEmu (x86_64)
+- ``dbus-daemon`` available
+
+Recommended:
+
+- KVM-enabled x86_64 host system
+- Preferably built BlueZ source tree
+- ``chronyd`` available
+- ``util-linux`` tools available
+- ``agetty`` available
+
+Python
+------
+
+The following Python packages are required:
+
+.. code-block::
+
+	pytest>=8
+	pytest-bluezenv==0.1.6
+
+To install them via pip::
+
+	python3 -m pip install -r test/functional/requirements.txt
+
+On Fedora / RHEL, the dependencies aside from `pytest-bluezenv` can be
+installed via::
+
+	sudo dnf install python3-pytest python3-pexpect python3-dbus
+
+Kernel
+------
+
+The **test-functional(1)** tool requires a kernel image with similar
+config as **test-runner(1)**.  If given `--kernel-build` option, a
+suitable image is built from sources downloaded under
+`test/.pytest_cache`.
+
+Simplest setup is
+
+.. code-block::
+
+	cp ../bluez/doc/tester.config .config
+	make olddefconfig
+	make -j8
+
+To get log timestamps right, the kernel should have the following
+configuration enabled:
+
+.. code-block::
+
+	CONFIG_HYPERVISOR_GUEST=y
+	CONFIG_PARAVIRT=y
+	CONFIG_KVM_GUEST=y
+
+	CONFIG_PTP_1588_CLOCK=y
+	CONFIG_PTP_1588_CLOCK_KVM=y
+	CONFIG_PTP_1588_CLOCK_VMCLOCK=y
+
+USB
+---
+
+Some tests may require a hardware controller instead of the virtual `btvirt` one.
+
+EXAMPLES
+========
+
+Run all tests
+-------------
+
+.. code-block::
+
+	$ test/test-functional --kernel=/pathto/bzImage
+
+	$ export FUNCTIONAL_TESTING_KERNEL=/pathto/bzImage
+	$ test/test-functional
+
+Test output is logged in ``test-functional.log``.
+
+Show output during run
+----------------------
+
+.. code-block::
+
+	$ test/test-functional --log-cli-level=0
+
+Show only specific loggers:
+
+.. code-block::
+
+	$ test/test-functional --log-cli-level=0 --log-filter=rpc,host
+
+	$ test/test-functional --log-cli-level=0 --log-filter=*.bluetoothctl
+
+Filter out loggers:
+
+.. code-block::
+
+	$ test/test-functional --log-cli-level=0 --log-filter=-host
+
+	$ test/test-functional --log-cli-level=0 --log-filter=host,-host.*.1
+
+Run selected tests
+------------------
+
+.. code-block::
+
+	$ test/test-functional test/functional/test_cli_simple.py::test_bluetoothctl_script_show
+
+	$ test/test-functional -k test_bluetoothctl_script_show
+
+	$ test/test-functional -k 'test_btmgmt or test_bluetoothctl'
+
+Don't run tests with a given marker:
+
+.. code-block::
+
+	$ test/test-functional -m "not pipewire"
+
+Don't run known-failing tests:
+
+.. code-block::
+
+	$ test/test-functional -m "not xfail"
+
+Note that otherwise known-failing tests would be run, but with
+failures suppressed.
+
+Run previously failed and stop on failure
+-----------------------------------------
+
+.. code-block::
+
+	$ test/test-functional -x --ff
+
+List all tests
+--------------
+
+.. code-block::
+
+	$ test/test-functional --list
+
+Show errors from know-failing test
+----------------------------------
+
+.. code-block::
+
+	$ test/test-functional --runxfail -k test_btmgmt_info
+
+Redirect USB devices
+--------------------
+
+.. code-block::
+
+	$ test/test-functional --usb=hci0,hci1
+
+	$ export FUNCTIONAL_TESTING_CONTROLLERS=hci0,hci1
+	$ test/test-functional -vv
+
+This does not require running as root. Changing device permissions is
+sufficient. In verbose mode (``-vv``) some instructions are printed.
+
+Run all tests using the USB controllers:
+
+.. code-block::
+
+	$ test/test-functional --usb=hci0,hci1 --force-usb
+
+Run tests in parallel
+---------------------
+
+pytest-xdist is required for parallel execution. To run:
+
+.. code-block::
+
+	$ test/test-functional -n auto --dist loadgroup
+
+Logging in to a test VM instance
+--------------------------------
+
+While test is running:
+
+.. code-block::
+
+	$ test/test-functional-attach
+
+For this to be useful, usually, you need to pause the test
+e.g. by running with ``--trace`` option.
+
+To do it manually, when starting the tester will log a line like::
+
+	TTY: socat /tmp/bluez-func-test-q658swgi/bluez-func-test-tty-0 STDIO,rawer
+
+with the location of the socket where the serial is connected to.
+
+WRITING TESTS
+=============
+
+The functional tests are written in files (test modules) names
+`test/functional/test_*.py`.  They are written using standard Pytest
+style.  See https://docs.pytest.org/en/stable/getting-started.html
+
+See https://pypi.org/project/pytest-bluezenv/ for documentation of
+how to write VM-using tests.
+
+Use `Black <https://black.readthedocs.io/en/stable/>`__ to autoformat
+Python test code.
-- 
2.54.0


^ permalink raw reply related

* [PATCH] Bluetooth: hci_uart: clear HCI_UART_SENDING when write_work is canceled
From: Pauli Virtanen @ 2026-06-13 15:29 UTC (permalink / raw)
  To: linux-bluetooth
  Cc: Pauli Virtanen, marcel, luiz.dentz, 25181214217, linux-kernel,
	stable

HCI_UART_SENDING bit in tx_state means write_work is pending and blocks
queueing it again.  Currently this bit is not cleared when canceling the
work in hci_uart_close(), which blocks future writes when device is
reopened later if write_work was pending.

Fix by clearing HCI_UART_SENDING when canceling the work.

Also make clearing of tx_skb safe by using disable_work_sync +
enable_work instead of just cancel_work_sync.  hci_uart_flush() purges
the proto tx queue so we can cancel the pending write_work there,
instead of doing it just in hci_uart_close().

Fixes: c1bb9336ae6b ("Bluetooth: hci_uart: fix UAFs and race conditions in close and init paths")
Link: https://lore.kernel.org/linux-bluetooth/07e0a28650773abec711ee492fdb1bf5d21a6c98.camel@iki.fi/
Cc: stable@vger.kernel.org
Signed-off-by: Pauli Virtanen <pav@iki.fi>
---
 drivers/bluetooth/hci_ldisc.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index 47f4902b40b4..b0708ec9751c 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -239,10 +239,17 @@ static int hci_uart_flush(struct hci_dev *hdev)
 
 	BT_DBG("hdev %p tty %p", hdev, tty);
 
+	disable_work_sync(&hu->write_work);
+
 	if (hu->tx_skb) {
 		kfree_skb(hu->tx_skb); hu->tx_skb = NULL;
 	}
 
+	if (test_and_clear_bit(HCI_UART_SENDING, &hu->tx_state))
+		wake_up_bit(&hu->tx_state, HCI_UART_SENDING);
+
+	enable_work(&hu->write_work);
+
 	/* Flush any pending characters in the driver and discipline. */
 	tty_ldisc_flush(tty);
 	tty_driver_flush_buffer(tty);
@@ -271,12 +278,8 @@ static int hci_uart_open(struct hci_dev *hdev)
 /* Close device */
 static int hci_uart_close(struct hci_dev *hdev)
 {
-	struct hci_uart *hu = hci_get_drvdata(hdev);
-
 	BT_DBG("hdev %p", hdev);
 
-	cancel_work_sync(&hu->write_work);
-
 	hci_uart_flush(hdev);
 	hdev->flush = NULL;
 	return 0;
-- 
2.54.0


^ permalink raw reply related

* [PATCH BlueZ] emulator: btvirt: support debug for -s socket server
From: Pauli Virtanen @ 2026-06-13 15:20 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Pauli Virtanen

Support btdev debug -d when using socket server -s.

$ btvirt -d -s
...
bredrle: host10: > 01 13 0c f8 00 00 00 00 00 00 00 00 00 00 00 00  ................
bredrle: host10:   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
...
---
 emulator/main.c   | 16 ++++++++++++++++
 emulator/server.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
 emulator/server.h |  5 +++++
 3 files changed, 66 insertions(+)

diff --git a/emulator/main.c b/emulator/main.c
index 09d6e9adb..c21640adc 100644
--- a/emulator/main.c
+++ b/emulator/main.c
@@ -80,6 +80,13 @@ static void vhci_debug(const char *str, void *user_data)
 	printf("vhci%u: %s\n", i, str);
 }
 
+static void server_debug(const char *str, void *user_data)
+{
+	const char *name = user_data;
+
+	printf("%s: %s\n", name, str);
+}
+
 int main(int argc, char *argv[])
 {
 	struct server *server1;
@@ -231,6 +238,15 @@ int main(int argc, char *argv[])
 		server5 = server_open_unix(SERVER_TYPE_MONITOR, path);
 		if (!server5)
 			fprintf(stderr, "Failed to open monitor server\n");
+
+		if (debug_enabled) {
+			server_set_debug(server1, server_debug, "bredrle",
+									NULL);
+			server_set_debug(server2, server_debug, "bredr", NULL);
+			server_set_debug(server3, server_debug, "amp", NULL);
+			server_set_debug(server4, server_debug, "le", NULL);
+			server_set_debug(server5, server_debug, "mon", NULL);
+		}
 	}
 
 	if (tcp_port) {
diff --git a/emulator/server.c b/emulator/server.c
index 7790867b7..4538e8f04 100644
--- a/emulator/server.c
+++ b/emulator/server.c
@@ -39,10 +39,14 @@ struct server {
 	enum server_type type;
 	uint16_t id;
 	int fd;
+	server_debug_func_t debug_callback;
+	server_destroy_func_t debug_destroy;
+	void *debug_data;
 };
 
 struct client {
 	int fd;
+	struct server *server;
 	struct btdev *btdev;
 	uint8_t *pkt_data;
 	uint8_t pkt_type;
@@ -223,6 +227,18 @@ static int accept_client(int fd)
 	return nfd;
 }
 
+static void dev_debug(const char *str, void *user_data)
+{
+	struct client *client = user_data;
+	struct server *server = client->server;
+	char buf[512];
+
+	if (server->debug_callback) {
+		snprintf(buf, sizeof(buf), "host%d: %s", client->fd, str);
+		server->debug_callback(buf, server->debug_data);
+	}
+}
+
 static void server_accept_callback(int fd, uint32_t events, void *user_data)
 {
 	struct server *server = user_data;
@@ -240,6 +256,8 @@ static void server_accept_callback(int fd, uint32_t events, void *user_data)
 
 	memset(client, 0, sizeof(*client));
 
+	client->server = server;
+
 	client->fd = accept_client(server->fd);
 	if (client->fd < 0) {
 		free(client);
@@ -271,6 +289,7 @@ static void server_accept_callback(int fd, uint32_t events, void *user_data)
 	}
 
 	btdev_set_send_handler(client->btdev, client_write_callback, client);
+	btdev_set_debug(client->btdev, dev_debug, client, NULL);
 
 done:
 	if (mainloop_add_fd(client->fd, EPOLLIN, client_read_callback,
@@ -413,4 +432,30 @@ void server_close(struct server *server)
 		return;
 
 	mainloop_remove_fd(server->fd);
+
+	if (server->debug_destroy)
+		server->debug_destroy(server->debug_data);
+
+	server->debug_callback = NULL;
+	server->debug_destroy = NULL;
+	server->debug_data = NULL;
+
+	free(server);
 }
+
+bool server_set_debug(struct server *server, server_debug_func_t callback,
+			void *user_data, server_destroy_func_t destroy)
+{
+	if (!server)
+		return false;
+
+	if (server->debug_destroy)
+		server->debug_destroy(server->debug_data);
+
+	server->debug_callback = callback;
+	server->debug_destroy = destroy;
+	server->debug_data = user_data;
+
+	return true;
+}
+
diff --git a/emulator/server.h b/emulator/server.h
index 7d6b7be74..1844a9871 100644
--- a/emulator/server.h
+++ b/emulator/server.h
@@ -24,3 +24,8 @@ struct server;
 struct server *server_open_unix(enum server_type type, const char *path);
 struct server *server_open_tcp(enum server_type type, uint16_t port);
 void server_close(struct server *server);
+
+typedef void (*server_debug_func_t)(const char *str, void *user_data);
+typedef void (*server_destroy_func_t)(void *user_data);
+bool server_set_debug(struct server *server, server_debug_func_t callback,
+				void *user_data, server_destroy_func_t destroy);
-- 
2.54.0


^ permalink raw reply related

* [Bug 73081] Fail to setup Bluetooth on Dell Venue 11 Pro
From: bugzilla-daemon @ 2026-06-13 15:17 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <bug-73081-62941@https.bugzilla.kernel.org/>

https://bugzilla.kernel.org/show_bug.cgi?id=73081

--- Comment #12 from Dmitry Khromov (icechrome@gmail.com) ---
@Hytham, noted.

First, please disregard everything I said about `CONFIG_SERIAL_DEV_BUG` -- got
another Baytrail device mixed up with this one, my bad. That said, the actual
problem, according to my notes, is the UART's `baud_base` (2764800), resulting
in framing errors with common baud rates (i.e. 3000000 and 3500000). The speed
the controller is pre-set to is 3768000. I've dug the tablet up and with
semi-recent musl-based Void rootfs and kernel 6.18.35 (CONFIG_SERIAL_DEV_BUS=m,
btw) got `btattach -B /dev/ttyS1 -P ath3k` working by manually setting the
speed with a `TCSETS2` ioctl. I’ve managed to pair and test some BT
peripherals.

@Paul, since, ultimately, this isn’t a kernel bug (though a patch for
rfkill-gpio is still required), should this discussion be continued on GitHub?

-- 
You may reply to this email to add a comment.

You are receiving this mail because:
You are the assignee for the bug.

^ permalink raw reply

* [Bug 73081] Fail to setup Bluetooth on Dell Venue 11 Pro
From: bugzilla-daemon @ 2026-06-13 13:08 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <bug-73081-62941@https.bugzilla.kernel.org/>

https://bugzilla.kernel.org/show_bug.cgi?id=73081

--- Comment #11 from Hytham (hytham@gmail.com) ---
Hi Dmitry,

I followed the instructions in https://github.com/bluez/bluez/issues/2222 to
copy the firmware to this directory and rebooted which solved the Wifi issue
but Bluetooth is yet not working. I provided additional logs in the bluez
ticket.

Thanks,
Hytham

-- 
You may reply to this email to add a comment.

You are receiving this mail because:
You are the assignee for the bug.

^ permalink raw reply

* [REGRESSION] Bluetooth: hci_uart: fix UAFs and race conditions in close and init paths
From: Pauli Virtanen @ 2026-06-13 12:58 UTC (permalink / raw)
  To: patchwork-bot+bluetooth, w15303746062
  Cc: luiz.dentz, pmenzel, marcel, linux-bluetooth, linux-kernel,
	stable, 25181214217
In-Reply-To: <177920280488.2756414.8251481561878776667.git-patchwork-notify@kernel.org>

Hi,

ti, 2026-05-19 kello 15:00 +0000, patchwork-bot+bluetooth@kernel.org
kirjoitti:
> Hello:
> 
> This patch was applied to bluetooth/bluetooth-next.git (master)
> by Luiz Augusto von Dentz <luiz.von.dentz@intel.com>:
> 
> On Mon, 18 May 2026 10:49:49 +0800 you wrote:
> > From: Mingyu Wang <25181214217@stu.xidian.edu.cn>
> > 
> > Vulnerabilities leading to Use-After-Free (UAF) and Null Pointer
> > Dereference (NPD) conditions were observed in the lifecycle management
> > of hci_uart.
> > 
> > The primary issue arises because the workqueues (init_ready and
> > write_work) are only flushed/cancelled if the HCI_UART_PROTO_READY
> > flag is set during TTY close. If a hangup occurs before setup completes,
> > hci_uart_tty_close() skips the teardown of these workqueues and
> > proceeds to free the `hu` struct. When the scheduled work executes
> > later, it blindly dereferences the freed `hu` struct.
> > 
> > [...]
> 
> Here is the summary with links:
>   - [v9] Bluetooth: hci_uart: fix UAFs and race conditions in close and init paths
>     https://git.kernel.org/bluetooth/bluetooth-next/c/7db62a762f61
> 
> You are awesome, thank you!

This patch (c1bb9336ae6b54a5f6a353c4bd4ed9a4307e429b upstream) appears
to cause a regression in the following test case, which does 
btmgmt power off; btmgmt power on; in a loop.

At some point response to Reset command is not received, and the
(emulated) controller can no longer be powered on.

Found by noting that newer kernel versions fail automated testing.

Kernel built with the bluez tester config
https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/tester.config

With c1bb9336ae6b54a5f6a353c4bd4ed9a4307e429b reverted, the power
off/on toggle continues indefinitely without errors.

Didn't investigate so far why precisely it starts failing.


$ cd bluez
$ git rev-parse HEAD
40f2e34b373944cf8142154881ce69f92c2be68d
$ make tools/test-runner emulator/btvirt
$ bash xtest.sh
...
hci0 Set Powered complete, settings: powered br/edr 
hci0 Set Powered complete, settings: br/edr 
hci0 Set Powered complete, settings: powered br/edr 
hci0 Set Powered complete, settings: br/edr 
Bluetooth: hci0: Opcode 0x0c03 failed: -110
Set Powered for hci0 failed with status 0x05 (Authentication Failed)
Set Powered for hci0 failed with status 0x05 (Authentication Failed)
Process 38 exited with status 0
reboot: Restarting system
reboot: machine restart
Set Powered for hci0 failed with status 0x05 (Authentication Failed)
Set Powered for hci0 failed with status 0x05 (Authentication Failed)
FAIL

----8<---- xtest.sh
#!/bin/sh

KERNEL=../linux/arch/x86_64/boot/bzImage

cat <<EOF > xtest-run.sh
for j in \$(seq 1 100); do
    ./tools/btmgmt power off 2>&1 | tee /tmp/test.log
    ./tools/btmgmt power on 2>&1 | tee -a /tmp/test.log
    if grep 'Authentication Failed' /tmp/test.log; then break; fi
done
EOF

./emulator/btvirt -s &
trap 'kill $(jobs -p)' EXIT

./tools/test-runner -k $KERNEL -u/tmp/bt-server-bredrle -- bash xtest-run.sh 2>&1 | tee xtest.log

if grep 'Authentication Failed' xtest.log; then
    echo "FAIL"
    exit 1
else
    echo "OK"
    exit 0
fi
----8<----

-- 
Pauli Virtanen

^ permalink raw reply

* Re: [PATCH v3] Bluetooth: hci_conn: Fix null ptr deref in hci_abort_conn()
From: XIAO WU @ 2026-06-13 10:40 UTC (permalink / raw)
  To: Siwei Zhang, Luiz Augusto von Dentz; +Cc: linux-bluetooth
In-Reply-To: <20260611152039.2176565-1-oss@fourdim.xyz>

Hi Siwei,

On Thu, 11 Jun 2026 11:19:52 -0400, Siwei Zhang wrote:
 > Bluetooth: hci_conn: Fix null ptr deref in hci_abort_conn()

This patch correctly fixes the NULL dereference in hci_abort_conn() by
tracking in-flight create commands with HCI_CONN_CREATE.

I noticed a Sashiko review[1] of this patch flagged that the new
clear_bit(HCI_CONN_CREATE, &conn->flags) calls after
__hci_cmd_sync_status_sk() introduce a use-after-free.  I wrote a PoC
to verify this and was able to trigger it reliably on a KASAN-enabled
kernel.

The race:

   If the controller rejects the ACL connection attempt (e.g. via
   Command Status with a non-zero status), the RX thread processes the
   rejection in hci_cs_create_conn() → hci_conn_del(), freeing the
   hci_conn object.  Shortly after, __hci_cmd_sync_status_sk() returns
   the error to hci_acl_create_conn_sync() on the hci_cmd_sync_work
   worker, which then writes to the freed conn via clear_bit().

My PoC opens /dev/vhci, creates a virtual controller that responds to
HCI_OP_CREATE_CONN with Command Status error 0x2e, powers on the
controller, and triggers an L2CAP connect.  This reliably hits:

==================================================================
BUG: KASAN: slab-use-after-free in hci_acl_create_conn_sync+0x3c6/0x600
Write of size 8 at addr ffff88802eed2950 by task kworker/u11:0/57
Workqueue: hci0 hci_cmd_sync_work

Call Trace:
  <TASK>
  dump_stack_lvl+0x116/0x1f0
  print_report+0xf4/0x600
  kasan_report+0xe0/0x110
  kasan_check_range+0x100/0x1b0
  hci_acl_create_conn_sync+0x3c6/0x600    <-- clear_bit on freed conn
  hci_cmd_sync_work+0x1b0/0x480
  process_one_work+0xa20/0x1c50
  worker_thread+0x6df/0xf30
  kthread+0x387/0x4a0

Allocated by task 9349 (L2CAP connect):
  __hci_conn_add+0xfd/0x1df0
  hci_conn_add_unset+0x7b/0x130
  hci_connect_acl+0x4aa/0x7c0
  l2cap_chan_connect+0x779/0x2160
  l2cap_sock_connect+0x381/0x7a0

Freed by task 9353 (RX thread):
  kfree+0x171/0x720
  device_release+0xd7/0x280
  hci_conn_del_sysfs+0x17b/0x1a0
  hci_conn_del+0x685/0x11d0
  hci_cs_create_conn+0x1e9/0x430     <-- controller rejection
  hci_cmd_status_evt+0x267/0x790
  hci_event_packet+0x521/0xce0
  hci_rx_work+0x2ce/0x1030
==================================================================

The race window:

   hci_acl_create_conn_sync()           hci_rx_work()
   ==========================           ==============
   __hci_cmd_sync_status_sk(...)        hci_cs_create_conn()
     → waiting for controller reply       → hci_conn_del()
                                          → kfree(conn)
   clear_bit(HCI_CONN_CREATE,
     &conn->flags);  ← UAF

The same pattern exists in hci_le_create_conn_sync().

One possible fix: take a reference on conn before the cmd_sync call
and drop it after clear_bit(), or move the clear_bit to a point where
the conn is still guaranteed to be alive.  The Sashiko review[1]
points out a few other issues in the same patch as well.

I wrote the following PoC.  It opens /dev/vhci, emulates a controller
that rejects CREATE_CONN, powers up via MGMT, and triggers an L2CAP
connect to exercise the race.

---8<--- poc.c ---
/*
  * PoC for UAF in hci_acl_create_conn_sync()
  *
  * Opens /dev/vhci, creates a virtual HCI controller that responds to
  * HCI_OP_CREATE_CONN with Command Status 0x2e 
(HCI_ERROR_COMMAND_DISALLOWED).
  * The RX thread processes this via hci_cs_create_conn() and frees the 
conn,
  * while the hci_cmd_sync_work worker then hits the UAF in clear_bit().
  *
  * Build:  gcc -Wall -O2 -o poc poc.c -lpthread
  * Run:    ./poc   (root, KASAN-enabled kernel, vhci loaded)
  */
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/poll.h>
#include <pthread.h>
#include <stdint.h>

#define HCI_COMMAND_PKT 0x01
#define HCI_EVENT_PKT    0x04
#define HCI_VENDOR_PKT   0xff
#define HCI_EV_CMD_COMPLETE 0x0e
#define HCI_EV_CMD_STATUS   0x0f
#define HCI_OP_CREATE_CONN  0x0405
#define HCI_OP_RESET        0x0c03
#define BTPROTO_L2CAP   0
#define BTPROTO_HCI     1
#define BDADDR_BREDR    0x00
#define HCI_CHANNEL_CONTROL 3

struct sockaddr_l2 {
     uint16_t l2_family, l2_psm;
     uint8_t  l2_bdaddr[6];
     uint16_t l2_cid;
     uint8_t  l2_bdaddr_type;
} __attribute__((packed));

struct sockaddr_hci {
     uint16_t hci_family, hci_dev, hci_channel;
};

static volatile int vhci_fd = -1;
static volatile int saw_conn = 0;

static int send_evt(uint8_t e, const void *d, uint8_t dl)
{
     uint8_t b[512];
     b[0] = HCI_EVENT_PKT; b[1] = e; b[2] = dl;
     if (dl && d) memcpy(b + 3, d, dl);
     return write(vhci_fd, b, 3 + dl);
}

static int read_cmd(uint16_t *o, uint8_t *p, int *pl, int tmo)
{
     uint8_t b[8192];
     struct pollfd pf = {.fd = vhci_fd, .events = POLLIN};
     int r = poll(&pf, 1, tmo);
     if (r <= 0) return -1;
     r = read(vhci_fd, b, sizeof(b));
     if (r < 4 || b[0] != HCI_COMMAND_PKT) return -1;
     *o = b[1] | (b[2] << 8); *pl = b[3];
     if (p && *pl) memcpy(p, b + 4, (*pl < r - 4) ? *pl : r - 4);
     return 1;
}

static void send_ok(uint16_t o) { uint8_t r[1] = {0}; 
send_evt(HCI_EV_CMD_COMPLETE, r, 1); }
static void send_cc(uint16_t o, const void *rd, uint8_t rl) { 
send_evt(HCI_EV_CMD_COMPLETE, rd, rl); }
static void send_cs(uint16_t o, uint8_t s) {
     uint8_t p[4] = {s, 1, o & 0xff, (o >> 8) & 0xff};
     send_evt(HCI_EV_CMD_STATUS, p, 4);
}

static void *init_thr(void *a)
{
     (void)a;
     uint16_t o; uint8_t p[256]; int pl;
     while (1) {
         if (read_cmd(&o, p, &pl, 2000) < 0) { usleep(50000); continue; }
         if (o == HCI_OP_CREATE_CONN) {
             /* Reject with Command Status error 0x2e */
             send_cs(o, 0x2e);
             saw_conn = 1;
             continue;
         }
         if (o == HCI_OP_RESET) { send_ok(o); continue; }
         /* ... handle many other HCI commands for init ... */
         send_ok(o);
     }
     return 0;
}

struct mgmt_hdr { uint16_t opcode, index, len; } __attribute__((packed));
#define MGMT_OP_SET_POWERED     0x0005
#define MGMT_OP_SET_CONNECTABLE 0x000b

int main(void)
{
     printf("[*] open vhci\n");
     vhci_fd = open("/dev/vhci", O_RDWR);
     if (vhci_fd < 0) { perror("vhci"); return 1; }
     uint8_t c[2] = {HCI_VENDOR_PKT, 0}; write(vhci_fd, c, 2);

     printf("[*] start vhci init thread\n");
     pthread_t t; pthread_create(&t, 0, init_thr, 0);
     sleep(6);

     /* Power on via MGMT */
     int mgmt = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
     if (mgmt >= 0) {
         struct sockaddr_hci ha = {AF_BLUETOOTH, 0xffff, 
HCI_CHANNEL_CONTROL};
         if (bind(mgmt, (struct sockaddr *)&ha, sizeof(ha)) == 0) {
             uint8_t cmd[256];
             struct mgmt_hdr *hdr = (struct mgmt_hdr *)cmd;
             hdr->opcode = MGMT_OP_SET_POWERED; hdr->index = 0; hdr->len 
= 1;
             cmd[sizeof(*hdr)] = 1;
             write(mgmt, cmd, sizeof(*hdr) + 1);
             usleep(200000);
             hdr->opcode = MGMT_OP_SET_CONNECTABLE;
             write(mgmt, cmd, sizeof(*hdr) + 1);
             usleep(200000);
         }
         close(mgmt);
     }

     /* L2CAP connect triggers hci_connect_acl → hci_acl_create_conn_sync */
     printf("[*] L2CAP connect (trigger)\n");
     int l2 = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
     if (l2 >= 0) {
         struct sockaddr_l2 ba; memset(&ba, 0, sizeof(ba));
         ba.l2_family = AF_BLUETOOTH; ba.l2_bdaddr_type = BDADDR_BREDR;
         bind(l2, (struct sockaddr *)&ba, sizeof(ba));
         struct sockaddr_l2 ca; memset(&ca, 0, sizeof(ca));
         ca.l2_family = AF_BLUETOOTH; ca.l2_psm = 1;
         ca.l2_bdaddr_type = BDADDR_BREDR;
         memset(ca.l2_bdaddr, 0x11, 6);
         connect(l2, (struct sockaddr *)&ca, sizeof(ca));
         close(l2);
     }
     usleep(500000);
     pthread_cancel(t); pthread_join(t, 0); close(vhci_fd);
     printf("[*] done. Check dmesg for KASAN slab-use-after-free.\n");
     return 0;
}
---8<---

Hope this helps with the patch.  Let me know if you need additional
information from the test setup.

[1] 
https://sashiko.dev/#/patchset/20260611152039.2176565-1-oss%40fourdim.xyz


^ permalink raw reply

* [syzbot] [bluetooth?] INFO: trying to register non-static key in bt_accept_unlink
From: syzbot @ 2026-06-13  8:24 UTC (permalink / raw)
  To: linux-bluetooth, linux-kernel, luiz.dentz, marcel, syzkaller-bugs

Hello,

syzbot found the following issue on:

HEAD commit:    2d3090a8aeb5 Merge tag 'v7.1-p5' of git://git.kernel.org/p..
git tree:       upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=157291b6580000
kernel config:  https://syzkaller.appspot.com/x/.config?x=65472e27d1590a04
dashboard link: https://syzkaller.appspot.com/bug?extid=534002670dd34a114fdc
compiler:       Debian clang version 21.1.8 (++20251221033036+2078da43e25a-1~exp1~20251221153213.50), Debian LLD 21.1.8

Unfortunately, I don't have any reproducer for this issue yet.

Downloadable assets:
disk image: https://storage.googleapis.com/syzbot-assets/90834e94de32/disk-2d3090a8.raw.xz
vmlinux: https://storage.googleapis.com/syzbot-assets/e27c57900a9a/vmlinux-2d3090a8.xz
kernel image: https://storage.googleapis.com/syzbot-assets/210244c0b7d3/bzImage-2d3090a8.xz

IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+534002670dd34a114fdc@syzkaller.appspotmail.com

Bluetooth: hci1: hardware error 0x00
INFO: trying to register non-static key.
The code is fine but needs lockdep annotation, or maybe
you didn't initialize this object before use?
turning off the locking correctness validator.
CPU: 1 UID: 0 PID: 5637 Comm: kworker/u9:3 Tainted: G             L      syzkaller #0 PREEMPT(full) 
Tainted: [L]=SOFTLOCKUP
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 05/09/2026
Workqueue: hci1 hci_error_reset
Call Trace:
 <TASK>
 dump_stack_lvl+0xe8/0x150 lib/dump_stack.c:120
 assign_lock_key+0x133/0x150 kernel/locking/lockdep.c:984
 register_lock_class+0xcc/0x2e0 kernel/locking/lockdep.c:1299
 __lock_acquire+0xad/0x2cf0 kernel/locking/lockdep.c:5112
 lock_acquire+0x106/0x350 kernel/locking/lockdep.c:5868
 __raw_spin_lock_bh include/linux/spinlock_api_smp.h:150 [inline]
 _raw_spin_lock_bh+0x36/0x50 kernel/locking/spinlock.c:182
 spin_lock_bh include/linux/spinlock.h:348 [inline]
 bt_accept_unlink+0x65/0x2c0 net/bluetooth/af_bluetooth.c:265
 l2cap_sock_teardown_cb+0x17e/0x490 net/bluetooth/l2cap_sock.c:1682
 l2cap_chan_del+0xb5/0x610 net/bluetooth/l2cap_core.c:658
 l2cap_conn_del+0x33d/0x570 net/bluetooth/l2cap_core.c:1804
 hci_disconn_cfm include/net/bluetooth/hci_core.h:2154 [inline]
 hci_conn_hash_flush+0x10d/0x260 net/bluetooth/hci_conn.c:2736
 hci_dev_close_sync+0x85d/0x1150 net/bluetooth/hci_sync.c:5383
 hci_dev_do_close net/bluetooth/hci_core.c:502 [inline]
 hci_error_reset+0x127/0x4c0 net/bluetooth/hci_core.c:998
 process_one_work kernel/workqueue.c:3314 [inline]
 process_scheduled_works+0xb5d/0x1860 kernel/workqueue.c:3397
 worker_thread+0xa53/0xfc0 kernel/workqueue.c:3478
 kthread+0x389/0x470 kernel/kthread.c:436
 ret_from_fork+0x514/0xb70 arch/x86/kernel/process.c:158
 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
 </TASK>
 slab kmalloc-2k start ffff888029aaa000 pointer offset 1400 size 2048
list_del corruption. prev->next should be ffff8880682f5578, but was 0000000000000001. (prev=ffff888029aaa578)
------------[ cut here ]------------
kernel BUG at lib/list_debug.c:64!
Oops: invalid opcode: 0000 [#1] SMP KASAN NOPTI
CPU: 1 UID: 0 PID: 5637 Comm: kworker/u9:3 Tainted: G             L      syzkaller #0 PREEMPT(full) 
Tainted: [L]=SOFTLOCKUP
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 05/09/2026
Workqueue: hci1 hci_error_reset
RIP: 0010:__list_del_entry_valid_or_report+0x15a/0x190 lib/list_debug.c:62
Code: e8 6b e7 52 fd 43 80 3c 2c 00 74 08 4c 89 ff e8 3c 8a 74 fd 49 8b 17 48 c7 c7 a0 be 28 8c 48 89 de 4c 89 f9 e8 e7 26 6b fc 90 <0f> 0b 4c 89 f7 e8 3c e7 52 fd 43 80 3c 2c 00 74 08 4c 89 ff e8 0d
RSP: 0018:ffffc9000202f800 EFLAGS: 00010246
RAX: 000000000000006d RBX: ffff8880682f5578 RCX: 5386ffdc73148000
RDX: 0000000000000000 RSI: 0000000000000201 RDI: 0000000000000000
RBP: dffffc0000000000 R08: 0000000000000003 R09: 0000000000000004
R10: dffffc0000000000 R11: fffffbfff1cfd240 R12: 1ffff110053554af
R13: dffffc0000000000 R14: ffff888029aaa578 R15: ffff888029aaa578
FS:  0000000000000000(0000) GS:ffff8881253a0000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007f1552dd9062 CR3: 000000001f339000 CR4: 0000000000350ef0
Call Trace:
 <TASK>
 __list_del_entry_valid include/linux/list.h:132 [inline]
 __list_del_entry include/linux/list.h:246 [inline]
 list_del_init include/linux/list.h:318 [inline]
 bt_accept_unlink+0x74/0x2c0 net/bluetooth/af_bluetooth.c:266
 l2cap_sock_teardown_cb+0x17e/0x490 net/bluetooth/l2cap_sock.c:1682
 l2cap_chan_del+0xb5/0x610 net/bluetooth/l2cap_core.c:658
 l2cap_conn_del+0x33d/0x570 net/bluetooth/l2cap_core.c:1804
 hci_disconn_cfm include/net/bluetooth/hci_core.h:2154 [inline]
 hci_conn_hash_flush+0x10d/0x260 net/bluetooth/hci_conn.c:2736
 hci_dev_close_sync+0x85d/0x1150 net/bluetooth/hci_sync.c:5383
 hci_dev_do_close net/bluetooth/hci_core.c:502 [inline]
 hci_error_reset+0x127/0x4c0 net/bluetooth/hci_core.c:998
 process_one_work kernel/workqueue.c:3314 [inline]
 process_scheduled_works+0xb5d/0x1860 kernel/workqueue.c:3397
 worker_thread+0xa53/0xfc0 kernel/workqueue.c:3478
 kthread+0x389/0x470 kernel/kthread.c:436
 ret_from_fork+0x514/0xb70 arch/x86/kernel/process.c:158
 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
 </TASK>
Modules linked in:
---[ end trace 0000000000000000 ]---
RIP: 0010:__list_del_entry_valid_or_report+0x15a/0x190 lib/list_debug.c:62
Code: e8 6b e7 52 fd 43 80 3c 2c 00 74 08 4c 89 ff e8 3c 8a 74 fd 49 8b 17 48 c7 c7 a0 be 28 8c 48 89 de 4c 89 f9 e8 e7 26 6b fc 90 <0f> 0b 4c 89 f7 e8 3c e7 52 fd 43 80 3c 2c 00 74 08 4c 89 ff e8 0d
RSP: 0018:ffffc9000202f800 EFLAGS: 00010246
RAX: 000000000000006d RBX: ffff8880682f5578 RCX: 5386ffdc73148000
RDX: 0000000000000000 RSI: 0000000000000201 RDI: 0000000000000000
RBP: dffffc0000000000 R08: 0000000000000003 R09: 0000000000000004
R10: dffffc0000000000 R11: fffffbfff1cfd240 R12: 1ffff110053554af
R13: dffffc0000000000 R14: ffff888029aaa578 R15: ffff888029aaa578
FS:  0000000000000000(0000) GS:ffff8881253a0000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007f1552dd9062 CR3: 000000001f339000 CR4: 0000000000350ef0


---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller@googlegroups.com.

syzbot will keep track of this issue. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.

If the report is already addressed, let syzbot know by replying with:
#syz fix: exact-commit-title

If you want to overwrite report's subsystems, reply with:
#syz set subsystems: new-subsystem
(See the list of subsystem names on the web dashboard)

If the report is a duplicate of another one, reply with:
#syz dup: exact-subject-of-another-report

If you want to undo deduplication, reply with:
#syz undup

^ permalink raw reply

* [Bug 73081] Fail to setup Bluetooth on Dell Venue 11 Pro
From: bugzilla-daemon @ 2026-06-13  7:16 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <bug-73081-62941@https.bugzilla.kernel.org/>

https://bugzilla.kernel.org/show_bug.cgi?id=73081

--- Comment #10 from Dmitry Khromov (icechrome@gmail.com) ---
My apologies for misleading, that was a hunch from back then.

From your dmesg log I notice the kernel fails to find the WiFi/Bluetooth chip
firmware. You should grab it from

https://github.com/qca/ath6kl-firmware/tree/master/ath6k/AR6004/hw3.0

which is where I got it the last time and put into
`/lib/firmware/ath6k/AR6004/hw3.0` if you haven't done so already.

-- 
You may reply to this email to add a comment.

You are receiving this mail because:
You are the assignee for the bug.

^ permalink raw reply

* [Bug 73081] Fail to setup Bluetooth on Dell Venue 11 Pro
From: bugzilla-daemon @ 2026-06-13  6:57 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <bug-73081-62941@https.bugzilla.kernel.org/>

https://bugzilla.kernel.org/show_bug.cgi?id=73081

--- Comment #9 from Hytham (hytham@gmail.com) ---
Hi Paul,

Yes, I confirmed that the kernel I already have in /boot has
CONFIG_SERIAL_DEV_BUG=y.

Thanks,
Hytham

-- 
You may reply to this email to add a comment.

You are receiving this mail because:
You are the assignee for the bug.

^ permalink raw reply

* [Bug 73081] Fail to setup Bluetooth on Dell Venue 11 Pro
From: bugzilla-daemon @ 2026-06-13  6:32 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <bug-73081-62941@https.bugzilla.kernel.org/>

https://bugzilla.kernel.org/show_bug.cgi?id=73081

--- Comment #8 from Paul Menzel (pmenzel+bugzilla.kernel.org@molgen.mpg.de) ---
At least Debian’s Linux kernel (6.1 and 7.1 from suite *experimental*) have it
set to `CONFIG_SERIAL_DEV_BUS=y`. @Hytham, please check your Ubuntu Linux
kernel config in `/boot/`, for example with `grep CONFIG_SERIAL_DEV_BUS
/boot/config*`.

-- 
You may reply to this email to add a comment.

You are receiving this mail because:
You are the assignee for the bug.

^ permalink raw reply

* [Bug 73081] Fail to setup Bluetooth on Dell Venue 11 Pro
From: bugzilla-daemon @ 2026-06-13  3:24 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <bug-73081-62941@https.bugzilla.kernel.org/>

https://bugzilla.kernel.org/show_bug.cgi?id=73081

--- Comment #7 from Dmitry Khromov (icechrome@gmail.com) ---
If memory serves, the MMIO-mapped UART requires
CONFIG_SERIAL_DEV_CTRL_TTYPORT=y for a port to be picked up by BlueZ. This, in
turn, requires CONFIG_SERIAL_DEV_BUS=y, but most desktop distros ship a kernel
with CONFIG_SERIAL_DEV_BUS=m.

Long story short, I was successful in bringing Bluetooth up and running on
Venue 8 Pro back in the day, so try compiling a kernel with the configuration
flags mentioned. No further action should be required -- BlueZ should
automatically pick the port up and attach the HCI.

-- 
You may reply to this email to add a comment.

You are receiving this mail because:
You are the assignee for the bug.

^ permalink raw reply

* [bluetooth-next:master] BUILD SUCCESS f70f7f2512c6b9113dc78f6a25361166afd1412e
From: kernel test robot @ 2026-06-13  1:07 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth

tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git master
branch HEAD: f70f7f2512c6b9113dc78f6a25361166afd1412e  Bluetooth: btintel_pcie: Separate coredump work from RX work

elapsed time: 1399m

configs tested: 321
configs skipped: 13

The following configs have been built successfully.
More configs may be tested in the coming days.

tested configs:
alpha                             allnoconfig    gcc-16.1.0
alpha                            allyesconfig    gcc-16.1.0
alpha                               defconfig    gcc-16.1.0
arc                              allmodconfig    clang-23
arc                               allnoconfig    gcc-16.1.0
arc                              allyesconfig    clang-23
arc                              allyesconfig    gcc-16.1.0
arc                                 defconfig    gcc-16.1.0
arc                        nsim_700_defconfig    gcc-16.1.0
arc                   randconfig-001-20260612    gcc-13.4.0
arc                   randconfig-001-20260613    gcc-12.5.0
arc                   randconfig-002-20260612    gcc-13.4.0
arc                   randconfig-002-20260613    gcc-12.5.0
arm                               allnoconfig    gcc-16.1.0
arm                              allyesconfig    clang-23
arm                         axm55xx_defconfig    clang-23
arm                                 defconfig    gcc-16.1.0
arm                   randconfig-001-20260612    gcc-13.4.0
arm                   randconfig-001-20260613    gcc-12.5.0
arm                   randconfig-002-20260612    gcc-13.4.0
arm                   randconfig-002-20260613    gcc-12.5.0
arm                   randconfig-003-20260612    gcc-13.4.0
arm                   randconfig-003-20260613    gcc-12.5.0
arm                   randconfig-004-20260612    gcc-13.4.0
arm                   randconfig-004-20260613    gcc-12.5.0
arm                       spear13xx_defconfig    gcc-16.1.0
arm64                            allmodconfig    clang-23
arm64                             allnoconfig    gcc-16.1.0
arm64                               defconfig    gcc-16.1.0
arm64                          randconfig-001    gcc-13.4.0
arm64                 randconfig-001-20260612    gcc-13.4.0
arm64                 randconfig-001-20260613    gcc-16.1.0
arm64                          randconfig-002    gcc-13.4.0
arm64                 randconfig-002-20260612    gcc-13.4.0
arm64                 randconfig-002-20260613    gcc-16.1.0
arm64                          randconfig-003    gcc-13.4.0
arm64                 randconfig-003-20260612    gcc-13.4.0
arm64                 randconfig-003-20260613    gcc-16.1.0
arm64                          randconfig-004    gcc-13.4.0
arm64                 randconfig-004-20260612    gcc-13.4.0
arm64                 randconfig-004-20260613    gcc-16.1.0
csky                             allmodconfig    gcc-16.1.0
csky                              allnoconfig    gcc-16.1.0
csky                                defconfig    gcc-16.1.0
csky                           randconfig-001    gcc-13.4.0
csky                  randconfig-001-20260612    gcc-13.4.0
csky                  randconfig-001-20260613    gcc-16.1.0
csky                           randconfig-002    gcc-13.4.0
csky                  randconfig-002-20260612    gcc-13.4.0
csky                  randconfig-002-20260613    gcc-16.1.0
hexagon                          allmodconfig    clang-23
hexagon                          allmodconfig    gcc-16.1.0
hexagon                           allnoconfig    gcc-16.1.0
hexagon                             defconfig    gcc-16.1.0
hexagon                        randconfig-001    gcc-11.5.0
hexagon               randconfig-001-20260612    clang-23
hexagon               randconfig-001-20260612    gcc-11.5.0
hexagon               randconfig-001-20260613    clang-23
hexagon                        randconfig-002    gcc-11.5.0
hexagon               randconfig-002-20260612    clang-23
hexagon               randconfig-002-20260612    gcc-11.5.0
hexagon               randconfig-002-20260613    clang-23
i386                             allmodconfig    clang-22
i386                             allmodconfig    gcc-14
i386                              allnoconfig    gcc-16.1.0
i386                             allyesconfig    clang-22
i386                             allyesconfig    gcc-14
i386                 buildonly-randconfig-001    gcc-14
i386        buildonly-randconfig-001-20260612    gcc-14
i386        buildonly-randconfig-001-20260613    gcc-14
i386                 buildonly-randconfig-002    gcc-14
i386        buildonly-randconfig-002-20260612    gcc-14
i386        buildonly-randconfig-002-20260613    gcc-14
i386                 buildonly-randconfig-003    gcc-14
i386        buildonly-randconfig-003-20260612    gcc-14
i386        buildonly-randconfig-003-20260613    gcc-14
i386                 buildonly-randconfig-004    gcc-14
i386        buildonly-randconfig-004-20260612    gcc-14
i386        buildonly-randconfig-004-20260613    gcc-14
i386                 buildonly-randconfig-005    gcc-14
i386        buildonly-randconfig-005-20260612    gcc-14
i386        buildonly-randconfig-005-20260613    gcc-14
i386                 buildonly-randconfig-006    gcc-14
i386        buildonly-randconfig-006-20260612    gcc-14
i386        buildonly-randconfig-006-20260613    gcc-14
i386                                defconfig    gcc-16.1.0
i386                  randconfig-001-20260612    clang-22
i386                  randconfig-001-20260613    clang-22
i386                  randconfig-002-20260612    clang-22
i386                  randconfig-002-20260613    clang-22
i386                  randconfig-003-20260612    clang-22
i386                  randconfig-003-20260613    clang-22
i386                  randconfig-004-20260612    clang-22
i386                  randconfig-004-20260613    clang-22
i386                  randconfig-005-20260612    clang-22
i386                  randconfig-005-20260613    clang-22
i386                  randconfig-006-20260612    clang-22
i386                  randconfig-006-20260613    clang-22
i386                  randconfig-007-20260612    clang-22
i386                  randconfig-007-20260613    clang-22
i386                           randconfig-011    clang-22
i386                  randconfig-011-20260612    clang-22
i386                  randconfig-011-20260613    gcc-14
i386                           randconfig-012    clang-22
i386                  randconfig-012-20260612    clang-22
i386                  randconfig-012-20260613    gcc-14
i386                           randconfig-013    clang-22
i386                  randconfig-013-20260612    clang-22
i386                  randconfig-013-20260613    gcc-14
i386                           randconfig-014    clang-22
i386                  randconfig-014-20260612    clang-22
i386                  randconfig-014-20260613    gcc-14
i386                           randconfig-015    clang-22
i386                  randconfig-015-20260612    clang-22
i386                  randconfig-015-20260613    gcc-14
i386                           randconfig-016    clang-22
i386                  randconfig-016-20260612    clang-22
i386                  randconfig-016-20260613    gcc-14
i386                           randconfig-017    clang-22
i386                  randconfig-017-20260612    clang-22
i386                  randconfig-017-20260613    gcc-14
loongarch                        allmodconfig    clang-19
loongarch                        allmodconfig    clang-23
loongarch                         allnoconfig    gcc-16.1.0
loongarch                           defconfig    clang-23
loongarch                      randconfig-001    gcc-11.5.0
loongarch             randconfig-001-20260612    clang-23
loongarch             randconfig-001-20260612    gcc-11.5.0
loongarch             randconfig-001-20260613    clang-23
loongarch                      randconfig-002    gcc-11.5.0
loongarch             randconfig-002-20260612    clang-23
loongarch             randconfig-002-20260612    gcc-11.5.0
loongarch             randconfig-002-20260613    clang-23
m68k                             allmodconfig    gcc-16.1.0
m68k                              allnoconfig    gcc-16.1.0
m68k                             allyesconfig    clang-23
m68k                          atari_defconfig    gcc-16.1.0
m68k                                defconfig    clang-23
microblaze                        allnoconfig    gcc-16.1.0
microblaze                       allyesconfig    gcc-16.1.0
microblaze                          defconfig    clang-23
mips                             allmodconfig    gcc-16.1.0
mips                              allnoconfig    gcc-16.1.0
mips                             allyesconfig    gcc-16.1.0
nios2                            allmodconfig    clang-20
nios2                            allmodconfig    gcc-11.5.0
nios2                             allnoconfig    clang-23
nios2                               defconfig    clang-23
nios2                          randconfig-001    gcc-11.5.0
nios2                 randconfig-001-20260612    clang-23
nios2                 randconfig-001-20260612    gcc-11.5.0
nios2                 randconfig-001-20260613    clang-23
nios2                          randconfig-002    gcc-11.5.0
nios2                 randconfig-002-20260612    clang-23
nios2                 randconfig-002-20260612    gcc-11.5.0
nios2                 randconfig-002-20260613    clang-23
openrisc                         allmodconfig    clang-20
openrisc                         allmodconfig    gcc-16.1.0
openrisc                          allnoconfig    clang-23
openrisc                            defconfig    gcc-16.1.0
parisc                           allmodconfig    gcc-16.1.0
parisc                            allnoconfig    clang-23
parisc                           allyesconfig    clang-23
parisc                           allyesconfig    gcc-16.1.0
parisc                              defconfig    gcc-16.1.0
parisc                randconfig-001-20260612    gcc-14.3.0
parisc                randconfig-001-20260613    gcc-15.2.0
parisc                randconfig-002-20260612    gcc-14.3.0
parisc                randconfig-002-20260613    gcc-15.2.0
parisc64                            defconfig    clang-23
powerpc                          allmodconfig    gcc-16.1.0
powerpc                           allnoconfig    clang-23
powerpc                  mpc885_ads_defconfig    clang-23
powerpc                      ppc64e_defconfig    gcc-16.1.0
powerpc               randconfig-001-20260613    gcc-15.2.0
powerpc               randconfig-002-20260613    gcc-15.2.0
powerpc64             randconfig-001-20260612    gcc-14.3.0
powerpc64             randconfig-001-20260613    gcc-15.2.0
powerpc64             randconfig-002-20260612    gcc-14.3.0
powerpc64             randconfig-002-20260613    gcc-15.2.0
riscv                            allmodconfig    clang-23
riscv                             allnoconfig    clang-23
riscv                            allyesconfig    clang-23
riscv                               defconfig    gcc-16.1.0
riscv                          randconfig-001    gcc-11.5.0
riscv                 randconfig-001-20260612    gcc-11.5.0
riscv                 randconfig-001-20260613    gcc-10.5.0
riscv                          randconfig-002    gcc-11.5.0
riscv                 randconfig-002-20260612    gcc-11.5.0
riscv                 randconfig-002-20260613    gcc-10.5.0
s390                             allmodconfig    clang-23
s390                              allnoconfig    clang-23
s390                             allyesconfig    gcc-16.1.0
s390                                defconfig    gcc-16.1.0
s390                           randconfig-001    gcc-11.5.0
s390                  randconfig-001-20260612    gcc-11.5.0
s390                  randconfig-001-20260613    gcc-10.5.0
s390                           randconfig-002    gcc-11.5.0
s390                  randconfig-002-20260612    gcc-11.5.0
s390                  randconfig-002-20260613    gcc-10.5.0
sh                               allmodconfig    gcc-16.1.0
sh                                allnoconfig    clang-23
sh                               allyesconfig    clang-23
sh                               allyesconfig    gcc-16.1.0
sh                                  defconfig    gcc-14
sh                             randconfig-001    gcc-11.5.0
sh                    randconfig-001-20260612    gcc-11.5.0
sh                    randconfig-001-20260613    gcc-10.5.0
sh                             randconfig-002    gcc-11.5.0
sh                    randconfig-002-20260612    gcc-11.5.0
sh                    randconfig-002-20260613    gcc-10.5.0
sparc                             allnoconfig    clang-23
sparc                               defconfig    gcc-16.1.0
sparc                          randconfig-001    gcc-8.5.0
sparc                 randconfig-001-20260612    gcc-8.5.0
sparc                 randconfig-001-20260613    gcc-13.4.0
sparc                          randconfig-002    gcc-8.5.0
sparc                 randconfig-002-20260612    gcc-8.5.0
sparc                 randconfig-002-20260613    gcc-13.4.0
sparc                       sparc64_defconfig    gcc-16.1.0
sparc64                          allmodconfig    clang-20
sparc64                             defconfig    gcc-14
sparc64                        randconfig-001    gcc-8.5.0
sparc64               randconfig-001-20260612    gcc-8.5.0
sparc64               randconfig-001-20260613    gcc-13.4.0
sparc64                        randconfig-002    gcc-8.5.0
sparc64               randconfig-002-20260612    gcc-8.5.0
sparc64               randconfig-002-20260613    gcc-13.4.0
um                               allmodconfig    clang-23
um                                allnoconfig    clang-23
um                               allyesconfig    gcc-14
um                               allyesconfig    gcc-16.1.0
um                                  defconfig    gcc-14
um                             i386_defconfig    gcc-14
um                             randconfig-001    gcc-8.5.0
um                    randconfig-001-20260612    gcc-8.5.0
um                    randconfig-001-20260613    gcc-13.4.0
um                             randconfig-002    gcc-8.5.0
um                    randconfig-002-20260612    gcc-8.5.0
um                    randconfig-002-20260613    gcc-13.4.0
um                           x86_64_defconfig    gcc-14
x86_64                           allmodconfig    clang-22
x86_64                            allnoconfig    clang-23
x86_64                           allyesconfig    clang-22
x86_64               buildonly-randconfig-001    gcc-14
x86_64      buildonly-randconfig-001-20260612    gcc-14
x86_64      buildonly-randconfig-001-20260613    clang-22
x86_64               buildonly-randconfig-002    gcc-14
x86_64      buildonly-randconfig-002-20260612    gcc-14
x86_64      buildonly-randconfig-002-20260613    clang-22
x86_64               buildonly-randconfig-003    gcc-14
x86_64      buildonly-randconfig-003-20260612    gcc-14
x86_64      buildonly-randconfig-003-20260613    clang-22
x86_64               buildonly-randconfig-004    gcc-14
x86_64      buildonly-randconfig-004-20260612    gcc-14
x86_64      buildonly-randconfig-004-20260613    clang-22
x86_64               buildonly-randconfig-005    gcc-14
x86_64      buildonly-randconfig-005-20260612    gcc-14
x86_64      buildonly-randconfig-005-20260613    clang-22
x86_64               buildonly-randconfig-006    gcc-14
x86_64      buildonly-randconfig-006-20260612    gcc-14
x86_64      buildonly-randconfig-006-20260613    clang-22
x86_64                              defconfig    gcc-14
x86_64                                  kexec    clang-22
x86_64                randconfig-001-20260612    clang-22
x86_64                randconfig-001-20260613    clang-22
x86_64                randconfig-002-20260612    clang-22
x86_64                randconfig-002-20260613    clang-22
x86_64                randconfig-003-20260612    clang-22
x86_64                randconfig-003-20260613    clang-22
x86_64                randconfig-004-20260612    clang-22
x86_64                randconfig-004-20260613    clang-22
x86_64                randconfig-005-20260612    clang-22
x86_64                randconfig-005-20260613    clang-22
x86_64                randconfig-006-20260612    clang-22
x86_64                randconfig-006-20260613    clang-22
x86_64                         randconfig-011    clang-22
x86_64                randconfig-011-20260612    clang-22
x86_64                randconfig-011-20260613    clang-22
x86_64                         randconfig-012    clang-22
x86_64                randconfig-012-20260612    clang-22
x86_64                randconfig-012-20260613    clang-22
x86_64                         randconfig-013    clang-22
x86_64                randconfig-013-20260612    clang-22
x86_64                randconfig-013-20260613    clang-22
x86_64                         randconfig-014    clang-22
x86_64                randconfig-014-20260612    clang-22
x86_64                randconfig-014-20260613    clang-22
x86_64                         randconfig-015    clang-22
x86_64                randconfig-015-20260612    clang-22
x86_64                randconfig-015-20260613    clang-22
x86_64                         randconfig-016    clang-22
x86_64                randconfig-016-20260612    clang-22
x86_64                randconfig-016-20260613    clang-22
x86_64                randconfig-071-20260612    gcc-14
x86_64                randconfig-071-20260613    clang-22
x86_64                randconfig-072-20260612    gcc-14
x86_64                randconfig-072-20260613    clang-22
x86_64                randconfig-073-20260612    gcc-14
x86_64                randconfig-073-20260613    clang-22
x86_64                randconfig-074-20260612    gcc-14
x86_64                randconfig-074-20260613    clang-22
x86_64                randconfig-075-20260612    gcc-14
x86_64                randconfig-075-20260613    clang-22
x86_64                randconfig-076-20260612    gcc-14
x86_64                randconfig-076-20260613    clang-22
x86_64                               rhel-9.4    clang-22
x86_64                           rhel-9.4-bpf    gcc-14
x86_64                          rhel-9.4-func    clang-22
x86_64                    rhel-9.4-kselftests    clang-22
x86_64                         rhel-9.4-kunit    gcc-14
x86_64                           rhel-9.4-ltp    gcc-14
x86_64                          rhel-9.4-rust    clang-22
xtensa                            allnoconfig    clang-23
xtensa                           allyesconfig    clang-20
xtensa                         randconfig-001    gcc-8.5.0
xtensa                randconfig-001-20260612    gcc-8.5.0
xtensa                randconfig-001-20260613    gcc-13.4.0
xtensa                         randconfig-002    gcc-8.5.0
xtensa                randconfig-002-20260612    gcc-8.5.0
xtensa                randconfig-002-20260613    gcc-13.4.0

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply

* [Bug 73081] Fail to setup Bluetooth on Dell Venue 11 Pro
From: bugzilla-daemon @ 2026-06-12 21:34 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <bug-73081-62941@https.bugzilla.kernel.org/>

https://bugzilla.kernel.org/show_bug.cgi?id=73081

--- Comment #6 from Hytham (hytham@gmail.com) ---
Thanks Paul, please find my dmesg.log and new issue here:

https://github.com/bluez/bluez/issues/2222

-- 
You may reply to this email to add a comment.

You are receiving this mail because:
You are the assignee for the bug.

^ permalink raw reply

* Re: [PATCH BlueZ v5 00/16] Functional/integration testing
From: Luiz Augusto von Dentz @ 2026-06-12 20:13 UTC (permalink / raw)
  To: Pauli Virtanen; +Cc: linux-bluetooth
In-Reply-To: <cover.1778688966.git.pav@iki.fi>

Hi Pauli,

On Wed, May 13, 2026 at 1:35 PM Pauli Virtanen <pav@iki.fi> wrote:
>
> Add framework for writing tests simulating "real" environments where
> BlueZ and other parts of the stack run on different virtual machine
> hosts that communicate with each other.
>
> *** v5 ***
>
> https://github.com/pv/bluez/compare/func-test-v4-r..func-test-v5
>
> * Factor out the pytest-bluezenv plugin, to be maintained separately.
>   https://pypi.org/project/pytest-bluezenv/
>
>   It could in principle be moved under the BlueZ organization, but
>   there's no particular reason why it should be in bluez repository.
>
>   Generally, it's better to have the pytest plugin separate so it's
>   easier to reuse and can have its own version cycle.
>
> * Pipewire tests are moved to pipewire repository where they probably
>   belong to.
>
>   They can be run easily vs. given BlueZ build dir.
>
>   We are currently running them in Pipewire CI, but at frozen
>   kernel/BlueZ version, so it is not testing BlueZ/kernel upstream
>   development.
>
> * No changes in the emulator/test-runner patches since v4
>
>   They are stand-alone bug fixes / improvements, and make sense
>   also separately from the rest.
>
> *** v4 ***
>
> https://github.com/pv/bluez/compare/func-test-v3-r..func-test-v4
>
> * Use virtconsole for simpler HCI forwarding to the vm
>
> * Fix typoed vm_module -> vm_once
>
> * Skip tests for some pipewire versions
>
> *** v3 ***
>
> https://github.com/pv/bluez/compare/func-test-v2-r..func-test-v3
>
> * fix configure.ac openpty() detection to match TOOLS conditional,
>   to fix make distcheck
>
> * properly retry virtio RPC connection if it fails initially
>
> * properly restart VM if previous test hangs
>
> * allow custom parent host side proxy objects, use them for pexpect
>
> * improve --list with out-of-tree test files
>
> * fix missing bus.set_exit_on_disconnect(False) for obex tests
>
> * have --vm-timeout etc. change values also on VM host side
>
> * use larger-memory VM instances for Pipewire, in case ASAN enabled
>
> * set reasonable inside-VM ASAN_OPTION default values
>
> * don't run btvirt under stdbuf, since not compatible with ASAN
>
> *** v2 ***
>
> https://github.com/pv/bluez/compare/func-test-v1-r..func-test-v2
>
> * move unit/func_test -> test/functional & test/pytest_bluez
>
>   The pytest_bluez plugin is in principle reusable for other projects,
>   so we can eg. have more complete Pipewire integration tests that can
>   live in Pipewire repository.
>
> * openpty() is in -lutil on some platforms, detect this in autoconf
>
> * more emulator adjustments:
>
>   - fix SCO data packet support in btvirt
>   - more complete Reset command
>
> * improve logging: get timestamps from kernel, and reorder logs
>   to timestamp order, so that lines from different hosts, btmon,
>   and parent tester appear in right order regardless of whether
>   VM console / btmon is lagging
>
>   - this requires accurate clock sync in the VM, so enable KVM PTP in
>     config and run chronyd inside the VMs
>   - use virtio port instead of qemu console to export logs, since the
>     console has fixed baud rate and is too slow
>
> * add --btmon & export btsnoop dumps from VM hosts
>
> * fix compatibility with older Python versions
>
> * add parametrized_host_config()
>
> * split Pipewire test to A2DP/BAP/HFP and really stream audio.
>   These catch the 5.86 regression fixed in 066a164a524e498 and
>   the 5.84 one in 6b0a08776a
>
> * add support for tests that reuse tester environment, so they can run
>   faster without needing Bluetoothd teardown/setup in between
>
> * add HostPlugin.presetup (mainly for test skipping)
>
> * deal with RPC virtio port buffer possibly containing unflushed
>   commands from previous failed test
>
> * add some Agent1 interface tests
>
> * add basic Obex file transfer tests
>
> * add support for logging in to a running test instance (for gdb etc)
>
> * export any core dumps out from test environ
>
> Some bells & whistles:
>
> * add --kernel-build for kernel image build
>
> * test suite Python code formatting checks
>
> ***
>
> Implements:
>
> - RPC communication with tester instances running each of the VM hosts.
>   Tests run on parent host, which instructs VM hosts what to do.
>
> - Extensible way to add stateful test-specific code inside the VM
>   instances
>
> - Logging control: output from different processes running inside the VM
>   are separated and can be filtered.
>
> - Test runner framework with Pytest (more convenient than Python/unittest)
>
> - Automatic grouping of tests to minimize VM reboots
>
> - Redirecting USB controllers to use for testing in addition to btvirt
>
> - Fairly straightforward, ~1600 sloc for the framework
>
> There is no requirement that the tests spawn VM instances, the test
> runner can be used for any tests written in Python.
>
> See doc/test-functional.rst for various examples.
>
> Also test/functional/test_bluetoothctl_vm.py has some simple cases, and
> test/functional/test_pipewire.py for a more complicated setup
>
>     host0(qemu): Pipewire <-> BlueZ <-> kernel
>     <-> btvirt
>     host1(qemu): kernel <-> BlueZ <-> Pipewire
>
> The framework allows easily passing any data and code between the parent
> and VM hosts, so writing tests is straightforward.
>
> ***
>
> Some examples:
>
> $ test/test-functional --list -q
>
> test/functional/lib/tests/test_rpc.py::test_basic
> test/functional/test_bluetoothctl_vm.py::test_bluetoothctl_pair[hosts0-vm2]
> test/functional/test_bluetoothctl_vm.py::test_bluetoothctl_script_show[hosts1-vm1]
> test/functional/test_btmgmt_vm.py::test_btmgmt_info[hosts2-vm1]
> test/functional/test_pipewire.py::test_pipewire[hosts3-vm2]
>
> $ test/test-functional -v --no-header
> ======================================= test session starts ========================================
> collected 5 items
>
> test/functional/lib/tests/test_rpc.py::test_basic PASSED                                      [ 20%]
> test/functional/test_bluetoothctl_vm.py::test_bluetoothctl_script_show[hosts1-vm1] SKIPPED    [ 40%]
> test/functional/test_btmgmt_vm.py::test_btmgmt_info[hosts2-vm1] SKIPPED (No kernel image)     [ 60%]
> test/functional/test_bluetoothctl_vm.py::test_bluetoothctl_pair[hosts0-vm2] SKIPPED (No k...) [ 80%]
> test/functional/test_pipewire.py::test_pipewire[hosts3-vm2] SKIPPED (No kernel image)         [100%]
>
> =================================== 1 passed, 4 skipped in 0.19s ===================================
>
> $ test/test-functional --kernel=../linux
> ============================= test session starts ==============================
> platform linux -- Python 3.14.3, pytest-8.3.5, pluggy-1.6.0
> rootdir: /home/pauli/prj/external/bluez/unit
> configfile: pytest.ini
> plugins: cov-5.0.0, forked-1.6.0, rerunfailures-15.0, timeout-2.4.0, xdist-3.7.0, hypothesis-6.123.0, flaky-3.8.1, anyio-4.12.1
> collected 5 items
>
> test/functional/lib/tests/test_rpc.py .                                   [ 20%]
> test/functional/test_bluetoothctl_vm.py .                                 [ 40%]
> test/functional/test_btmgmt_vm.py .                                       [ 60%]
> test/functional/test_bluetoothctl_vm.py .                                 [ 80%]
> test/functional/test_pipewire.py .                                        [100%]
>
> ============================== 5 passed in 41.92s ==============================
>
> $ test/test-functional --kernel=../linux -k test_btmgmt
> ============================= test session starts ==============================
> platform linux -- Python 3.14.3, pytest-8.3.5, pluggy-1.6.0
> rootdir: /home/pauli/prj/external/bluez/unit
> configfile: pytest.ini
> plugins: cov-5.0.0, forked-1.6.0, rerunfailures-15.0, timeout-2.4.0, xdist-3.7.0, hypothesis-6.123.0, flaky-3.8.1, anyio-4.12.1
> collected 5 items / 4 deselected / 1 selected
>
> test/functional/test_btmgmt_vm.py .                                       [100%]
>
> ======================= 1 passed, 4 deselected in 9.15s ========================
>
> $ grep btmgmt test-functional.log
> 13:15:42 INFO   rpc.host.0.0        :  client: call_plugin ('call', '__call__', <function run at 0x7f27b81ce140>, ['/home/pauli/prj/external/bluez/build/tools/btmgmt', '--index', '0', 'info']) {'stdout': -1, 'stdin': -3, 'encoding': 'utf-8'}
> 13:15:42 INFO   host.0.0.rpc        :  server: call_plugin ('call', '__call__', <function run at 0x7fd5e35a1010>, ['/home/pauli/prj/external/bluez/build/tools/btmgmt', '--index', '0', 'info']) {'stdout': -1, 'stdin': -3, 'encoding': 'utf-8'}
> 13:15:42 INFO   host.0.0.run        :      $ /home/pauli/prj/external/bluez/build/tools/btmgmt --index 0 info
>
> $ test/test-functional --kernel=../linux -k test_btmgmt --log-cli-level=0
> ============================= test session starts ==============================
> platform linux -- Python 3.14.3, pytest-8.3.5, pluggy-1.6.0
> rootdir: /home/pauli/prj/external/bluez/unit
> configfile: pytest.ini
> plugins: cov-5.0.0, forked-1.6.0, rerunfailures-15.0, timeout-2.4.0, xdist-3.7.0, hypothesis-6.123.0, flaky-3.8.1, anyio-4.12.1
> collected 5 items / 4 deselected / 1 selected
>
> test/functional/test_btmgmt_vm.py::test_btmgmt_info[hosts2-vm1]
> -------------------------------- live log setup --------------------------------
> 13:00:31 INFO   func_test.lib.env   :  Starting btvirt: /usr/bin/stdbuf -o L -e L /home/pauli/prj/external/bluez/build/emulator/btvirt --server=/tmp/bluez-func-test-8t6ychy8
> 13:00:31 OUT    btvirt              :  Bluetooth emulator ver 5.86
> 13:00:31 INFO   func_test.lib.env   :  Starting host: /home/pauli/prj/external/bluez/build/tools/test-runner --kernel=../linux/arch/x86/boot/bzImage -u/tmp/bluez-func-test-8t6ychy8/bt-server-bredrle -o -chardev -o socket,id=ser0,path=/tmp/bluez-func-test-8t6ychy8/bluez-func-test-rpc-0,server=on,wait=off -o -device -o virtio-serial -o -device -o virtserialport,chardev=ser0,name=bluez-func-test-rpc -H -- /usr/bin/python3 -P /home/pauli/prj/external/bluez/test/functional/lib/runner.py /dev/ttyS2
> 13:00:31 OUT    btvirt              :  Request for /tmp/bluez-func-test-8t6ychy8/bt-server-bredrle
> 13:00:32 OUT    host.0.0            :  early console in extract_kernel
> 13:00:32 OUT    host.0.0            :  input_data: 0x000000000425c2c4
> ...
> 13:00:39 INFO   rpc.host.0.0        :  client: call_plugin ('call', '__call__', <function run at 0x7f7547472140>, ['/home/pauli/prj/external/bluez/build/tools/btmgmt', '--index', '0', 'info']) {'stdout': -1, 'stdin': -3, 'encoding': 'utf-8'}
> 13:00:39 DEBUG  host.0.0.rpc        :  server: done
> 13:00:39 INFO   host.0.0.rpc        :  server: call_plugin ('call', '__call__', <function run at 0x7f77dcc81010>, ['/home/pauli/prj/external/bluez/build/tools/btmgmt', '--index', '0', 'info']) {'stdout': -1, 'stdin': -3, 'encoding': 'utf-8'}
> 13:00:39 INFO   host.0.0.run        :      $ /home/pauli/prj/external/bluez/build/tools/btmgmt --index 0 info
> 13:00:40 OUT    host.0.0.run.out    :  hci0:    Primary controller
> 13:00:40 OUT    host.0.0.run.out    :   addr 00:AA:01:00:00:42 version 11 manufacturer 1521 class 0x000000
> 13:00:40 OUT    host.0.0.run.out    :   supported settings: powered connectable fast-connectable discoverable bondable link-security ssp br/edr le advertising secure-conn debug-keys privacy static-addr phy-configuration cis-central cis-peripheral iso-broadcaster sync-receiver ll-privacy past-sender past-receiver
> 13:00:40 OUT    host.0.0.run.out    :   current settings: br/edr
> 13:00:40 OUT    host.0.0.run.out    :   name
> 13:00:40 OUT    host.0.0.run.out    :   short name
> 13:00:40 INFO   host.0.0.run        :  (return code 0)
> 13:00:40 DEBUG  rpc.host.0.0        :  client-reply
> PASSED                                                                   [100%]
> 13:00:40 OUT    host.0.0            :  qemu-system-x86_64: terminating on signal 15 from pid 149047 (python3)
> ======================= 1 passed, 4 deselected in 8.84s ========================
>
> $ test/test-functional --kernel=../linux -k test_bluetoothctl_pair --log-cli-level=0 --log-filter=*.bluetoothctl,rpc.* --force-usb
> ============================= test session starts ==============================
> platform linux -- Python 3.14.3, pytest-8.3.5, pluggy-1.6.0
> rootdir: /home/pauli/prj/external/bluez/unit
> configfile: pytest.ini
> plugins: cov-5.0.0, forked-1.6.0, rerunfailures-15.0, timeout-2.4.0, xdist-3.7.0, hypothesis-6.123.0, flaky-3.8.1, anyio-4.12.1
> collected 5 items / 4 deselected / 1 selected
>
> test/functional/test_bluetoothctl_vm.py::test_bluetoothctl_pair[hosts0-vm2]
> -------------------------------- live log setup --------------------------------
> 13:03:20 INFO   rpc.host.0.0        :  client: start_load (<func_test.lib.host_plugins.Bdaddr object at 0x7f268712d160>,) {}
> 13:03:20 INFO   rpc.host.0.0        :  client: start_load (<func_test.lib.host_plugins.Call object at 0x7f268712d2b0>,) {}
> 13:03:20 INFO   rpc.host.0.0        :  client: start_load (<func_test.lib.host_plugins.DbusSystem object at 0x7f2687aa30e0>,) {}
> 13:03:20 INFO   rpc.host.0.0        :  client: start_load (<func_test.lib.host_plugins.Bluetoothd object at 0x7f2687aa3230>,) {}
> 13:03:20 INFO   rpc.host.0.0        :  client: start_load (<func_test.lib.host_plugins.Bluetoothctl object at 0x7f268712d010>,) {}
> 13:03:20 INFO   rpc.host.0.1        :  client: start_load (<func_test.lib.host_plugins.Bdaddr object at 0x7f26871542d0>,) {}
> 13:03:20 INFO   rpc.host.0.1        :  client: start_load (<func_test.lib.host_plugins.Call object at 0x7f2687154410>,) {}
> 13:03:20 INFO   rpc.host.0.1        :  client: start_load (<func_test.lib.host_plugins.DbusSystem object at 0x7f2687aa30e0>,) {}
> 13:03:20 INFO   rpc.host.0.1        :  client: start_load (<func_test.lib.host_plugins.Bluetoothd object at 0x7f2687aa3230>,) {}
> 13:03:20 INFO   rpc.host.0.1        :  client: start_load (<func_test.lib.host_plugins.Bluetoothctl object at 0x7f2687154190>,) {}
> 13:03:20 INFO   rpc.host.0.0        :  client: wait_load () {}
> 13:03:21 DEBUG  rpc.host.0.0        :  client-reply
> 13:03:21 INFO   rpc.host.0.1        :  client: wait_load () {}
> 13:03:21 DEBUG  rpc.host.0.1        :  client-reply
> -------------------------------- live log call ---------------------------------
> 13:03:21 INFO   rpc.host.0.0        :  client: call_plugin ('bluetoothctl', 'send', 'show\n') {}
> 13:03:21 DEBUG  rpc.host.0.0        :  client-reply
> 13:03:21 INFO   rpc.host.0.0        :  client: call_plugin ('bluetoothctl', 'expect', 'Powered: yes') {}
> ...
> 13:03:23 INFO   rpc.host.0.0        :  client: call_plugin ('bluetoothctl', 'send', 'pair 70:1a:b8:73:99:bb\n') {}
> 13:03:23 OUT    host.0.0.bluetoothctl:  pair 70:1a:b8:73:99:bb
> 13:03:23 DEBUG  rpc.host.0.0        :  client-reply
> 13:03:23 INFO   rpc.host.0.0        :  client: call_plugin ('bluetoothctl', 'expect', 'Confirm passkey (\\d+).*:') {}
> 13:03:23 OUT    host.0.0.bluetoothctl:  [bluetoothctl]> pair 70:1a:b8:73:99:bb
> 13:03:23 OUT    host.0.0.bluetoothctl:  Attempting to pair with 70:1A:B8:73:99:BB
> 13:03:23 OUT    host.0.0.bluetoothctl:  [bluetoothctl]> hci0 device_flags_changed: 70:1A:B8:73:99:BB (BR/EDR)
> 13:03:23 OUT    host.0.0.bluetoothctl:  [bluetoothctl]>      supp: 0x00000007  curr: 0x00000000
> 13:03:23 OUT    host.0.0.bluetoothctl:  [bluetoothctl]> hci0 type 7 discovering off
> 13:03:25 OUT    host.0.0.bluetoothctl:  [bluetoothctl]> hci0 70:1A:B8:73:99:BB type BR/EDR connected eir_len 12
> 13:03:25 OUT    host.0.0.bluetoothctl:  [bluetoothctl]> [BlueZ 5.86]> [CHG] Device 70:1A:B8:73:99:BB Connected: yes
> 13:03:25 OUT    host.0.0.bluetoothctl:  [BlueZ 5.86]> Request confirmation
> 13:03:25 DEBUG  rpc.host.0.0        :  client-reply
> 13:03:25 INFO   rpc.host.0.1        :  client: call_plugin ('bluetoothctl', 'expect', 'Confirm passkey 237345') {}
> 13:03:25 OUT    host.0.1.bluetoothctl:  [bluetoothctl]> hci0 84:5C:F3:77:31:19 type BR/EDR connected eir_len 12
> 13:03:25 OUT    host.0.1.bluetoothctl:  [bluetoothctl]> [NEW] Device 84:5C:F3:77:31:19 BlueZ 5.86
> 13:03:25 DEBUG  rpc.host.0.1        :  client-reply
> 13:03:25 INFO   rpc.host.0.0        :  client: call_plugin ('bluetoothctl', 'send', 'yes\n') {}
> 13:03:25 OUT    host.0.1.bluetoothctl:  [bluetoothctl]> [BlueZ 5.86]> Request confirmation
> 13:03:25 OUT    host.0.0.bluetoothctl:  [BlueZ 5.86]> [agent] Confirm passkey 237345 (yes/no): yes
> 13:03:25 DEBUG  rpc.host.0.0        :  client-reply
> 13:03:25 INFO   rpc.host.0.1        :  client: call_plugin ('bluetoothctl', 'send', 'yes\n') {}
> 13:03:25 OUT    host.0.1.bluetoothctl:  [BlueZ 5.86]> [agent] Confirm passkey 237345 (yes/no): yes
> 13:03:25 DEBUG  rpc.host.0.1        :  client-reply
> 13:03:25 INFO   rpc.host.0.0        :  client: call_plugin ('bluetoothctl', 'expect', 'Pairing successful') {}
> 13:03:25 OUT    host.0.0.bluetoothctl:  yes
> 13:03:25 OUT    host.0.0.bluetoothctl:  [BlueZ 5.86]> hci0 new_link_key 70:1A:B8:73:99:BB type 0x08 pin_len 0 store_hint 1
> 13:03:25 OUT    host.0.0.bluetoothctl:  [BlueZ 5.86]> [CHG] Device 70:1A:B8:73:99:BB Bonded: yes
> 13:03:26 OUT    host.0.0.bluetoothctl:  [BlueZ 5.86]> [CHG] Device 70:1A:B8:73:99:BB AddressType: public
> 13:03:26 OUT    host.0.0.bluetoothctl:  [BlueZ 5.86]> [CHG] Device 70:1A:B8:73:99:BB UUIDs: 0000110c-0000-1000-8000-00805f9b34fb
> 13:03:26 OUT    host.0.0.bluetoothctl:  [BlueZ 5.86]> [CHG] Device 70:1A:B8:73:99:BB UUIDs: 0000110e-0000-1000-8000-00805f9b34fb
> 13:03:26 DEBUG  rpc.host.0.0        :  client-reply
> PASSED                                                                   [100%]
> ------------------------------ live log teardown -------------------------------
> 13:03:26 OUT    host.0.0.bluetoothctl:  [BlueZ 5.86]> [CHG] Device 70:1A:B8:98:FF:qemu-system-x86_64: terminating on signal 15 from pid 149357 (python3)
>
> ======================= 1 passed, 4 deselected in 13.22s =======================
>
> $ test/test-functional -k test_btmgmt --kernel=../linux --trace
> ============================= test session starts ==============================
> platform linux -- Python 3.14.3, pytest-8.3.5, pluggy-1.6.0
> rootdir: /home/pauli/prj/external/bluez/unit
> configfile: pytest.ini
> plugins: cov-5.0.0, forked-1.6.0, rerunfailures-15.0, timeout-2.4.0, xdist-3.7.0, hypothesis-6.123.0, flaky-3.8.1, anyio-4.12.1
> collected 5 items / 4 deselected / 1 selected
>
> test/functional/test_btmgmt_vm.py
> >>>>>>>>>>>>>>>>>>>> PDB runcall (IO-capturing turned off) >>>>>>>>>>>>>>>>>>>>>
> > /home/pauli/prj/external/bluez/test/functional/test_btmgmt_vm.py(19)test_btmgmt_info()
> -> (host,) = hosts
> (Pdb) n
> > /home/pauli/prj/external/bluez/test/functional/test_btmgmt_vm.py(21)test_btmgmt_info()
> -> result = host.call(
> (Pdb) p host.bdaddr
> '00:aa:01:00:00:42'
> (Pdb) n
> > /home/pauli/prj/external/bluez/test/functional/test_btmgmt_vm.py(22)test_btmgmt_info()
> -> run,
> (Pdb) n
> > /home/pauli/prj/external/bluez/test/functional/test_btmgmt_vm.py(23)test_btmgmt_info()
> -> [btmgmt, "--index", "0", "info"],
> (Pdb) n
> > /home/pauli/prj/external/bluez/test/functional/test_btmgmt_vm.py(24)test_btmgmt_info()
> -> stdout=subprocess.PIPE,
> (Pdb) n
> > /home/pauli/prj/external/bluez/test/functional/test_btmgmt_vm.py(25)test_btmgmt_info()
> -> stdin=subprocess.DEVNULL,
> (Pdb) n
> > /home/pauli/prj/external/bluez/test/functional/test_btmgmt_vm.py(26)test_btmgmt_info()
> -> encoding="utf-8",
> (Pdb) n
> > /home/pauli/prj/external/bluez/test/functional/test_btmgmt_vm.py(21)test_btmgmt_info()
> -> result = host.call(
> (Pdb) n
> > /home/pauli/prj/external/bluez/test/functional/test_btmgmt_vm.py(28)test_btmgmt_info()
> -> assert result.returncode == 0
> (Pdb) p result
> CompletedProcess(args=['/home/pauli/prj/external/bluez/build/tools/btmgmt', '--index', '0', 'info'], returncode=0, stdout='hci0:\tPrimary controller\n\taddr 00:AA:01:00:00:42 version 11 manufacturer 1521 class 0x000000\n\tsupported settings: powered connectable fast-connectable discoverable bondable link-security ssp br/edr le advertising secure-conn debug-keys privacy static-addr phy-configuration cis-central cis-peripheral iso-broadcaster sync-receiver ll-privacy past-sender past-receiver \n\tcurrent settings: br/edr \n\tname \n\tshort name \n')
> (Pdb) print(result.stdout)
> hci0:   Primary controller
>         addr 00:AA:01:00:00:42 version 11 manufacturer 1521 class 0x000000
>         supported settings: powered connectable fast-connectable discoverable bondable link-security ssp br/edr le advertising secure-conn debug-keys privacy static-addr phy-configuration cis-central cis-peripheral iso-broadcaster sync-receiver ll-privacy past-sender past-receiver
>         current settings: br/edr
>         name
>         short name
> (Pdb) q
>
> !!!!!!!!!!!!!!!!!!! _pytest.outcomes.Exit: Quitting debugger !!!!!!!!!!!!!!!!!!!
> ======================= 4 deselected in 75.91s (0:01:15) =======================
>
> Pauli Virtanen (16):
>   emulator: btvirt: check pkt lengths, don't get stuck on malformed
>   emulator: btvirt: allow specifying where server unix sockets are made
>   emulator: btvirt: support SCO data packets
>   emulator: btdev: clear more state on Reset
>   test-runner: enable path argument for --unix
>   test-runner: Add -o/--option option
>   test-runner: allow source tree root for -k
>   test-runner: use virtio-serial for implementing -u device forwarding
>   doc: enable CONFIG_VIRTIO_CONSOLE in tester config
>   doc: enable KVM paravirtualization & clock support in tester kernel
>     config
>   doc: add functional/integration testing documentation
>   test: add functional/integration testing framework
>   build: add functional testing target
>   test: functional: impose Python code formatting
>   test: functional: add some Agent1 interface tests
>   test: functional: add basic obex file transfer tests
>
>  Makefile.am                             |  10 +
>  configure.ac                            |  22 ++
>  doc/ci.config                           |   9 +
>  doc/test-functional.rst                 | 299 ++++++++++++++++++++++++
>  doc/test-runner.rst                     |  17 ++
>  doc/tester.config                       |   9 +
>  emulator/btdev.c                        | 117 ++++++----
>  emulator/main.c                         |  37 +--
>  emulator/server.c                       |  21 ++
>  test/functional/__init__.py             |   2 +
>  test/functional/conftest.py             |  48 ++++
>  test/functional/requirements.txt        |   2 +
>  test/functional/test_agent.py           |  46 ++++
>  test/functional/test_bluetoothctl_vm.py | 152 ++++++++++++
>  test/functional/test_btmgmt_vm.py       |  30 +++
>  test/functional/test_obex.py            | 285 ++++++++++++++++++++++
>  test/functional/test_tests.py           |  23 ++
>  test/pytest.ini                         |  17 ++
>  test/test-functional                    |  21 ++
>  test/test-functional-attach             |   7 +
>  tools/test-runner.c                     |  89 ++++---
>  21 files changed, 1177 insertions(+), 86 deletions(-)
>  create mode 100644 doc/test-functional.rst
>  create mode 100644 test/functional/__init__.py
>  create mode 100644 test/functional/conftest.py
>  create mode 100644 test/functional/requirements.txt
>  create mode 100644 test/functional/test_agent.py
>  create mode 100644 test/functional/test_bluetoothctl_vm.py
>  create mode 100644 test/functional/test_btmgmt_vm.py
>  create mode 100644 test/functional/test_obex.py
>  create mode 100644 test/functional/test_tests.py
>  create mode 100644 test/pytest.ini
>  create mode 100755 test/test-functional
>  create mode 100755 test/test-functional-attach
>
> --
> 2.54.0

Do you mind resending the remaining changes? I'd like to see how it
works; it seems you've already integrated with things like `make
check`, right?

-- 
Luiz Augusto von Dentz

^ permalink raw reply

* RE: [v4,1/2] Bluetooth: hci_conn: Fix null ptr deref in hci_abort_conn()
From: bluez.test.bot @ 2026-06-12 18:32 UTC (permalink / raw)
  To: linux-bluetooth, oss
In-Reply-To: <20260612161753.3140707-1-oss@fourdim.xyz>

[-- Attachment #1: Type: text/plain, Size: 2794 bytes --]

This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=1110757

---Test result---

Test Summary:
CheckPatch                    PASS      2.09 seconds
VerifyFixes                   PASS      0.13 seconds
VerifySignedoff               PASS      0.13 seconds
GitLint                       PASS      0.64 seconds
SubjectPrefix                 PASS      0.24 seconds
BuildKernel                   PASS      31.25 seconds
CheckAllWarning               PASS      29.22 seconds
CheckSparse                   PASS      27.09 seconds
BuildKernel32                 PASS      24.86 seconds
TestRunnerSetup               PASS      539.28 seconds
TestRunner_l2cap-tester       PASS      59.68 seconds
TestRunner_iso-tester         PASS      85.37 seconds
TestRunner_bnep-tester        PASS      18.81 seconds
TestRunner_mgmt-tester        FAIL      211.24 seconds
TestRunner_rfcomm-tester      PASS      25.31 seconds
TestRunner_sco-tester         PASS      32.96 seconds
TestRunner_ioctl-tester       PASS      26.06 seconds
TestRunner_mesh-tester        FAIL      25.94 seconds
TestRunner_smp-tester         PASS      23.50 seconds
TestRunner_userchan-tester    PASS      20.60 seconds
TestRunner_6lowpan-tester     FAIL      46.95 seconds
IncrementalBuild              PASS      42.35 seconds

Details
##############################
Test: TestRunner_mgmt-tester - FAIL
Desc: Run mgmt-tester with test-runner
Output:
Total: 494, Passed: 489 (99.0%), Failed: 1, Not Run: 4

Failed Test Cases
Read Exp Feature - Success                           Failed       0.247 seconds
##############################
Test: TestRunner_mesh-tester - FAIL
Desc: Run mesh-tester with test-runner
Output:
Total: 10, Passed: 8 (80.0%), Failed: 2, Not Run: 0

Failed Test Cases
Mesh - Send cancel - 1                               Timed out    2.773 seconds
Mesh - Send cancel - 2                               Timed out    1.990 seconds
##############################
Test: TestRunner_6lowpan-tester - FAIL
Desc: Run 6lowpan-tester with test-runner
Output:
Total: 8, Passed: 3 (37.5%), Failed: 5, Not Run: 0

Failed Test Cases
Client Connect - Disconnect                          Timed out    5.128 seconds
Client Recv Dgram - Success                          Timed out    4.988 seconds
Client Recv Raw - Success                            Timed out    4.994 seconds
Client Recv IPHC Dgram - Success                     Timed out    4.996 seconds
Client Recv IPHC Raw - Success                       Timed out    4.994 seconds


https://github.com/bluez/bluetooth-next/pull/311

---
Regards,
Linux Bluetooth


^ permalink raw reply

* [bluez/bluez]
From: BluezTestBot @ 2026-06-12 18:26 UTC (permalink / raw)
  To: linux-bluetooth

  Branch: refs/heads/1094320
  Home:   https://github.com/bluez/bluez

To unsubscribe from these emails, change your notification settings at https://github.com/bluez/bluez/settings/notifications

^ permalink raw reply

* Re: [PATCH v1] Bluetooth: 6lowpan: Fix using chan->conn as indication to no remote netdev
From: Siwei Zhang @ 2026-06-12 16:42 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth
In-Reply-To: <20260612142957.524526-1-luiz.dentz@gmail.com>

Hi Luiz,

On Fri, Jun 12, 2026, at 10:29 AM, Luiz Augusto von Dentz wrote:
> From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
>
> b66774b48dd9 ("Bluetooth: L2CAP: Fix UAF in channel timeout by holding
> conn ref") don't reset the chan->conn to NULL anymore making the bt#
> netdev not be remove once the last l2cap_chan_del is removed.
>
> Instead of restoring the original behavior this remove the logic of
> keeping the interface after the last channel is removed because it
> never worked as intended and the l2cap_chan_del always detach its
> l2cap_conn which results in always removing the channel anyway.
>
> Fixes: b66774b48dd9 ("Bluetooth: L2CAP: Fix UAF in channel timeout by 
> holding conn ref")
> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

I think the 6lowpan CI failed because of this.
What about backporting it to stable here?
b66774b48dd9 ("Bluetooth: L2CAP: Fix UAF in channel timeout by holding
conn ref") has a cc to stable.

> ---
>  net/bluetooth/6lowpan.c | 10 ----------
>  1 file changed, 10 deletions(-)
>
> diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
> index cb1e329d66fd..dba0c9128cf6 100644
> --- a/net/bluetooth/6lowpan.c
> +++ b/net/bluetooth/6lowpan.c
> @@ -801,16 +801,6 @@ static void chan_close_cb(struct l2cap_chan *chan)
> 
>  	BT_DBG("chan %p conn %p", chan, chan->conn);
> 
> -	if (chan->conn && chan->conn->hcon) {
> -		if (!is_bt_6lowpan(chan->conn->hcon))
> -			return;
> -
> -		/* If conn is set, then the netdev is also there and we should
> -		 * not remove it.
> -		 */
> -		remove = false;

After removing this, the remove var will always be true,
leaving the var and the corresponding checking redundant.

> -	}
> -
>  	spin_lock(&devices_lock);
> 
>  	list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list) {
> -- 
> 2.54.0

Best,
Siwei

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox