Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .clang-tidy
Original file line number Diff line number Diff line change
Expand Up @@ -144,4 +144,10 @@ readability-static-accessed-through-instance,
readability-static-definition-in-anonymous-namespace,
readability-string-compare,
readability-uniqueptr-delete-release,
readability-use-anyofallof'
readability-use-anyofallof,
cppcoreguidelines-avoid-non-const-global-variables,
clang-analyzer-security.*,
cppcoreguidelines-pro-bounds-*,
cppcoreguidelines-pro-type-reinterpret-cast'


40 changes: 40 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Dependabot configuration
#
# Automatically opens PRs to update pinned GitHub Actions SHAs whenever a new
# release is published. Combined with SHA pinning in ci.yml, this gives both
# immutability (the SHA cannot be moved) and automatic security updates (a PR
# is raised as soon as a new version is tagged upstream).
#
# References:
# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates
# https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-third-party-actions

version: 2
updates:
# ── GitHub Actions ────────────────────────────────────────────────────────
- package-ecosystem: "github-actions"
# Dependabot scans every workflow file under .github/workflows/
directory: "/"
schedule:
interval: "weekly"
day: "monday"
time: "07:00"
timezone: "UTC"
# Group all action bumps into a single PR so the diff is easy to review
groups:
github-actions:
patterns:
- "*"
# Only open PRs against main/master
target-branch: "main"
labels:
- "dependencies"
- "github-actions"
commit-message:
prefix: "ci"
include: "scope"
# Limit open PRs to avoid noise
open-pull-requests-limit: 5
# Keep the version comment accurate even when SHA changes
versioning-strategy: "auto"

25 changes: 16 additions & 9 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@ jobs:
actions: read
steps:
- name: Checkout code
uses: actions/checkout@v4
# actions/checkout v4.2.2 — pinned to full SHA
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
submodules: recursive

- name: Initialize CodeQL
uses: github/codeql-action/init@v3
# github/codeql-action/init v4.32.6 — pinned to full SHA
uses: github/codeql-action/init@fb0994ef1c058010acf1efccff928b0a83b1ed54 # v4.32.6
with:
languages: cpp
queries: security-and-quality
Expand Down Expand Up @@ -55,7 +57,8 @@ jobs:
CXX: g++-14

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
# github/codeql-action/analyze v4.32.6 — pinned to full SHA (was @v3, now consistent with init)
uses: github/codeql-action/analyze@fb0994ef1c058010acf1efccff928b0a83b1ed54 # v4.32.6
with:
category: "/language:cpp"

Expand All @@ -66,7 +69,8 @@ jobs:
contents: read
steps:
- name: Checkout code
uses: actions/checkout@v4
# actions/checkout v4.2.2 — pinned to full SHA
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

- name: Install clang-format
run: |
Expand All @@ -88,7 +92,8 @@ jobs:
contents: read
steps:
- name: Checkout code
uses: actions/checkout@v4
# actions/checkout v4.2.2 — pinned to full SHA
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
submodules: recursive

Expand All @@ -98,7 +103,7 @@ jobs:
wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | \
sudo tee /etc/apt/trusted.gpg.d/llvm.asc
sudo add-apt-repository -y \
'deb http://apt.llvm.org/noble/ llvm-toolchain-noble-19 main'
'deb https://apt.llvm.org/noble/ llvm-toolchain-noble-19 main'
sudo apt-get update
sudo apt-get install -y \
clang-19 \
Expand Down Expand Up @@ -179,7 +184,8 @@ jobs:
- {cc: clang-19, cxx: clang++-19, name: llvm-19, stdlib: libc++}
steps:
- name: Checkout code
uses: actions/checkout@v4
# actions/checkout v4.2.2 — pinned to full SHA
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
submodules: recursive

Expand All @@ -202,7 +208,7 @@ jobs:
wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | \
sudo tee /etc/apt/trusted.gpg.d/llvm.asc
sudo add-apt-repository -y \
'deb http://apt.llvm.org/noble/ llvm-toolchain-noble-19 main'
'deb https://apt.llvm.org/noble/ llvm-toolchain-noble-19 main'
sudo apt-get update
sudo apt-get install -y \
clang-19 \
Expand Down Expand Up @@ -257,7 +263,8 @@ jobs:
ls -lh artifacts/

