6

How do you allow non-root users to access I2C on the Raspberry Pi 2?

I've compiled this code for accessing an MPU6050 sensor via I2C, and it works perfectly, but only when I call it via sudo.

I tried adding the pi user to the spi and i2c groups, and adding udev rules as explained here and here, but even after rebooting, those had little effect. I can run /usr/sbin/i2cdetect as a non-root user, but the C code I2Cdev::initialize() still crashes if run without sudo.

This is documented in the underlying bcm2835 library:

If the library runs with any other effective UID (ie not root), then bcm2835_init() will attempt to open /dev/gpiomem, and, if successful, will only permit GPIO operations. In particular, bcm2835_spi_begin() and bcm2835_i2c_begin() will return false and all other non-gpio operations may fail silently or crash.

Is there any workaround for this? Even if I add the pi user to the root group, it still silently crashes.

1
  • 2
    In case you aren't familiar with the concept of "suid" ... we can change the permissions on a binary file such that when it runs, it will run as the effective userid of the user that owns the file. For example, if you have a program that needs to run as root but you don't want to give all your users full root access, you change the owner of the file to be root and then execute chmod u+s on the file. This means that when a "regular" user runs the program, the program will run "as root".
    – Kolban
    Jul 18, 2016 at 2:12

5 Answers 5

4

I think the bcm2835 C library is unique in being the only one which drives the I2C peripheral directly rather than using the Linux I2C driver.

This access was needed when the Pi first came out as there was no Linux I2C driver but nowadays it's a bit of an anachronism.

There is nothing stopping you using the standard driver from within the bcm2835 library - it's just standard device calls to /dev/i2c-0 and/or /dev/i2c-1. Using the standard calls might mean you can use bcm2835 without root privileges as long as the user is added to the i2c group.

2

I believe it only works when using sudo because you are accessing the bcm2835 directly and this requires elevated privileges.

If you use the linux i2c driver (sudo apt-get install i2c-tools will get you everything you need) then you can use device calls (which do not require elevated privileges). The code looks something like this:

    char *deviceName = (char*)"/dev/i2c-1";
    unsigned char bytesToSend[6] = {0,1,2,3,4,5};
    int bytes = 6;
    int i2cAddress = 0x3C;

    if ((i2cHandle = open(deviceName, O_RDWR)) < 0)
    {
        printf("error opening I2C\n");
    }
    else
    {
        if (ioctl(i2cHandle, I2C_SLAVE, i2cAddress) < 0)
        {
            printf("Error at ioctl\n");
        }
        else
        {
            write(i2cHandle, data, bytes);
        }

        // Close the i2c device bus
        close(*deviceName);
    }
1

As Kolban has mentioned, you can use the setuid bit; the example code there is about dropping the privileges at some point, so you do not have to actually add anything to use them, you just need to set the permissions on the compiled executable. You can do this as root or via sudo:

sudo chown root:root MPU6050_example_1
sudo chmod 4755 MPU6050_example_1

Note this won't work with a python or other script, but it will work with a compiled C++ program.

This is a theoretical security risk, although in this context not any more so than running the code sudo.

1

When I try to ls -l I2C devices, I see the group is i2c.

# ls -l /dev/i2c*
crw-rw---- 1 root i2c 89, 1 Mar 18 04:36 /dev/i2c-1

Therefor, I add my user to the group:

# usermod -a -G i2c ubuntu

Then, I exit and login again. And it is works.

By the way I using Ubuntu for Raspberry Pi with Ubuntu Server 20.04.2 LTS image.

3
  • This may be true, but doesn't answer the Question.
    – Milliways
    Jun 7, 2021 at 0:08
  • @Milliways Oops my bad, he already did it. Maybe something to do with I use Ubuntu instead of Raspberry Pi OS.
    – bayuah
    Jun 7, 2021 at 7:32
  • No. It has more to do with the difference between kernel drivers and direct hardware access.
    – Milliways
    Jun 7, 2021 at 7:43
-1

The user needs to be in the i2c group and the group members of file /dev/i2c-1 must have read and write permissions. If one of the two conditions is missing. It won t work.

Since we do not know if @Cerin changed the default permissions of the file.

Try changing permissions of the /dev/i2c-1 file. Grant read and write permission to the file owner and the group members (aka root user and members of i2c group.

sudo chmod 660 /dev/i2c-1
4
  • 1
    What's wrong with simply adding the user to the i2c group?
    – Dougie
    Aug 12, 2022 at 8:43
  • The user needs to be in the i2c group and the group members of file /dev/i2c-1 must have read and write permissions. If one of the two conditions is missing. It just won t work.
    – UserK
    Aug 12, 2022 at 8:48
  • Since we do not know if @Cerin changed the default permissions of the file. You must have both conditions. It simple logic in a context of scarcity of information and a world of wannabe hackers
    – UserK
    Aug 12, 2022 at 8:52
  • And by the way, 660 is not harming your system. My answer is adding value to a confused question topic. So I don t see any reason to downvote my answer.
    – UserK
    Aug 12, 2022 at 8:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.