2

I'm trying to indirectly run VLC media player on Linux from a program that runs as root (i.e. sudo ./capture). After running into some error codes that VLC doesn't run as root, I attempted to de-escalate the program's privileges before running, as such

setuid(1000);
setgid(1000);
putenv("HOME=/home/musicman");
putenv("LOGNAME=musicman");
putenv("USER=musicman");
putenv("DISPLAY=:0");
putenv("DESKTOP_SESSION=plasma");
    
printf("Running args: ");
char* ARGS2[] = {"cvlc", "file:///home/musicman/bad_apple.mp3", "vlc://quit", NULL};
for (int i = 0; i < 3; i++)
{
    printf("'%s' ", ARGS2[i]);
}
printf("\n");
execvp(ARGS2[0], ARGS2);

Now, while the intermediary python program runs fine, VLC itself generates the following errors:

Running args: 'cvlc' 'file:///home/musicman/bad_apple.mp3' 'vlc://quit' 
VLC media player 3.0.12 Vetinari (revision 3.0.12-1-0-gd147bb5e7e)
[0000557de32b32c0] vlcpulse audio output error: PulseAudio server connection failure: Connection refused
[0000557de3354f70] dummy interface: using the dummy interface module...
ALSA lib pcm_dmix.c:1075:(snd_pcm_dmix_open) unable to open slave
[0000557de32b32c0] alsa audio output error: cannot open ALSA device "default": Device or resource busy
[0000557de32b32c0] main audio output error: Audio output failed
[0000557de32b32c0] main audio output error: The audio device "default" could not be used:
Device or resource busy.
[0000557de32b32c0] main audio output error: module not functional
[00007f5094c48220] main decoder error: failed to create audio output

However, if I just run the following code without sudo

char* ARGS2[] = {"cvlc", "file:///home/musicman/bad_apple.mp3", "vlc://quit", NULL};
printf("Running args: ");
for (int i = 0; i < 3; i++)
{
    printf("'%s' ", ARGS2[i]);
}
printf("\n");
execvp(ARGS2[0], ARGS2);

I get the following output:

Running args: 'cvlc' 'file:///home/musicman/bad_apple.mp3' 'vlc://quit' 
VLC media player 3.0.12 Vetinari (revision 3.0.12-1-0-gd147bb5e7e)
[00005570414ddd00] dummy interface: using the dummy interface module...

...and the song plays. I suspect that, for some reason, PulseAudio is relying on some environmental variables that I'm not providing, but I'm really not sure what I'm missing, as running env | egrep "^PULSE" reveals nothing. Do any of you have ideas?

I'm running on Kubuntu 21.04 with an X11 session and pulseaudio 14.2.

tink
  • 14,342
  • 4
  • 46
  • 50
