Skip to content

Commit daf366a

Browse files
authored
Merge pull request #3964 from grandixximo/nosetuid
Rootless uspace preempt-rt (rebase of #918, fixes for #3928)
2 parents 7b68c9e + 4099ee2 commit daf366a

19 files changed

Lines changed: 689 additions & 315 deletions

debian/control.top.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ Build-Depends:
2828
libgl-dev | libgl1-mesa-dev,
2929
libglu1-mesa-dev,
3030
libgtk-3-dev,
31+
libcap-dev,
3132
libmodbus-dev (>= 3.0),
3233
libgpiod-dev,
3334
@LIBREADLINE_DEV@,
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# LinuxCNC - grant Mesa HostMot2 PCI cards to the plugdev group so
2+
# rtapi_app can map their config space and BARs without CAP_DAC_OVERRIDE.
3+
# Needed only for rootless (file-capabilities) builds; setuid-root builds
4+
# bypass DAC regardless.
5+
#
6+
# Add or remove Mesa subsystem IDs below to match new boards. SSIDs come
7+
# from src/hal/drivers/mesa-hostmot2/hm2_pci.h.
8+
9+
ACTION!="add|change", GOTO="linuxcnc_hm2_end"
10+
SUBSYSTEM!="pci", GOTO="linuxcnc_hm2_end"
11+
12+
# Direct-Mesa cards (5i24, 5i25, 5i25T, 6i25, 6i25T): single vendor match.
13+
ATTR{vendor}=="0x2718", GOTO="linuxcnc_hm2_chmod"
14+
15+
# PLX-bridged Mesa cards share vendor 0x10B5 with generic PLX bridges,
16+
# so match Mesa subsystem_device ids one at a time.
17+
ATTR{vendor}!="0x10b5", GOTO="linuxcnc_hm2_end"
18+
# 5i20
19+
ATTRS{subsystem_device}=="0x3131", GOTO="linuxcnc_hm2_chmod"
20+
# 4i65
21+
ATTRS{subsystem_device}=="0x3132", GOTO="linuxcnc_hm2_chmod"
22+
# 4i68 (old SSID)
23+
ATTRS{subsystem_device}=="0x3133", GOTO="linuxcnc_hm2_chmod"
24+
# 4i68 (new SSID)
25+
ATTRS{subsystem_device}=="0x3311", GOTO="linuxcnc_hm2_chmod"
26+
# 5i21
27+
ATTRS{subsystem_device}=="0x3312", GOTO="linuxcnc_hm2_chmod"
28+
# 5i22-1.5M
29+
ATTRS{subsystem_device}=="0x3313", GOTO="linuxcnc_hm2_chmod"
30+
# 5i22-1.0M
31+
ATTRS{subsystem_device}=="0x3314", GOTO="linuxcnc_hm2_chmod"
32+
# 5i23
33+
ATTRS{subsystem_device}=="0x3315", GOTO="linuxcnc_hm2_chmod"
34+
# 3x20-10
35+
ATTRS{subsystem_device}=="0x3427", GOTO="linuxcnc_hm2_chmod"
36+
# 3x20-15
37+
ATTRS{subsystem_device}=="0x3428", GOTO="linuxcnc_hm2_chmod"
38+
# 3x20-20
39+
ATTRS{subsystem_device}=="0x3429", GOTO="linuxcnc_hm2_chmod"
40+
# 4i69-16
41+
ATTRS{subsystem_device}=="0x3472", GOTO="linuxcnc_hm2_chmod"
42+
# 4i69-25
43+
ATTRS{subsystem_device}=="0x3473", GOTO="linuxcnc_hm2_chmod"
44+
GOTO="linuxcnc_hm2_end"
45+
46+
LABEL="linuxcnc_hm2_chmod"
47+
# Fork a helper; sysfs files may not exist until the device is fully
48+
# sized, so the chmod failures are ignored.
49+
RUN+="/bin/sh -c 'chgrp plugdev /sys%p/config /sys%p/resource* 2>/dev/null; chmod g+rw /sys%p/config /sys%p/resource* 2>/dev/null; exit 0'"
50+
51+
LABEL="linuxcnc_hm2_end"
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# LinuxCNC - expose realtime tuning knobs to the plugdev group so that
2+
# rtapi_app can tune latency without CAP_DAC_OVERRIDE when running under
3+
# file capabilities. setuid-root builds do not need this rule.
4+
5+
# /dev/cpu_dma_latency: harden_rt() opens this to pin CPU idle states at
6+
# C0, cutting wake-up jitter on AC-powered machines. Default is 0600
7+
# root:root, so an unprivileged rtapi_app would fail to open it.
8+
KERNEL=="cpu_dma_latency", MODE="0660", GROUP="plugdev"

docs/src/man/man9/hm2_eth.9.adoc

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,24 @@ IO boards, with HostMot2 firmware.
77

88
== SYNOPSIS
99

10-
*loadrt hm2_eth* [**config=**"__str__[,__str__...]"] [**board_ip=**__ip__[,__ip__...] ] [**board_mac=**__mac__[,__mac__...] ]
10+
*loadrt hm2_eth* [**config=**"__str__[,__str__...]"] [**board_ip=**__ip__[,__ip__...] ] [**board_mac=**__mac__[,__mac__...] ] [**no_iptables=**__0|1__]
1111

1212
____
1313
*config* [default: ""]::
1414
HostMot2 config strings, described in the hostmot2(9) manpage.
1515
*board_ip* [default: ""]::
1616
The IP address of the board(s), separated by commas.
1717
As shipped, the board address is 192.168.1.121.
18+
*no_iptables* [default: 0]::
19+
Explicit override that disables all iptables interaction. By default
20+
hm2_eth installs *iptables* and *ip6tables* rules itself; rtapi_app
21+
raises *cap_net_admin* into its ambient capability set at startup so
22+
the calls succeed under both setuid-root and rootless (file-cap)
23+
installs. If the cap is not held the probe fails and rule
24+
installation is skipped with a warning; in that case configure the
25+
rules manually using the recipe in the NOTES section below. Set
26+
*no_iptables=1* when iptables is reachable but you prefer to manage
27+
the firewall externally (nftables, firewalld, systemd units).
1828
____
1929

2030
== DESCRIPTION
@@ -146,6 +156,53 @@ At (normal) exit, hm2_eth will remove the rules. After a crash, you can
146156
manually clear the rules with *sudo iptables -F hm2-eth-rules-output*;
147157
the rules are also removed by a reboot.
148158

159+
=== Manual iptables configuration
160+
161+
When LinuxCNC is installed without *cap_net_admin* on rtapi_app
162+
(typically because *sudo make setcap* was not run after the build),
163+
hm2_eth cannot install its rules and prints a warning. Set up the
164+
chain manually as root. Adjust the IP addresses, UDP destination port,
165+
and interface name to match your install:
166+
167+
----
168+
HOST_IP=192.168.1.1
169+
BOARD_IP=192.168.1.121
170+
BOARD_DPORT=27181
171+
IFACE=eth1
172+
173+
iptables -N hm2-eth-rules-output
174+
iptables -I OUTPUT 1 -j hm2-eth-rules-output
175+
iptables -A hm2-eth-rules-output \
176+
-p udp -m udp -d $BOARD_IP --dport $BOARD_DPORT \
177+
-s $HOST_IP -j ACCEPT
178+
iptables -A hm2-eth-rules-output -o $IFACE -p icmp -j DROP
179+
iptables -A hm2-eth-rules-output -o $IFACE \
180+
-j REJECT --reject-with icmp-admin-prohibited
181+
ip6tables -N hm2-eth-rules-output
182+
ip6tables -I OUTPUT 1 -j hm2-eth-rules-output
183+
ip6tables -A hm2-eth-rules-output -o $IFACE -j DROP
184+
----
185+
186+
For full IPv6 quiescence (no router solicitations or neighbor discovery
187+
on the dedicated interface), additionally add this line to
188+
`/etc/sysctl.d/99-hm2-eth.conf` and reboot:
189+
190+
----
191+
net.ipv6.conf.IFACE.disable_ipv6 = 1
192+
----
193+
194+
(The default ip6tables rule above only drops outbound IPv6; the kernel
195+
still generates the packets.) Tear down the runtime rules with:
196+
197+
----
198+
iptables -F hm2-eth-rules-output
199+
iptables -D OUTPUT -j hm2-eth-rules-output
200+
iptables -X hm2-eth-rules-output
201+
ip6tables -F hm2-eth-rules-output
202+
ip6tables -D OUTPUT -j hm2-eth-rules-output
203+
ip6tables -X hm2-eth-rules-output
204+
----
205+
149206
"hardware-irq-coalesce-rx-usecs" decreases time waiting to receive a packet on most systems,
150207
but on at least some Marvel-chipset NICs it is harmful.
151208
If the line does not improve system performance, then remove it.

docs/src/man/man9/hm2_rpspi.9.adoc

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,14 @@ Mesa's SPI based Anything I/O boards (with the HostMot2 firmware) to the
7070
LinuxCNC HAL. This driver is not based on the linux spidev driver, but
7171
on a dedicated BCM2835-SPI driver.
7272

73-
It is *strongly* recommended that you unload/disable the kernel's spidev
74-
driver by disabling it using *raspi-config*. Please note that having
75-
both kernel and user-space SPI drivers installed can result in
76-
unexpected interactions and system instabilities.
73+
The kernel's *spi_bcm2835* driver conflicts with this user-space driver
74+
and must be disabled before *hm2_rpspi* will load. Use *raspi-config*
75+
(Interface Options -> SPI -> Disable) and reboot. If the kernel module
76+
is still present at load time the driver will refuse to start with
77+
"Kernel SPI driver spi_bcm2835 is loaded and conflicts" rather than
78+
fight the kernel for the bus. Having both kernel and user-space SPI
79+
drivers installed otherwise leads to unexpected interactions and
80+
system instabilities.
7781

7882
The supported boards are: 7I90HD.
7983

docs/src/man/man9/hm2_spix.9.adoc

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -208,13 +208,27 @@ setting would be to set one step below the maximum speeds.
208208

209209
== NOTES
210210

211-
If you know your setup and do not require the spix_spidev driver, then
212-
it is *strongly* recommended that you unload/disable the kernel's SPI
213-
drivers *dw_spi* and *dw_spi_mmio* for the RPi5 or *spi_bmc2835* for the
214-
RPi3 and RPi4. The hm2_spix hardware drivers attempt to unload the
215-
kernel driver at startup if detected and restore it at exit if initially
216-
loaded. However, there are no guarantees about the effectiveness of the
217-
module unload/load actions.
211+
If you do not require the spix_spidev driver you must disable the
212+
kernel's SPI driver before *hm2_spix* will load. The conflicting module
213+
is *spi_bcm2835* on the RPi3 / RPi4 and *dw_spi_mmio* (with its
214+
dependency *dw_spi*) on the RPi5. The driver detects the kernel module
215+
at startup and refuses to load with "Kernel SPI driver ... is loaded
216+
and conflicts" rather than fight the kernel for the bus.
217+
218+
To disable on RPi3 / RPi4, run *raspi-config* and pick
219+
Interface Options -> SPI -> Disable, then reboot.
220+
221+
To disable on RPi5, blacklist both kernel modules. Create
222+
*/etc/modprobe.d/blacklist-linuxcnc.conf* containing:
223+
224+
----
225+
blacklist dw_spi_mmio
226+
blacklist dw_spi
227+
----
228+
229+
Then reboot. If either module is built-in to the kernel rather than
230+
loadable, use a kernel command-line override
231+
(*modprobe.blacklist=dw_spi_mmio,dw_spi* in `/boot/firmware/cmdline.txt`).
218232

219233
*Warning*: having both kernel and user-space SPI drivers installed can
220234
result in unexpected interactions and system instabilities.

src/Makefile

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ endif
5757
ifeq ($(MAKECMDGOALS),)
5858
TRIVIAL_BUILD=no
5959
else
60-
ifeq ($(filter-out docclean clean setuid install tags swish,$(MAKECMDGOALS)),)
60+
ifeq ($(filter-out docclean clean setuid setcap install tags swish,$(MAKECMDGOALS)),)
6161
TRIVIAL_BUILD=yes
6262
else
6363
TRIVIAL_BUILD=no
@@ -140,7 +140,13 @@ ifeq ($(RUN_IN_PLACE),yes)
140140
ifneq ($(BUILD_SYS),uspace)
141141
@if [ -f ../bin/linuxcnc_module_helper ]; then if ! [ `id -u` = 0 -a -O ../bin/linuxcnc_module_helper -a -u ../bin/linuxcnc_module_helper ]; then $(VECHO) "You now need to run 'sudo make setuid' in order to run in place."; fi; fi
142142
else
143-
@if [ -f ../bin/rtapi_app ]; then if ! [ `id -u` = 0 -a -O ../bin/rtapi_app -a -u ../bin/rtapi_app ]; then $(VECHO) "You now need to run 'sudo make setuid' in order to run in place with access to hardware."; fi; fi
143+
@if [ -f ../bin/rtapi_app ]; then \
144+
if [ `id -u` = 0 -a -O ../bin/rtapi_app -a -u ../bin/rtapi_app ]; then :; \
145+
elif PATH="/sbin:/usr/sbin:$$PATH" command -v getcap >/dev/null 2>&1 \
146+
&& [ -n "`PATH=/sbin:/usr/sbin:$$PATH getcap ../bin/rtapi_app 2>/dev/null`" ]; then :; \
147+
else $(VECHO) "You now need to run 'sudo make setuid' or 'sudo make setcap' in order to run in place with access to hardware."; \
148+
fi; \
149+
fi
144150
endif
145151
endif
146152

@@ -568,6 +574,25 @@ endif
568574
chown root ../bin/linuxcnc_module_helper
569575
chmod 4750 ../bin/linuxcnc_module_helper
570576

577+
# File capabilities alternative to setuid (uspace only).
578+
# Grants rtapi_app the kernel privileges it needs without running as root:
579+
# cap_ipc_lock - mlock() for realtime memory
580+
# cap_net_admin - raw socket access for hm2_eth / iptables management
581+
# cap_sys_rawio - iopl() and /dev/mem for parallel port and PCI I/O
582+
# cap_sys_nice - SCHED_FIFO scheduling and CPU affinity
583+
# Linux capabilities are not inherited across exec(), so /sbin/iptables
584+
# launched from rtapi_app would run unprivileged. rtapi_app raises
585+
# cap_net_admin into its ambient set at startup so it survives execve().
586+
# Clears any setuid bit left by a prior 'make setuid' so the two paths don't
587+
# silently stack.
588+
setcap:
589+
ifeq ($(BUILD_SYS),uspace)
590+
chmod u-s ../bin/rtapi_app
591+
setcap cap_ipc_lock,cap_net_admin,cap_sys_rawio,cap_sys_nice+ep ../bin/rtapi_app
592+
else
593+
@echo "setcap target is only supported for uspace builds" >&2; exit 1
594+
endif
595+
571596
# These rules allows a header file from this directory to be installed into
572597
# ../include. A pair of rules like these will exist in the Submakefile
573598
# of each file that contains headers.
@@ -1022,7 +1047,6 @@ hm2_pci-objs := \
10221047
$(MATHSTUB)
10231048
hm2_eth-objs := \
10241049
hal/drivers/mesa-hostmot2/hm2_eth.o \
1025-
hal/drivers/mesa-hostmot2/eshellf.o \
10261050
$(MATHSTUB)
10271051
hm2_spi-objs := \
10281052
hal/drivers/mesa-hostmot2/hm2_spi.o \
@@ -1031,15 +1055,15 @@ hm2_spi-objs := \
10311055
hm2_rpspi-objs := \
10321056
hal/drivers/mesa-hostmot2/hm2_rpspi.o \
10331057
hal/drivers/mesa-hostmot2/llio_info.o \
1034-
hal/drivers/mesa-hostmot2/eshellf.o \
1058+
hal/drivers/mesa-hostmot2/kmod_check.o \
10351059
$(MATHSTUB)
10361060
hm2_spix-objs := \
10371061
hal/drivers/mesa-hostmot2/hm2_spix.o \
10381062
hal/drivers/mesa-hostmot2/spix_rpi5.o \
10391063
hal/drivers/mesa-hostmot2/spix_rpi3.o \
10401064
hal/drivers/mesa-hostmot2/spix_spidev.o \
10411065
hal/drivers/mesa-hostmot2/llio_info.o \
1042-
hal/drivers/mesa-hostmot2/eshellf.o \
1066+
hal/drivers/mesa-hostmot2/kmod_check.o \
10431067
$(MATHSTUB)
10441068
hm2_modbus-objs := \
10451069
hal/drivers/mesa-hostmot2/hm2_modbus.o \

src/hal/drivers/hal_evoreg.c

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -66,20 +66,9 @@
6666
#include <rtapi_ctype.h> /* isspace() */
6767
#include <rtapi.h> /* RTAPI realtime OS API */
6868
#include <rtapi_app.h> /* RTAPI realtime module decls */
69+
#include <rtapi_io.h> /* rtapi_inb(), rtapi_outb() */
6970
#include <hal.h> /* HAL public API decls */
7071

71-
/* If FASTIO is defined, uses outb() and inb() from <asm.io>,
72-
instead of rtapi_outb() and rtapi_inb() - the <asm.io> ones
73-
are inlined, and save a microsecond or two (on my 233MHz box)
74-
*/
75-
#define FASTIO
76-
77-
#ifdef FASTIO
78-
#define rtapi_inb inb
79-
#define rtapi_outb outb
80-
#include <asm/io.h>
81-
#endif
82-
8372
/* module information */
8473
MODULE_AUTHOR("Martin Kuhnle");
8574
MODULE_DESCRIPTION("SIEMENS-EVOREG Driver for EMC HAL");

src/hal/drivers/mesa-hostmot2/eshellf.c

Lines changed: 0 additions & 63 deletions
This file was deleted.

0 commit comments

Comments
 (0)