- name: Upload build artifacts
uses: actions/upload-artifact@v4
# actions/upload-artifact v4.6.2 — pinned to full SHA
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: binaries-${{ matrix.compiler.name }}
path: artifacts/*
Expand Down
38 changes: 37 additions & 1 deletion generate.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,41 @@
#!/bin/bash -ex

PROXY=src/proxy
XML2CPP=$(find -iname sdbus-c++-xml2cpp)

# fix — safe tool resolution (no unconstrained find)
#
# Previous code: XML2CPP=$(find -iname sdbus-c++-xml2cpp)
# Risk: an adversary who can plant a file named sdbus-c++-xml2cpp anywhere
# beneath the working directory (e.g., in a malicious submodule) would have it
# executed instead of the real code-generator.
#
# Strategy (ordered, most-specific first):
# 1. Known CMake build-tree path (cmake-build-debug or build).
# 2. The tool on PATH (installed system-wide or via the project's own install).
# 3. Abort with a clear error — never fall through to an untrusted location.
_find_xml2cpp() {
local candidates=(
"cmake-build-debug/third_party/sdbus-cpp/tools/sdbus-c++-xml2cpp"
"build/third_party/sdbus-cpp/tools/sdbus-c++-xml2cpp"
"cmake-build-release/third_party/sdbus-cpp/tools/sdbus-c++-xml2cpp"
)
for candidate in "${candidates[@]}"; do
if [[ -x "${candidate}" ]]; then
echo "${candidate}"
return 0
fi
done
# Fall back to a PATH lookup (e.g., system-installed package)
if command -v sdbus-c++-xml2cpp &>/dev/null; then
command -v sdbus-c++-xml2cpp
return 0
fi
echo "ERROR: sdbus-c++-xml2cpp not found." \
"Build the project first (cmake + ninja) or install sdbus-c++." >&2
return 1
}

XML2CPP=$(_find_xml2cpp)

mkdir -p ${PROXY}/org/bluez/{Adapter1,AgentManager,BatteryProviderManager1,Battery1,Device1,GattManager1,GattService1,GattCharacteristic1,GattDescriptor1,Input1,LEAdvertisingManager1,Media1,NetworkServer1,Profile1} |true

Expand Down Expand Up @@ -147,3 +181,5 @@ mkdir -p ${PROXY}/org/ofono/{HandsfreeAudioManager,Manager} |true

${XML2CPP} --verbose --proxy=${PROXY}/org/ofono/HandsfreeAudioManager/handsfree_audio_manager_proxy.h interfaces/org/ofono/HandsfreeAudioManager/HandsfreeAudioManager.xml
${XML2CPP} --verbose --proxy=${PROXY}/org/ofono/Manager/manager_proxy.h interfaces/org/ofono/Manager/Manager.xml

scripts/clang-format.sh src/proxy
62 changes: 50 additions & 12 deletions src/bluez/hidraw.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
#include <unordered_map>
#include <vector>

#include <unistd.h>

#include <libudev.h>
#include <linux/hidraw.h>
#include <linux/input.h>
Expand All @@ -32,6 +34,44 @@

#include "hexdump.hpp"

/// RAII wrapper for a POSIX file descriptor.
/// Automatically closes the fd when it goes out of scope, preventing leaks
/// on every error-path break/return/exception.
struct UniqueFd {
explicit UniqueFd(const int fd) noexcept : fd_(fd) {}

~UniqueFd() {
if (fd_ >= 0) {
::close(fd_);
}
}

// Non-copyable, movable
UniqueFd(const UniqueFd&) = delete;
UniqueFd& operator=(const UniqueFd&) = delete;

UniqueFd(UniqueFd&& other) noexcept : fd_(other.fd_) { other.fd_ = -1; }
UniqueFd& operator=(UniqueFd&& other) noexcept {
if (this != &other) {
if (fd_ >= 0) {
::close(fd_);
}
fd_ = other.fd_;
other.fd_ = -1;
}
return *this;
}

/// Returns true if the fd is valid (>= 0).
[[nodiscard]] bool valid() const noexcept { return fd_ >= 0; }

/// Returns the raw file descriptor.
[[nodiscard]] int get() const noexcept { return fd_; }

private:
int fd_;
};

class Hidraw {
public:
Hidraw() = default;
Expand All @@ -47,17 +87,15 @@ class Hidraw {
Hidraw(Hidraw&&) = delete;
Hidraw& operator=(Hidraw&&) = delete;

void HidDevicesLock() { devices_mutex_.lock(); }

void HidDevicesUnlock() { devices_mutex_.unlock(); }

[[nodiscard]] bool HidDevicesContains(const std::string& key) const {
return devices_.contains(key);
}

[[nodiscard]] const std::string& GetHidDevice(
const std::string& dev_key) const {
return devices_.at(dev_key);
/// Thread-safe lookup of a hidraw device by key.
/// Returns the device path string if found, or an empty string if not.
/// Internally uses std::scoped_lock — callers never touch the mutex directly.
[[nodiscard]] std::string FindHidDevice(const std::string& key) const {
std::scoped_lock lock(devices_mutex_);
if (const auto it = devices_.find(key); it != devices_.end()) {
return it->second;
}
return {};
}

/**
Expand Down Expand Up @@ -341,7 +379,7 @@ class Hidraw {
static constexpr std::string DEV_NAME = "DEVNAME";
static constexpr std::string DEV_PATH = "DEVPATH";

std::mutex devices_mutex_;
mutable std::mutex devices_mutex_;
std::map<std::string, std::string> devices_;
};

Expand Down
10 changes: 2 additions & 8 deletions src/bluez/horipad_steam/horipad_steam.cc
Original file line number Diff line number Diff line change
Expand Up @@ -150,14 +150,8 @@ void HoripadSteam::onInterfacesAdded(
}

if (!hidraw_device_key.empty()) {
std::string hidraw_device;
HidDevicesLock();
if (HidDevicesContains(hidraw_device_key)) {
hidraw_device = GetHidDevice(hidraw_device_key);
}
HidDevicesUnlock();

if (!hidraw_device.empty()) {
if (const std::string hidraw_device = FindHidDevice(hidraw_device_key);
!hidraw_device.empty()) {
LOG_INFO("Adding hidraw device: {}", hidraw_device_key);
if (!input_reader_) {
input_reader_ = std::make_unique<InputReader>(hidraw_device);
Expand Down
Loading