Package: halevt Version: 0.1.6.2-1 Severity: normal Tags: patch
It appears that halevt does not setup supplemental groups (i.e., doesn't call initgroups) when changing ids to a non-root user. This means that the halevt daemon does not have permission to access files/devices owned by a group for which user "halevt" is a member, but are not owned by user "halevt" or group "plugdev" themselves. As a motivating example, I have a halevt rule that toggles my sound mixer's mute setting on a "mute button" hotkey keypress. Access to /dev/snd/controlC0 via amixer requires that the user be a member of group "audio", which on my system user "halevt" is. In this case, it wouldn't make sense to change ownership of the mixer device to either halevt or plugdev, as other applications (used with group audio membership) access the mixer device. Running halevt under group audio would work, but is a heavy-handed approach that might not be appropriate in all situations. As it turns out this bug is a regression. Although halevt itself never called initgroups, the Debian halevt init.d script in version 0.1.5-4 and below ran halevt as a non-root user via start-stop-daemon's -c and -g options, and thus the "change id" code in halevt itself was always bypassed. It's unclear from the changelog why the "change id" responsibility was shifted from start-stop-daemon to halevt. Personally I find the former to be strategic from a security perspective--that is, leave the privileged operations solely to a well trusted program (start-stop-daemon) since halevt itself does not need root privileges except to change users. In any event, if the change to have halevt switch users itself is intended, then attached is a patch which adds the appropriate initgroups call to halevt. I've tested it, and it works well to fix the problem. Thanks!
diff --git a/src/manager.c b/src/manager.c --- a/src/manager.c +++ b/src/manager.c @@ -331,6 +331,11 @@ DEBUG(_("Error setting gid to %u: %s"), gid, strerror(errno)); exit(1); } + if (initgroups(user, gid) != 0) + { + DEBUG(_("Error setting initgroups for %s, %u: %s"), user, gid, strerror(errno)); + exit(1); + } if (setuid(uid) != 0) { DEBUG(_("Error setting uid to %u: %s"), uid, strerror(errno));