Raspberry Pi acces to /dev/mem using PREEMPT_RT

More
01 Jan 2017 13:18 #85004 by DaBit
I am currently building a 3D printer from the ground up.
To control it, I intend to use a Raspberry Pi 3 with either LinuxCNC or MachineKit. Why? Because I can.
So far I am using LinuxCNC; it is a comfortable environment and I am not yet sure what benefits MachineKit would offer over LinuxCNC. Once things are working I will try it, but until then I will stick to LinuxCNC.

Now, to drive stepper motors I attached ST Microelectronics dSpin/L6470 chips. These are real beauties; they communicate with SPI, they incorporate a trapezoidal motion planner, and the 128-ustep voltage-mode driving they use makes the motor REALLY silent. There is also a bigger brother called powerSTEP01 which is capable of 80V/10Amp and either voltage-mode driving or current-mode, so I am seeing potential in those chips even beyond a humble 3D printer.



Now, I wrote a module that communicates with the chips using bit-banged SPI. The Raspberry can toggle it's I/O faster than the L6470's can accept anyway, those chips need a pulse on the chip select every byte, and I like to keep the hardware SPI free for other purposes.

To access the GPIO I used a part of the WiringPi library, which needs access to /dev/mem to be able to map the SoC registers. To gain that access, I took a piece of code from hm2_rpspi.c

The code that does that is:
/* Taken from hm2_rpspi.c */
int rtapi_open_as_root(const char *filename, int mode) {
        fprintf (stderr, "euid: %d uid: %d\n", geteuid(), getuid());
	setfsuid(geteuid());
	int r = open(filename, mode);
	setfsuid(getuid());
	return r;
}

