clinuxaudioraspberry-pisudo

Set program permissions at runtime


I am trying to use a linux kernel module to do some hardware control on my raspberry pi. It's fairly trivial user-level code, but implementing some of the functionality as a kernel module is a necessary academic exercise. The kernel module sends a SIGIO signal to the user-level code on button press, which is output to a speaker connected to a breadboard using aplay. aplay connects to a pulseaudio server which (rightly) refuses to connect as root. How do I tell my program that I want to run this line of code as a regular user?

This is a rough skeleton based on the user-level code, not the kernel module.

/* various includes */

void main() {
    // stuff that requires sudo perms
    fd = open("/dev/manager", O_WRONLY);
    
    /* setup signal_handler() to handle signal from fd [omitted] */

    close(fd);
}

void signal_handler(int signo) {
    // None of this needs to be run with sudo privilege, and malfunctions if so
    setgid(1000); setuid(1000);        // see https://stackoverflow.com/questions/3357737/dropping-root-privileges
    setenv("HOME", "/home/raspi", 1);  // aplay uses $HOME, which was /root and inaccessible

    /* generate output.wav [omitted] */
    system("aplay /path/to/file/output.wav");
}

Here's a minimal compilable version of some sandbox code so that you can better reproduce the issue yourselves. It plays when run as a regular user, but not as sudo. If I can run the below as sudo, fixing the above code should become straightforward.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

void main() {
    setgid(1000);
    setuid(1000);
    setenv("HOME", "/home/raspi", 1);
    system("aplay /path/to/file/output.wav");
}

I'm not even attached at the hip to aplay. If someone can give me any minimal working example of audio playing from a C program when run as sudo using whatever audio utility you have on hand, I'd love to see it.

Related Questions: [1] Dropping root privileges - This almost answers my question. This should answer my question. It just didn't actually work when I tried it. [2] sudo permission problems in c program - I am aware of what needs sudo and what doesn't need sudo here. What I'm unclear on is how to switch from one to the other at runtime.


Solution

  • Prefaced by the top comments ...

    @CraigEstey sudo chmod 666 /dev/manager did the trick! I'm crying tears of joy thank you so much! Do you want to make an answer post for this? – PR4v1

    While we need sudo to do things like insmod/modprobe, we don't need it to invoke your program.

    1. The only reason we need sudo is because your program opens /dev/manager. It is [probably] owned by root and has permission of (e.g.) 600 or 644.
    2. Since /dev/manager is strictly for your device driver, we can set the ownership and/or permissions to any values we want.
    3. There's little harm to having the device file be world writable. That is, we do want any user to be able to play audio, don't we?

    If we do either of the following your program does not need to run as root:

    1. chown raspi: /dev/manager
    2. chmod 666 /dev/manager (preferred).

    Thus, aplay will be run as a non-root user (and it will no longer complain about being root).