Re: [Jack-Devel] su, limits, PAM and JACK

PrevNext  Index
DateTue, 22 May 2012 23:09:49 +0000
From Jamie Heilman <[hidden] at audible dot transient dot net>
ToRobin Gareus <[hidden] at gareus dot org>
CcJACK Mailing List <[hidden] at lists dot jackaudio dot org>
In-Reply-ToRobin Gareus [Jack-Devel] su, limits, PAM and JACK
Follow-UpRobin Gareus Re: [Jack-Devel] su, limits, PAM and JACK
Follow-UpJeremy Henty Re: [Jack-Devel] su, limits, PAM and JACK
Robin Gareus wrote:
> Hya,
> 
> This is somewhat off-topic, but I think someone here may know the answer.
> 
> For an installation, I'm trying to start jackd during boot on a headless
> box, but it fails to acquire real-time privileges.
> 
> 'user' is in the audio group, and limits.conf is set up. All works fine
> if I log-in as 'user' and launch `jackd -d alsa ..` manually.
> 
> If I log in as root (or call it from init):
> 
>   su user -c 'jackd ..'     # fails -> no rt priv
>   su user -l -c 'jackd ..'  # fails -> no rt priv
> 
> the actual error message from jack is
>   Cannot use real-time scheduling (RR/10)(1: Operation not permitted)
> 
> If I change /etc/pam.d/su and add (or un-comment)
> "session    required   pam_limits.so"
> 
>   su user -l -c 'jackd ..'  # works now (also from init on boot.)
> 
> Well. Next step is to not use 'su' but proper POSIX setgid(), setuid().
> Alas, I seem to miss some crucial step that sets up the proper limits
> after calling setuid().

Chances are your PAM stack isn't configured to use pam_limits.so for
su sessions, which means using su won't pay any attention to the
setttings in limits.conf until it is.  That said, don't do that.
Using su programatically to switch users is a bad idea becuase su's
behavior is notoriously unportable anyway.

> Any idea what that may be?

I run jackd on boot on headless virtuals, and I use Gerrit Pape's
daemontools-a-like runit to do it.  That said, the recipe is the more
or less the same regardless of technique.  My jackd-net/run script is:

#!/bin/bash
exec 2>&1
ulimit -l unlimited -r 95       # XXX ulimit -r is a bashism
exec chpst -u jackd jackd -d net -a 0 -i 0 -o 2 -I 0 -O 0

That script is run as superuser, so that breaks down into:

1) allow unlimited bytes to be locked into memory
2) allow a maximum real-time scheduling priority of 95
3) switch group to audio (implied because the jackd user's primary
   group is audio on this system) then switch user to jackd. (chpst is
   part of runit)

> Run the following as root from a console (don't use sudo or su to
> acquire root priv) to reproduce the problem:
> 
> #!/usr/bin/perl
> use POSIX qw(setuid setgid);
> my ($login,$pass,$uid,$gid) = getpwnam('user');
> my $audiog  = getgrnam('audio');
> setgid($audiog);
> setuid($uid);
> print `id`; # shows the UID and GID just fine
> system('jackd -d alsa -d hw:1');
> # Cannot use real-time scheduling (RR/10)(1: Operation not permitted)
> # Aarrrrg!
> # help please

Right, your perl script is missing two calls to setrlimit(2) for
RLIMIT_RTPRIO and RLIMIT_MEMLOCK.  afaik there's no native wrapper for
setrlimit in perl though, so you'll probably have to install
BSD::Resource and use that or something similar.  Or call your perl
script from a bash script that does the above ulimit first.

Normally I would never write bash-specific shell, because while bash
is a fine login shell, it's a bloated horror and a lousy replacement
for /bin/sh ... but unfortunately bash's builtin ulimit is one of only
that I know supports setting RLIMIT_RTPRIO.

-- 
Jamie Heilman                     http://audible.transient.net/~jamie/
PrevNext  Index

1337728198.26789_0.ltw:2, <20120522230948.GA18937 at cucamonga dot audible dot transient dot net>