int gpioInitialise(void)
{
   int fd;

   gpioHardwareRevision(); /* sets piModel, needed for peripherals address */

   fd = rtapi_open_as_root("/dev/mem", O_RDWR | O_SYNC) ;

   if (fd < 0)
   {
      fprintf(stderr,
         "Connot open /dev/mem. This program needs root privileges.  Try using sudo\n");
      return -1;
   }

   gpioReg  = initMapMem(fd, GPIO_BASE,  GPIO_LEN);
   systReg  = initMapMem(fd, SYST_BASE,  SYST_LEN);
   bscsReg  = initMapMem(fd, BSCS_BASE,  BSCS_LEN);

   close(fd);

// and some more..

Full code can be found here: github.com/dabit20
(but it is still very much in an 'under construction / barely working' state)

Now, I started to develop this on a few months old Rasbian install with kernel from www.frank-durr.de/?p=203.
This worked fine.

Recently I decided I would do a fresh Raspbian install on a faster and larger SD card. The 'old' image is a bit polluted due to tinkering with many things and the kernel mentioned above does not support the onboard WiFi on the Pi3. So I took a fresh Raspbian install, the raspbian kernel sources, applied RT patches from kernel.org and configured the kernel for realtime.

4.4.39-rt49 kernel works fine, latency is very acceptable for a servo-only system:


But no access to /dev/mem from within a LinuxCNC module :angry:

I tried a lot of things, and at the moment I ended up with:
- The original 8GB card with 4.4.9-rt17 kernel from frank-durr.de, LinuxCNC 2.7.7 compiled for uspace.
- A new 32GB card with fresh Raspbian Jessie, the very same 4.4.9-rt17 kernel and the very same LinuxCNC 2.7.7 as on the 8GB card (I copied the linuxcnc-dev tree from the 8GB card).

On both cards linuxcnc-dev/bin/rtapi_app has the permissions changed by sudo make setuid:
pi@raspberrypi:~/linuxcnc-dev/bin $ ls -al rtapi*
-rwsr-x--- 1 root pi 524360 Oct 20 11:27 rtapi_app

In the end it seems to be a uid/permission issue.
On the 8GB SD card:
pi@raspberrypi:~/rpi_cnc/linuxcnc_modules $ uname -a
Linux raspberrypi 4.4.9-rt17-v7+ #1 SMP PREEMPT RT Wed May 11 22:46:14 CEST 2016 armv7l GNU/Linux
pi@raspberrypi:~/rpi_cnc/linuxcnc_modules $ halrun -I dspin_test.hal 
Note: Using POSIX realtime
loading dspin module
euid: 0 uid: 1000
joint 0 config register: 2e88
halcmd: quit
dSpin module unloaded
Note: Using POSIX realtime
pi@raspberrypi:~/rpi_cnc/linuxcnc_modules $

EUID=0, UID=1000 (which is user 'pi'). so I can see it working.

On the new 32GB card:
pi@raspberrypi:~/rpi_cnc/linuxcnc_modules $ uname -a
Linux raspberrypi 4.4.9-rt17-v7+ #1 SMP PREEMPT RT Wed May 11 22:46:14 CEST 2016 armv7l GNU/Linux
pi@raspberrypi:~/rpi_cnc/linuxcnc_modules $ halrun -I dspin_test.hal 
Note: Using POSIX realtime
loading dspin module
euid: 1000 uid 1000
This program needs root privileges.  Try using sudo
GPIO initialise went wrong
rtapi_app: caught signal 11 - dumping core
dspin_test.hal:2: waitpid failed /home/pi/linuxcnc-dev/bin/rtapi_app dspin

dspin_test.hal:2: /home/pi/linuxcnc-dev/bin/rtapi_app exited without becoming ready
dspin_test.hal:2: insmod for dspin failed, returned -1
halcmd: quit
Waited 3 seconds for master.  giving up.
Note: Using POSIX realtime
pi@raspberrypi:~/rpi_cnc/linuxcnc_modules $

Both EUID and UID are 1000, and opening /dev/mem fails (as it should).

I am pretty sure this is more a Linux problem than a LinuxCNC problem, but I have no idea where to search for a solution.

Please Log in or Create an account to join the conversation.

More
01 Jan 2017 14:13 - 01 Jan 2017 14:13 #85009 by DaBit
Adding a call to seteuid() seems to work:
/* Taken from hm2_rpspi.c */
int rtapi_open_as_root(const char *filename, int mode) {
	fprintf (stderr, "euid: %d uid %d\n", geteuid(), getuid());
	seteuid(0);
	fprintf (stderr, "euid: %d uid %d\n", geteuid(), getuid());
	setfsuid(geteuid());
	int r = open(filename, mode);
	setfsuid(getuid());
	return r;
}

Result:
pi@raspberrypi:~/rpi_cnc/linuxcnc_modules $ halcompile --install dspin.c 
Compiling realtime dspin.c
Linking dspin.so
cp dspin.so /home/pi/linuxcnc-dev/rtlib/
pi@raspberrypi:~/rpi_cnc/linuxcnc_modules $ halrun -I dspin_test.hal 
Note: Using POSIX realtime
loading dspin module
euid: 1000 uid 1000
euid: 0 uid 1000
joint 0 config register: 2e88
halcmd: halscope: config file 'autosave.halscope' could not be opened

halcmd: quit
dSpin module unloaded
Note: Using POSIX realtime
pi@raspberrypi:~/rpi_cnc/linuxcnc_modules $

But to be honest I nave no clue what I am doing.
As far as I know, the EUID of an executable with the setuid bit enabled is that of the owner of the file. It should already be 0 since root is the owner. The fact that the seteuid() call succeeds proves this:

SETEUID(2) Linux Programmer's Manual SETEUID(2)

NAME
seteuid, setegid - set effective user or group ID
..
..
DESCRIPTION
seteuid() sets the effective user ID of the calling process. Unprivi‐
leged user processes may only set the effective user ID to the real
user ID, the effective user ID or the saved set-user-ID.



Raspbian bug? Or stupid user?
Last edit: 01 Jan 2017 14:13 by DaBit.

Please Log in or Create an account to join the conversation.

Time to create page: 0.116 seconds
Powered by Kunena Forum