[BRLTTY] BRLTTY appears severely broken
Alexander Epaneshnikov
aarnaarn2 at gmail.com
Tue Nov 25 22:07:47 UTC 2025
On Tue, Nov 25, 2025 at 04:39:20PM -0500, Dave Mielke wrote:
> [quoted lines by Alexander Epaneshnikov on 2025/11/26 at 00:14 +0300]
>
> >this change was done by systemd in commit https://github.com/systemd/systemd/commit/a4d1891475
>
> I don't know how to read that link. Could you, perhaps, please post the diff?
sure.
$ LC_ALL=.utf8 git --no-pager show a4d1891475
commit a4d1891475
Author: Yu Watanabe <watanabe.yu+github at gmail.com>
Date: 12 months ago
meson: allow to customize the access mode for tty/pts devices
Then, switch the default value to "0600", due to general security
concerns about terminals being written to by other users.
Closing #35599.
diff --git a/NEWS b/NEWS
index e6baa12c40..7563d63d9c 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,11 @@ CHANGES WITH 258 in spe:
Incompatible changes:
+ * The default access mode of tty/pts device nodes has been changed to
+ 0600, which was 0620 in the older releases, due to general security
+ concerns about terminals being written to by other users. To restore
+ the old default access mode, use '-Dtty-mode=0620' meson build option.
+
* systemd-run's --expand-environment= switch, which was disabled
by default when combined with --scope, has been changed to to be
enabled by default. This brings cmdline expansion of transient
diff --git a/meson.build b/meson.build
index bffda86845..aa51a3aead 100644
--- a/meson.build
+++ b/meson.build
@@ -978,6 +978,16 @@ conf.set10('DEV_KVM_UACCESS', dev_kvm_mode != '0666')
group_render_mode = get_option('group-render-mode')
conf.set_quoted('GROUP_RENDER_MODE', group_render_mode)
conf.set10('GROUP_RENDER_UACCESS', group_render_mode != '0666')
+tty_mode = get_option('tty-mode')
+# The setting is used as both octal integer and string through STRINGIFY().
+# Here, only check if the value starts with '06', and further check will be done in terminal-util.h.
+if not tty_mode.startswith('06')
+ error('Unexpected access mode "@0@" is specified for TTY/PTS device nodes, it must be "06xx".'.format(tty_mode))
+elif tty_mode != '0600' and tty_mode != '0620'
+ warning('Unexpected access mode "@0@" is specified for TTY/PTS device nodes, typically it should be "0600" or "0620", proceeding anyway.'.format(tty_mode))
+endif
+# Do not use set_quoted() here, so that the value is available as an integer.
+conf.set('TTY_MODE', tty_mode)
kill_user_processes = get_option('default-kill-user-processes')
conf.set10('KILL_USER_PROCESSES', kill_user_processes)
diff --git a/meson_options.txt b/meson_options.txt
index 78ec25bfa3..d9242d3b30 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -330,6 +330,8 @@ option('dev-kvm-mode', type : 'string', value : '0666',
description : '/dev/kvm access mode')
option('group-render-mode', type : 'string', value : '0666',
description : 'Access mode for devices owned by render group (e.g. /dev/dri/renderD*, /dev/kfd).')
+option('tty-mode', type : 'string', value : '0600',
+ description : 'Access mode for tty/pts device nodes.')
option('default-kill-user-processes', type : 'boolean',
description : 'the default value for KillUserProcesses= setting')
option('gshadow', type : 'boolean',
diff --git a/rules.d/50-udev-default.rules.in b/rules.d/50-udev-default.rules.in
index 6f80feeecf..8fa518cd8f 100644
--- a/rules.d/50-udev-default.rules.in
+++ b/rules.d/50-udev-default.rules.in
@@ -37,7 +37,7 @@ ACTION!="add", GOTO="default_end"
SUBSYSTEM=="tty", KERNEL=="ptmx", GROUP="tty", MODE="0666"
SUBSYSTEM=="tty", KERNEL=="tty", GROUP="tty", MODE="0666"
-SUBSYSTEM=="tty", KERNEL=="tty[0-9]*|hvc[0-9]*|sclp_line[0-9]*|ttysclp[0-9]*|3270/tty[0-9]*", GROUP="tty", MODE="0620"
+SUBSYSTEM=="tty", KERNEL=="tty[0-9]*|hvc[0-9]*|sclp_line[0-9]*|ttysclp[0-9]*|3270/tty[0-9]*", GROUP="tty", MODE="{{TTY_MODE}}"
SUBSYSTEM=="vc", KERNEL=="vcs*|vcsa*", GROUP="tty"
KERNEL=="tty[A-Z]*[0-9]|ttymxc[0-9]*|pppox[0-9]*|ircomm[0-9]*|noz[0-9]*|rfcomm[0-9]*", GROUP="dialout"
diff --git a/src/basic/terminal-util.h b/src/basic/terminal-util.h
index 782b0fed9d..fc7a22e6a5 100644
--- a/src/basic/terminal-util.h
+++ b/src/basic/terminal-util.h
@@ -143,8 +143,9 @@ int vt_release(int fd, bool restore_vt);
void get_log_colors(int priority, const char **on, const char **off, const char **highlight);
-/* This assumes there is a 'tty' group */
-#define TTY_MODE 0620
+/* Assume TTY_MODE is defined in config.h. Also, this assumes there is a 'tty' group. */
+assert_cc((TTY_MODE & ~0666) == 0);
+assert_cc((TTY_MODE & 0711) == 0600);
void termios_disable_echo(struct termios *termios);
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index 500725d35f..6f90f2f418 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -2399,13 +2399,13 @@ static int setup_pts(const char *dest) {
#if HAVE_SELINUX
if (arg_selinux_apifs_context)
(void) asprintf(&options,
- "newinstance,ptmxmode=0666,mode=620,gid=" GID_FMT ",context=\"%s\"",
+ "newinstance,ptmxmode=0666,mode=" STRINGIFY(TTY_MODE) ",gid=" GID_FMT ",context=\"%s\"",
arg_uid_shift + TTY_GID,
arg_selinux_apifs_context);
else
#endif
(void) asprintf(&options,
- "newinstance,ptmxmode=0666,mode=620,gid=" GID_FMT,
+ "newinstance,ptmxmode=0666,mode=" STRINGIFY(TTY_MODE) ",gid=" GID_FMT,
arg_uid_shift + TTY_GID);
if (!options)
diff --git a/src/shared/mount-setup.c b/src/shared/mount-setup.c
index d5009fb59e..73be3b5dce 100644
--- a/src/shared/mount-setup.c
+++ b/src/shared/mount-setup.c
@@ -93,7 +93,7 @@ static const MountPoint mount_table[] = {
#endif
{ "tmpfs", "/dev/shm", "tmpfs", "mode=01777", MS_NOSUID|MS_NODEV|MS_STRICTATIME,
NULL, MNT_FATAL|MNT_IN_CONTAINER },
- { "devpts", "/dev/pts", "devpts", "mode=0620,gid=" STRINGIFY(TTY_GID), MS_NOSUID|MS_NOEXEC,
+ { "devpts", "/dev/pts", "devpts", "mode=" STRINGIFY(TTY_MODE) ",gid=" STRINGIFY(TTY_GID), MS_NOSUID|MS_NOEXEC,
NULL, MNT_IN_CONTAINER },
#if ENABLE_SMACK
{ "tmpfs", "/run", "tmpfs", "mode=0755,smackfsroot=*" TMPFS_LIMITS_RUN, MS_NOSUID|MS_NODEV|MS_STRICTATIME,
diff --git a/tools/meson-render-jinja2.py b/tools/meson-render-jinja2.py
index 977de79378..1f893ed9a4 100755
--- a/tools/meson-render-jinja2.py
+++ b/tools/meson-render-jinja2.py
@@ -17,7 +17,9 @@ def parse_config_h(filename):
if not m:
continue
a, b = m.groups()
- if b and b[0] in '0123456789"':
+ # The function ast.literal_eval() cannot evaluate octal integers, e.g. 0600.
+ # So, it is intentional that the string below does not contain '0'.
+ if b and (b[0] in '123456789"' or b == '0'):
b = ast.literal_eval(b)
ans[a] = b
return ans
> >I pushed fix to archlinux brltty package
> >https://gitlab.archlinux.org/archlinux/packaging/packages/brltty/-/commit/fcb9ae5937575e1df759db92fc828ed76c7586eb
>
> Could you also post your fix?
$ LC_ALL=.utf8 git --no-pager show fcb9ae5937
commit fcb9ae5
Author: Alexander Epaneshnikov <alex19ep at archlinux.org>
Date: 2 hours ago
fix /dev/tty* permissions
diff --git a/PKGBUILD b/PKGBUILD
index 35f1ca0..2068a68 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -51,15 +51,18 @@ source=(
$pkgname-6.2-systemd_sysusers_groups.patch
$pkgname-6.8-lock-brltty-user.patch
$pkgname-6.4-x11_autostart.patch
+ $pkgname-6.8-udev-tty-perms.rules
)
sha512sums=('a7f49850722e65640a3f9690a391d429b3d8658ee55141d9cffc636813ffeedd9eaa1acfa451a0120a9eefcd9b84c6b640eb99aa26357aac9ffda3d48b4fc520'
'32ba91271e2247b4a330cd213ed75b591268cb99a79c2efd9ae675804faee027c6b2f782768cb2329a65fc914ca2400b2901f35ce1fc2522c6691b343799eb02'
'2f1dba4fa5495913837972030fbcf1c265c90d481d9e0f96ff89c6cab082f7a6b0594c5c7ca6ea446eb76c8f483c7ed57ede58480898ae003261e6373440862c'
- '4871512affefbc178f4204a1b285fc2b5a05ea2d181163195d695b760e9729b3d2d00b5f052abd71379df609c3859d7cbd64128bdefd16e898bbc4368500a9a0')
+ '4871512affefbc178f4204a1b285fc2b5a05ea2d181163195d695b760e9729b3d2d00b5f052abd71379df609c3859d7cbd64128bdefd16e898bbc4368500a9a0'
+ 'dd210599e467a073f891554c7d3991dce90fa0506a7aef28c43a1543d94073e8d561d36c909511778d4bfcc198cac04f146966edf4462d5e553224a72864f6f3')
b2sums=('e75b2d0d977f88b61f294226f4e7728ffe0a18592a2b331e63c1d486be909a9e5237c6618151a789b9518f327d8fc2a80a975178201318d9284a399fc0571d42'
'036e36d558594bb06af1eb41ff5fc9ae52ccf4bad54556c3f4f81a5e2f31f574039835e5e756455527c327a73d563a3db54a9f32e3478545a2a22c2725aaeee2'
'76fd46571dab803c39a1663e52293c7e1ee9232b6241528e708bca072c7f9bd270c1961b960bece7f91331a259042b8dfc9a8e77f7dc463944b305700fe0c8f6'
- '4ebc07a725ef8362233a83118e93901e78943e8dae08f9358b668ff13ab88a65eb9e87c49d106a8c3d87eb62007b230e199107eacb01f92dc683335076c01309')
+ '4ebc07a725ef8362233a83118e93901e78943e8dae08f9358b668ff13ab88a65eb9e87c49d106a8c3d87eb62007b230e199107eacb01f92dc683335076c01309'
+ '7110448b42799195abbc6f9711ebe25cdbc95056833764332c343a2d6e1201c8b590644db46a2d6612fa96740cb7da8cc7f72bb329127ae3bb6c8351efcde260')
prepare() {
cd $pkgbase-${pkgbase^^}-$pkgver
@@ -143,6 +146,7 @@ package_brltty() {
# move generic udev rule, as it applies too broadly
mv -v "$pkgdir/usr/lib/udev/rules.d/90-brltty-usb-generic.rules" ../
+ install -vDm 644 ../brltty-6.8-udev-tty-perms.rules "$pkgdir/usr/lib/udev/rules.d/90-brltty-tty-perms.rules"
}
package_brltty-udev-generic() {
diff --git a/brltty-6.8-udev-tty-perms.rules b/brltty-6.8-udev-tty-perms.rules
new file mode 100644
index 0000000..3e77ee4
--- /dev/null
+++ b/brltty-6.8-udev-tty-perms.rules
@@ -0,0 +1 @@
+SUBSYSTEM=="tty", KERNEL=="tty[0-9]*", GROUP="tty", MODE="0660"
> Does systemd now maintain service units for brltty?
no.
> --
> I believe the Bible to be the very Word of God: http://Mielke.cc/bible/
> Dave Mielke | 2213 Fox Crescent | WebHome: http://Mielke.cc/
> EMail: Dave at Mielke.cc | Ottawa, Ontario | Twitter: @Dave_Mielke
> Phone: +1 613 726 0014 | Canada K2A 1H7 |
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> http://mielke.cc/xmother.html (Letter from a Feminist ex-Mother)
Sincerely, Alexander
More information about the BRLTTY
mailing list