Skip to content

sysctl: allow only log level and sync over serial SysRq - #2641

Merged
widgetii merged 2 commits into
masterfrom
sysrq-mask
Oct 20, 2026
Merged

widgetii merged 2 commits into
masterfrom
sysrq-mask

Conversation

@widgetii

@widgetii widgetii commented Oct 20, 2026 •

Copy link
Copy Markdown
Member

Problem

A serial BREAK followed by any byte runs that byte as a SysRq key, and the kernel default (kernel.sysrq = 1) enables every key. Hot-plugging a UART adapter produces exactly that sequence.

The same path can just as easily reboot, power off, crash, kill every process, or remount filesystems read-only, depending on which byte arrives.

Change

general/overlay/etc/sysctl.conf gains kernel.sysrq = 18: log level (2) and sync (16) only. S02sysctl (Buildroot's busybox package) already applies this file early in boot.

  • Refused from the console: b reboot, o power-off, c crash, e/i/f kill tasks, u remount read-only, j thaw, n RT-nice, and the show-timers/show-locks keys. The dump keys (t, m, w, l, p) share the dump bit with crash c in these kernels, so allowing them would allow crash too.
  • Unaffected: /proc/sysrq-trigger ignores the mask (write_sysrq_trigger() calls __handle_sysrq(c, false)), so root on the camera can still run any key.
  • Kernels without CONFIG_MAGIC_SYSRQ (hi3520dv200, gk710x boards) have no kernel.sysrq entry. Busybox sysctl -p logs it as an unknown key and exits 0, the same as the existing net.core.bpf_jit_enable line already does on boards without a BPF JIT.
  • Failsafe boots: rcS hands these to failsafe-rescue before any init script runs, so failsafe-rescue now starts S02sysctl first in its own service list. A rescue session is when someone is likely to be attaching a UART. That path is untested here: it ships only on the failsafe families.
  • Not covered: the window before S02sysctl runs. These kernels hard-code the default (SYSRQ_DEFAULT_ENABLE 1) and have no Kconfig option to change it.

Hardware tested on

XM550 (XM530 die) + IMX335, xm550_lite nightly with kernel #6 SMP Sun Oct 18.

This branch's sysctl.conf was copied over /etc/sysctl.conf (overlay) and the camera rebooted. The overlay copy was removed afterwards. Not tested as a built image.

Evidence

Before (stock image):

# cat /proc/sys/kernel/sysrq
1

After (this branch's file, after a reboot):

# cat /proc/sys/kernel/sysrq
18
# logread | grep sysctl
kern.info sysctl: * Applying /etc/sysctl.conf ...
kern.info sysctl: kernel.printk = 3 3 1 3
kern.err sysctl: sysctl: error: 'net.core.bpf_jit_enable' is an unknown key
kern.info sysctl: kernel.sysrq = 18

(The bpf_jit_enable error predates this change.)

Mask behaviour, QEMU xm530 machine, stock (unfixed) xm530 nightly kernel, init=/bin/sh, keys sent as serial BREAK + key:

kernel.sysrq = 1 (default):
  BREAK+j -> "SysRq : Emergency Thaw of all frozen filesystems", then 47,812 "Emergency Thaw on mtdblock3" in 6 s; shell dead
kernel.sysrq = 18:
  BREAK+j -> "SysRq : This sysrq operation is disabled."
  BREAK+s -> "SysRq : Emergency Sync" ... "Emergency Sync complete"
  shell still answers

Checks: ci-matrix.py --self-test ok. STRICT=1 test_shell_parse.sh clean. ci-matrix.py --stdin selects every board: "general/overlay/etc/sysctl.conf affects every board".

Scope

  • No kernel patches under general/package/all-patches/linux/ (those go to OpenIPC/linux)
  • No files specific to a single retail camera model (those go to OpenIPC/builder)
  • No probing or bring-up tooling (that goes to OpenIPC/ipctool)
  • Nothing under general/overlay/ or in a shared load_<vendor> script hardcodes a value specific to my board
  • Package sources come from an OpenIPC repository, and any version bump keeps at least the specificity of the pin it replaces (a new package should pin a full 40-character SHA)
  • No LD_PRELOAD, and no binaries that cannot be rebuilt from source
  • New code is selected by a defconfig, so CI actually builds it

A BREAK on the console line followed by any byte runs that byte as a SysRq
key, and the kernel default enables every one. Hot-plugging a UART adapter
makes exactly that. On a lab XM550 it fired an emergency thaw, which on the
pre-4.9 kernels loops for ever (OpenIPC/linux#113) and took the camera off
the network until it was power-cycled; a later boot of the same board took
96 framing errors and a BREAK from plugging an adapter in, and logged
"SysRq : HELP" from the stray key.

kernel.sysrq = 18 keeps log level (2) and sync (16). Everything else --
reboot, power-off, crash, kill-all, remount read-only, thaw -- is refused
from the console. /proc/sysrq-trigger ignores the mask, so root on the
camera can still run any of them. S02sysctl applies it early in boot; the
kernel's own default can't be narrowed on these kernels, so the window
before that remains.
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Restrict serial SysRq to log level and sync

🐞 Bug fix ⚙️ Configuration changes 🕐 Less than 10 minutes

Grey Divider

AI Description

• Limit serial-console SysRq to log-level changes and sync, preventing stray UART bytes from
 triggering disruptive operations.
• Apply the shared mask through the existing early-boot sysctl configuration; root-triggered SysRq
 remains unaffected.
Diagram

graph TD
  Boot["Early boot sysctl"] --> Config["Shared sysctl config"] --> Mask{"SysRq mask 18"} -->|allowed keys| Allowed["Log level sync"]
  UART["Serial BREAK key"] --> Mask -->|other keys| Refused["Operation refused"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Change the kernel's default SysRq mask
  • ➕ Closes the exposure window before the boot-time sysctl runs.
  • ➖ Requires changes across affected kernels rather than one shared overlay configuration.

Recommendation: Use the shared sysctl setting for this PR: it limits console SysRq after early boot without kernel-specific changes. A kernel-default change is worth considering separately if the pre-sysctl exposure window must also be closed.

Files changed (1) +6 / -0

Bug fix (1) +6 / -0
sysctl.confRestrict console SysRq with a shared kernel mask +6/-0

Restrict console SysRq with a shared kernel mask

• Sets kernel.sysrq to 18, permitting log-level changes and sync while disabling other serial-console SysRq operations. Comments document the UART hot-plug risk and clarify that /proc/sysrq-trigger bypasses the mask.

general/overlay/etc/sysctl.conf

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Remediation recommended

1. Failsafe boots leave serial SysRq open ✓ Resolved
Description
kernel.sysrq = 18 depends on the regular sysctl init script, but rcS exits into
failsafe-rescue before running any regular init scripts. On failsafe-enabled Goke cameras, that
rescue path brings up networking and SSH while the kernel's configured SysRq default remains 0x1,
so a serial BREAK and stray byte can still invoke the destructive keys throughout the rescue
session.
Code

general/overlay/etc/sysctl.conf[9]

+kernel.sysrq = 18
Evidence
The new setting is only in the sysctl configuration file. The failsafe branch exits before rcS runs
the init-script loop, and the rescue script's explicit service list does not include sysctl. Goke
builds enable this failsafe path and configure the kernel's unrestricted SysRq default.

general/overlay/etc/sysctl.conf[4-9]
general/overlay/etc/init.d/rcS[12-25]
general/package/openipc-failsafe/files/failsafe-rescue[29-32]
br-ext-chip-goke/configs/gk7205v200_lite_defconfig[76-76]
br-ext-chip-goke/board/gk7205v200/gk7205v200.generic.config[2520-2520]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Failsafe boot bypasses the init script that applies `/etc/sysctl.conf`, leaving serial SysRq unrestricted for the rescue session.
## Fix Focus Areas
- general/overlay/etc/sysctl.conf[4-9]
- general/overlay/etc/init.d/rcS[12-25]
- general/package/openipc-failsafe/files/failsafe-rescue[29-32]
## Recommended Fix
Apply the SysRq mask before `rcS` enters the failsafe branch, or explicitly apply the configuration in `failsafe-rescue`, while preserving its restricted service startup.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Tip of the day
💡 Did you know, you can open the rule or relationship behind a finding in one click

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread general/overlay/etc/sysctl.conf
rcS hands a failsafe boot to failsafe-rescue before any init script runs,
so S02sysctl -- and with it the serial SysRq mask -- never ran there. A
rescue session is when someone is attaching a UART adapter, whose BREAK
and stray byte would run any SysRq key. Start S02sysctl first in its
hand-written service list.
@widgetii
widgetii merged commit e45ee2d into master Oct 20, 2026
137 checks passed
@widgetii
widgetii deleted the sysrq-mask branch October 20, 2026 14:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant