Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Library segfaults when not running as root on Raspberry Pi #424

Closed
paulirwin opened this issue Apr 5, 2018 · 4 comments
Closed

Library segfaults when not running as root on Raspberry Pi #424

paulirwin opened this issue Apr 5, 2018 · 4 comments

Comments

@paulirwin
Copy link

paulirwin commented Apr 5, 2018

I assume this affects other Linux distros besides Raspbian on the Pi, but I haven't tested it as I don't have a Linux device with GPIO/SPI handy. This was encountered on the latest version of Raspbian on the Pi 3.

The library (including all of its examples) does not work on the Pi unless you're running as root/su, which may be common knowledge, but it is not mentioned in the RPi documentation page. It is subtly shown to use sudo on the Linux documentation page but I did not discover this until after I found the solution to the problem. Also I was not the only one that had this problem.

The result of running it as non-root on the Raspberry Pi is a segfault, which is extremely user-unfriendly. Ideally, the library should detect if SPI is unavailable and throw a meaningful exception.

It appears from the code comments here that this should be as simple as checking the return value for zero here. I am not a C++ expert but I think I can try my hand at submitting a PR for this, I just wanted to go ahead and get an issue logged in case someone had a better solution in the meantime. Also, the RPi documentation should probably be updated with this requirement.

@akatran
Copy link
Contributor

akatran commented Apr 15, 2018

Maybe someone with more knowledge could help on this.

Debugging the library (non root user) I saw something that it is does not looks good.

This is a backtrace of the failing function ....

#0  bcm2835_peri_read (paddr=paddr@entry=**0xffffffff**) at utility/RPi/bcm2835.c:124
#1  0x76fa5cf8 in bcm2835_peri_set_bits (paddr=**0xffffffff**, value=0, mask=12) at utility/RPi/bcm2835.c:195
#2  0x76fa5a9c in SPI::beginTransaction (settings=...) at utility/RPi/spi.cpp:23
#3  0x76fa3d88 in beginTransaction (this=0x24318 <radio>) at RF24.cpp:70
#4  RF24::write_register (this=this@entry=0x24318 <radio>, reg=reg@entry=0 '\000', value=value@entry=12 '\f') at RF24.cpp:194
#5  0x76fa5890 in RF24::begin (this=0x24318 <radio>) at RF24.cpp:638
#6  0x76f6d5a8 in RF24Mesh::begin(unsigned char, rf24_datarate_e, unsigned int) () from /usr/local/lib/librf24mesh.so.1
#7  0x76f5828c in RF24Gateway::begin(bool, bool, unsigned short, unsigned char, rf24_datarate_e, unsigned char) () from /usr/local/lib/librf24gateway.so.1
#8  0x76f58114 in RF24Gateway::begin(unsigned char, unsigned char, rf24_datarate_e) () from /usr/local/lib/librf24gateway.so.1
#9  0x00012c74 in main ()

At the first two function calls the paddr is 0xffffffff which does not seems to be right.

Even if there is no alternative to find if the SPI or the bcm can access the hardware, it can easily detected from paddr.

@akatran
Copy link
Contributor

akatran commented Apr 15, 2018

While digging...

(gdb) print bcm2835_spi0
$24 = (volatile uint32_t *) 0xffffffff

From the code we see

/*! Base of the SPI0 registers.
  Available after bcm2835_init has been called (as root)
*/as root
extern volatile uint32_t *bcm2835_spi0;

So either check after bcm2835_init for root access or address 0xffffffff of bcm2835_spi0 instead of a segmentation fault!

@akatran
Copy link
Contributor

akatran commented Apr 19, 2018

As the bcm2835 could not initialize the spi0 because of privileges we could make a check if we actually have root access.
As SPI is not available the radio functions will not work so the program will not run.
Instead of having a segmentation fault we could just print a "Root access required" message and exit.

The best place to put the check is

3 0x76fa3d88 in beginTransaction (this=0x24318 ) at RF24.cpp:70

We can easily detect root access there with something like :

  inline void RF24::beginTransaction() {
    #if defined (RF24_SPI_TRANSACTIONS)
    if (geteuid() == 0){
        _SPI.beginTransaction(SPISettings(RF24_SPI_SPEED, MSBFIRST, SPI_MODE0));
    }else{
        fprintf(stderr, "Root access required!\n") ;
        exit(-1);
    }
    #endif
    csn(LOW);
  }

@akatran
Copy link
Contributor

akatran commented Apr 19, 2018

I'm going to create a PR for that!

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

No branches or pull requests

3 participants