MusicMan
  • 134
  • 9
  • Can you open a terminal without doing sudo, run the command `env`, and see if you have any [pulseaudio related environment variables](https://www.freedesktop.org/wiki/Software/PulseAudio/FAQ/#whatenvironmentvariablesdoespulseaudiocareabout) or the variable `$DISPLAY` set? – Nick ODell Aug 07 '21 at 18:41
  • 1
    Running `env | egrep "^PULSE"` returns nothing. `env | egrep "DISPLAY"` returns `DISPLAY=:0`, which is pretty much what I have set above. – MusicMan Aug 07 '21 at 18:46
  • 2
    Silly question - why the need to run musicman's music as root? What problem are you trying to solve? – tink Aug 07 '21 at 18:56
  • No, I sort of expected that to come. Essentially, I have a program that lets me search for and run music files from the command line. What I want to do is trigger that program without opening up the command line (i.e., running my "battle" playlist within Halo without minimizing the game). To accomplish this, I made a keylogger program that will detect keyboard input from /dev/input/event5 no matter that window I'm focused on. However, the keylogger must run as root in order to gain access to /dev/input. – MusicMan Aug 07 '21 at 19:00
  • That said, if anyone has an alternative solution, I am open (I tried the pynput python module already, but that seemed to cause my Plasma session to crash at random intervals, so I decided to avoid that one). – MusicMan Aug 07 '21 at 19:10
  • @MusicMan most systems make the input devices readable/writable by anyone in a certain group, e.g. `input`. You could simply add yourself to that group. If yours doesn't do that, you can tweak the udev rules so that it does. – hobbs Aug 07 '21 at 19:46
  • Right, I just added myself to the inputs group and logged back in, and my program seems to work fine. I'll look into udev rules so that not just any program can become a keylogger, but other than that, my immediate problem is solved. Thanks, @hobbs. – MusicMan Aug 07 '21 at 19:58
  • Glad you're on a way to resolution. And showing my utter ignorance here, but does that gaming environment override all of your WM/DE's keybindings? If it doesn't, why didn't you just tap into that, and create custom-key bindings from there? – tink Aug 07 '21 at 20:01
  • Btw, while you're not seeing [that error](https://www.freedesktop.org/wiki/Software/PulseAudio/FAQ/#igetthiserrormessage:accessdenied) I think the information provided there is relevant to your problem (w/o having tested any of this, of course, it's just a hunch). – tink Aug 07 '21 at 20:07
  • My main goal is to capture key input regardless of what has focus. Tapping into the /dev/input devices and using the library seemed like the easiest way to accomplish this. However, I'm not very familiar with writing applications that tap into Linux's lower-level API and such, so if there is a better way of doing this, I'm very much interested. – MusicMan Aug 07 '21 at 20:09
  • Shouldn't `cvlc` behave **exaclty** like being run without `sudo` if it's called by a program/script (run as root) that sets the USID/GUID and all relevant environment variables? – Jardel Lucca Aug 07 '21 at 20:17
  • About your error, @tink, I checked and my user home does seem to be properly mapped to /home/musicman. Furthermore, I reinforced this by setting PULSE_COOKIE to /home/musicman/.config/pulse/cookie, and I still got the same error as above. Of course, the actual error message does indicate that pulseaudio is not running in a way that my de-escalated application can access. This is weird, since, between the setid functions and the putenv variables, I should be running within musicman's user space just like any other program. – MusicMan Aug 07 '21 at 20:17
  • I'm a systems guy, so never tried to experiment with any of the kinky stuff you're doing here, but my understanding is that pulse is tied to a user running an active logged in session; which means that tapping into the WM/DE's hotkkeys should suffice. Binding to `/dev/input` should be required only if you expect it to also work if there's no X running at all. What Gooey environment are you working with? – tink Aug 07 '21 at 20:20
  • 1
    @JardelLucca that is the idea. However, there seems to be something unusual going on with the pulseaudio connection. In my main program, I call VLC indirectly by executing a Python program that does additional processing before that python program calls VLC, and the Python program doesn't seem to behave any differently aside from a weird error with the argument strings I'm passing (unrelated, I'm pretty sure). However, for some reason, if the program starts at root, VLC just can't hook up with pulseaudio (or alsa, for that matter). – MusicMan Aug 07 '21 at 20:20
  • @tink I'm using KDE Plasma 5.21.4 with Qt version 5.15.2 running on X11. Don't worry, I'm not experienced in these matters myself. I usually just make Java Swing applications or processing files with Python and Bash. – MusicMan Aug 07 '21 at 20:21
  • Have you investigated the possibility of using KDE Keybindings for your purposes? – tink Aug 07 '21 at 20:22
  • 1
    @tink I didn't really know that was a thing. I'll start researching it now. – MusicMan Aug 07 '21 at 20:23
  • Key, @tink, when you were talking about KDE keybindings, did you mean predefined keyboard shortcuts like Alt+F1 to open help or something like that? I so, that wasn't what I was looking for. What I need to do is capture arbitrary keystrokes to build up a list of search terms. So, if the user triggers the program and types in the letters "doom gate" and presses enter, the program will then search my file system for songs that contain the terms "doom" or "gate" before playing matching files in the background, all without triggering any GUI or changing window focus. Sorry if I wasn't clear. – MusicMan Aug 07 '21 at 20:48
  • Oh, right. Sorry, no, I didn't realise you were after complex sequences. – tink Aug 07 '21 at 21:37

3 Answers3

2

At the end of the day, my primary issue was trying to run a keylogger and VLC in the same process. At @hobbs suggestion, I just added my user to Linux's inputs user group, allowing me to run the keylogger in the user space. The final program was uploaded by my partner to GitHub.

That said, if anyone does come up with an answer to the original question, I will mark that as the correct answer for anyone who comes across a similar situation that can't be side-stepped like my problem was.

MusicMan
  • 134
  • 9
0

Whether any of this is germane to your issue, I don't know but pulseaudio is not designed to run as root.

Expect to see something like the following:

E: [pulseaudio] core-util.c: Home directory not accessible: Permission denied
W: [pulseaudio] main.c: This program is not intended to be run as root (unless --system is specified).
E: [autospawn] core-util.c: Home directory not accessible: Permission denied
W: [autospawn] lock-autospawn.c: Cannot access autospawn lock.
E: [pulseaudio] main.c: Failed to acquire autospawn lock
Home directory not accessible: Permission denied
Connection failure: Connection refused
pa_context_connect() failed: Connection refused
Home directory not accessible: Permission denied

There are ways (optional parameters) around it but they're not recommended.

Specifically:

--system[=BOOL]
              Run as system-wide instance instead  of  per-user.  Please  note
              that  this disables certain features of PulseAudio and is gener‐
              ally not recommended unless the  system  knows  no  local  users
              (e.g.  is  a thin client). This feature needs special configura‐
              tion and a dedicated UNIX user set up. It is highly  recommended
              to combine this with --disallow-module-loading (see below).


--disallow-module-loading[=BOOL]
          Disallow  module  loading after startup. This is a security fea‐
          ture since it disallows additional module loading during runtime
          and  on  user request. It is highly recommended when --system is
          used (see above). Note however, that this  breaks  certain  fea‐
          tures like automatic module loading on hot plug.

Additionally, pulseaudio expects to be able to access a default.pa file, which would normally be found in $HOME/.config/pulse.
There may be issues with that too, if running as root.

Rolf of Saxony
  • 21,661
  • 5
  • 39
  • 60
  • I did figure out this much, hence why I tried de-escalating my user privileges back to that of user 1000 before running VLC and setting the user home to /home/musicman. However, there doesn't seem to be an effect even after doing this. – MusicMan Aug 09 '21 at 13:46
  • @MusicMan In which case I assume you have read: https://www.freedesktop.org/wiki/Software/PulseAudio/Documentation/User/WhatIsWrongWithSystemWide/ and https://www.freedesktop.org/wiki/Software/PulseAudio/Documentation/User/SystemWide/ – Rolf of Saxony Aug 09 '21 at 17:13
0

I had the same exact problem, and was able to solve by setting the XDG_RUNTIME_DIR environment variable to my user's one (which for the records is /run/user/1000).

No idea why, and indeed that is not mentioned in the list of relevant environment variables... but another FAQ does refer to it. I just found out by trying to add all environment variables one by one until it worked.

Pietro Battiston
  • 7,930
  • 3
  • 42
  • 45