Re: Running sndiod as user sndiod on Arch Linux

From: Alexandre Ratchov <alex_at_caoua.org>
Date: Mon Sep 18 2017 - 12:42:22 CEST
On Mon, Sep 18, 2017 at 09:44:35AM +0000, Edward Wandasiewicz wrote:
> Does the illustration below, explain why /usr/bin/sndiod is run as user "root"
> or a local user, and never as user "sndiod"?

Sure.

> 
> #
> # Lets have a look at the directories created in /tmp
> # when running sndiod as user { alison, root, sndiod }
> #
> 
> #
> # Run sndiod as user=alison with id 1000
> #
> 
> $ ls -la /tmp/aucat-1000
> total 0
> drwx------ 2 alison alison  60 Sep 18 08:10 .
> drwxrwxrwt 9 root   root   240 Sep 18 08:10 ..
> srw-rw-rw- 1 alison alison   0 Sep 18 08:10 aucat0
> 

this is OK, user alison gets its own daemon with its on private socket
thus only reachable by his own processes.

> #
> # Run sndiod as user=root
> #
> 
> $ ls -la /tmp
> drwxr-xr-x  2 root   root     60 Sep 18 08:55 aucat             # _MARK_1.0
> 
> $ ls -la /tmp/aucat
> total 0
> drwxr-xr-x 2 root root  60 Sep 18 08:18 .
> drwxrwxrwt 9 root root 220 Sep 18 08:18 ..
> srw-rw-rw- 1 root root   0 Sep 18 08:18 aucat0                  # _MARK_1.1
> 

this is OK as well, the dameon created (as root) a world
readable/searchable directory with a socket to which any local user
can connect. At this stage the ps utility should show the sndiod
process running as user 'sndiod' (even if it was started by root)
because root privileges are not needed anymore and the daemon has
changed its user-id to the unprivileged 'sndiod' user-id.

This way if the daemon is comprimised by a local attacker, he doesn't
get root permissions.

> #
> # Run sndiod as user=sndiod via systemctl and not "sudo -u sndiod"
> #
> # user sndiod is running "/usr/bin/sndiod -dd -f rsnd/1"
> #
> 

This is not the proper setup for the system daemon. Here, sndiod would
try to run as if 'sndiod' was a regular user, who would have its own
private daemon. Thus, only processes that belong to the 'sndiod' user
would be allowed to use it.

> $ sudo systemctl restart sndiod.service
> 
> $ ls -la /tmp
> drwx------  2 sndiod audio    60 Sep 18 08:22 aucat-991         # _MARK_2.0
>
> $ sudo ls -la /tmp/aucat-991/
> total 0
> drwx------ 2 sndiod audio  60 Sep 18 08:22 .
> drwxrwxrwt 9 root   root  220 Sep 18 08:22 ..
> srw-rw-rw- 1 sndiod audio   0 Sep 18 08:22 aucat0               # _MARK_2.1
> 

the socket belongs to the 'sndiod' user and is private (mode 0700,
owned by user 991)

> #
> # Run an strace on aucat as our local user
> #
> 
> $ strace aucat -f snd/0 -i /use/share/sounds/alsa/Side_Right.wav
> 

can't work as no local users except 991 (aka sndiod) are allowed to
connect to the private daemon.

> #
> # BINGO - file can't be opened
> #
> 
> connect(4, {sa_family=AF_UNIX, sun_path="/tmp/aucat-1000/aucat0"}, 110) = -1 ENOENT (No such file or directory)
> connect(4, {sa_family=AF_UNIX, sun_path="/tmp/aucat/aucat0"}, 110) = -1 ENOENT (No such file or directory)
> close(4)                                = 0
> write(2, "snd/0: couldn't open audio devic"..., 34snd/0: couldn't open audio device
> 

first, the client (aucat) tries to connect to its own daemon and then
to the system-shared daemon with no success (neither exists).

> #
> # Running sndiod as user sndiod, the local user never gets to open /tmp/aucat-991/aucat0
> # no wonder....
> # Lets try a symbolic link from /tmp/aucat to /tmp/aucat-991, and try an strace
> #
> 
> $ sudo ln -fs aucat-991 aucat
> 
> #
> # Run an strace with aucat symbolic linked to aucat-_ID_SNDIO_USER_
> #
> 
> $ strace aucat -f snd/0 -i /use/share/sounds/alsa/Side_Right.wav
> 
> connect(4, {sa_family=AF_UNIX, sun_path="/tmp/aucat-1000/aucat0"}, 110) = -1 ENOENT (No such file or directory)
> connect(4, {sa_family=AF_UNIX, sun_path="/tmp/aucat/aucat0"}, 110) = -1 EACCES (Permission denied)
> close(4)                                = 0
> write(2, "snd/0: couldn't open audio devic"..., 34snd/0: couldn't open audio device
> 
> #
> # What's different between running as root, and sndiod?
> # File aucat0 has the same properties, srw-rw-rw- , see above _MARK_1.1 & _MARK_2.1
> # Lets make _MARK_2.0 the same as _MARK_1.0
> #
> # Lets add {g, o} r+x permissions to /tmp/aucat-991
> # the same properties as /tmp/aucat - sndiod running as root
> # and add local users to the group audio
> #
> 
> $ sudo chmod g+rx aucat-991
> $ sudo chmod o+rx aucat-991
> 
> $ ls -la /tmp
> 
> drwxrw-rw-  2 sndiod audio    60 Sep 18 08:22 aucat-991
> 
> $ id
> 
> uid=1000(alison) gid=1000(alison) groups=1000(alison),10(wheel),990(audio)
> 
> #
> # Let's give it a go...
> #
> 
> $ strace aucat -f snd/0 -i /use/share/sounds/alsa/Side_Right.wav
> 
> connect(4, {sa_family=AF_UNIX, sun_path="/tmp/aucat-1000/aucat0"}, 110) = -1 ENOENT (No such file or directory)
> connect(4, {sa_family=AF_UNIX, sun_path="/tmp/aucat/aucat0"}, 110) = 0
> getuid()                                = 1000
> geteuid()                               = 1000
> getgid()                                = 1000
> getegid()                               = 1000
> openat(AT_FDCWD, "/home/alison/.aucat_cookie", O_RDONLY) = 5
> 
> #
> # WE HAVE LIFT OFF BABY!!!
> #

at this point the private socket is public and symlinked it to the
location of the shared socket. So any client manages to connect to it.

> 
> $ ls -la /tmp
> lrwxrwxrwx  1 root   root      9 Sep 18 09:12 aucat -> aucat-991
> drwxr-xr-x  2 sndiod audio    60 Sep 18 09:10 aucat-991
> 
> Question: Do we run systemctl sndiod.service as user "sndiod"

No. The system server must be started as root, the 'sndiod' is not
intended to be used directly.

> - where we would have to add an extra file to connect to - aucat of user sndiod
> - and amend it's directory properties accordingly, with +rx
> - and users would need to be a member of group audio
> 
> Question: or run systemctl sndiod.service as user "roor"
> 
> - no changes required
> 

As root. FWIW, I tried to play with systemd and ended with this
sndiod.service file. Maybe TimeoutSec could be lowered; not sure, yet.

[Unit]
Description=sndio audio and MIDI server
After=network.target

[Service]
Type=forking
Restart=on-abort
EnvironmentFile=-/etc/default/sndiod
ExecStart=/usr/bin/sndiod $DAEMON_OPTS

[Install]
WantedBy=multi-user.target
Received on Mon, 18 Sep 2017 12:42:22 +0200

This archive was generated by hypermail 2.1.8 : Wed Nov 08 2017 - 16:31:34 CET