Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature Request: Logind conditional #4603

Closed
crocket opened this issue Oct 13, 2021 · 21 comments
Closed

Feature Request: Logind conditional #4603

crocket opened this issue Oct 13, 2021 · 21 comments
Labels
enhancement New feature request

Comments

@crocket
Copy link
Contributor

crocket commented Oct 13, 2021

Is your feature request related to a problem? Please describe.

(e)udev attaches uaccess tag to devices.
systemd-logind and elogind grant logged-in users rights to devices with uaccess tag.
With logind, noroot and nogroups don't break device access.
Without logind, noroot or nogroups may break device access.

Some linux distributions like Void Linux and Gentoo Linux allow users to replace logind with other seat managers like seatd.

Describe the solution you'd like

To support all linux distributions and all seat managers without any manual user configuration, a logind conditional like ?SEAT-ACL is desirable. Then,

noroot
nogroups

can be replaced with

?SEAT-ACL: noroot
?SEAT-ACL: nogroups
@crocket crocket changed the title Logind conditional Feature Request: Logind conditional Oct 13, 2021
@rusty-snake
Copy link
Collaborator

?SEAT-ACL: noroot
?SEAT-ACL: nogroups

Would require maintaining that they are always behind a condition. I would prefer a more implicit solution.


Previous discussions: #4600, #4531, #4602
Related issues: #3711, #841, #3303, #2042

@rusty-snake rusty-snake added the enhancement New feature request label Oct 13, 2021
@crocket
Copy link
Contributor Author

crocket commented Oct 13, 2021

noroot-if-seat-acl and nogroups-if-seat-acl?

Or, noroot and nogroups kick in only if seat-acl is present.

@smitsohu
Copy link
Collaborator

smitsohu commented Oct 13, 2021

Quoting @crocket from #4600

There can be better ways to manage permission than noroot and nogroups. I read about a
discussion of fine-grained control over access to supplementary groups.

To me this sounds more useful than a conditional alone. And once facilities are in place, they could also be exposed in firejail.config, so that users, and maybe distributions, find it easier to adapt firejail to their setup.

Edit to clarify: I was referring to something like #2042

@topimiettinen
Copy link
Collaborator

@smitsohu Let's say fine-grained group control means something like groups.drop sudo (black/denylist) and groups.keep audio (white/allowlist). The case for local admin is clear, maybe also for distros, but how could we use them in upstream profiles? Maybe just commented out as examples?

@smitsohu
Copy link
Collaborator

@topimiettinen Right. This kind of fine grained control (groups.drop) won't be very helpful for upstream profiles. I was thinking from the perspective of an administrator, but a more dynamic solution would be clearly better.

@kmk3
Copy link
Collaborator

kmk3 commented Oct 15, 2021

@topimiettinen commented on Oct 14:

@smitsohu Let's say fine-grained group control means something like
groups.drop sudo (black/denylist) and groups.keep audio
(white/allowlist). The case for local admin is clear, maybe also for distros,
but how could we use them in upstream profiles? Maybe just commented out as
examples?

@smitsohu commented on Oct 14:

@topimiettinen Right. This kind of fine grained control (groups.drop) won't
be very helpful for upstream profiles. I was thinking from the perspective of
an administrator, but a more dynamic solution would be clearly better.

Considering groups.keep being more desirable than ?SET_FACL, that there is
a working implementation of the former and assuming that the audio group (if
any) is called "audio" on basically every distro that has firejail (would have
to check this one):

If a program requires audio output (e.g.: mpv), would there be any downside in
replacing nogroups with e.g.: groups.keep audio in its profile?

On distros that default to systemd/pulseaudio, are new users added to an audio
group by default? If not, I think that @topimiettinen's multi-seat
concern
would not apply, as the user would have to be deliberately added to
such a group. As in, I think that this responsibility would fall on the user
rather than on firejail (though we could document it of course).

Also, if there are more things needed to unblock (e.g.: specific device files)
other than the group, maybe there could be an include like the following:

allow-audio.inc:

ignore nogroups

# alsa
noblacklist /dev/snd/*

# sndio
noblacklist /dev/audio*
noblacklist /dev/midi*

groups.keep audio

That is, adding include allow-audio.inc to relevant profiles rather than
replacing nogroups with groups.keep audio on them.

Overriding the above (in e.g.: allow-audio.local) would also permit allowing
only specific devices rather than every audio device, which would be even more
granular than just groups.keep. Example:

ignore noblacklist /dev/audio*

noblacklist /dev/audio3

write-only /dev/audio3

Note: There is currently no write-only, but having something like the above
looks like it could also effectively fix the following issue:

And if someone would like to avoid allowing any groups at all, then something
like ignore include allow-audio.inc (or ignore ignore nogroups) could be
added to globals.local.

@crocket
Copy link
Contributor Author

crocket commented Oct 15, 2021

It doesn't make much sense to put ignore nogroups in allow-audio.inc if allow-audio.inc is included in main profiles.

You should just remove nogroups.

Adding more stuff to counteract existing stuff is counterproductive. We should remove lines instead.

If we keep adding stuff without eliminating lines, we may end up with something like ignore ignore ignore nogroups

@rusty-snake
Copy link
Collaborator

rusty-snake commented Oct 15, 2021

If we keep adding stuff without eliminating lines, we may end up with something like ignore ignore ignore nogroups

ignore nogroups is enough.


What about nogroups <all|auto|none>?

  • nogroups all (and alias nogroups for backward compatibility) will drop all supplementary groups. (and noroot will not change groups noroot removes all user groups, nogroups redundant #3303)
  • nogroups none will keep all groups (maybe we don't need this as it is the same as not using nogroups and just complicates things)
  • nogroups auto will autodetect which groups it should keep (whitelisting)
    if !arg_nosound:
        drop_group("audio")
    if !arg_novideo:
        drop_group("video")
    if !arg_nodvd:
        drop_group("cdrom")
    if !arg_noinput:
        drop_group("input")
    if !arg_no3d: // /dev/dri/card0 has group video
        drop_group("render")
    if !arg_noprinters:
        drop_group("lp")
    in case other group names are used, we can provide mappings in firejail.config

@crocket
Copy link
Contributor Author

crocket commented Oct 15, 2021

I think I like nogroups (all) and nogroups auto. I also want noroot to not touch groups.

@topimiettinen
Copy link
Collaborator

@topimiettinen commented on Oct 14:

@smitsohu Let's say fine-grained group control means something like
groups.drop sudo (black/denylist) and groups.keep audio
(white/allowlist). The case for local admin is clear, maybe also for distros,
but how could we use them in upstream profiles? Maybe just commented out as
examples?

@smitsohu commented on Oct 14:

@topimiettinen Right. This kind of fine grained control (groups.drop) won't
be very helpful for upstream profiles. I was thinking from the perspective of
an administrator, but a more dynamic solution would be clearly better.

Considering groups.keep being more desirable than ?SET_FACL, that there is a working implementation of the former and assuming that the audio group (if any) is called "audio" on basically every distro that has firejail (would have to check this one):

If a program requires audio output (e.g.: mpv), would there be any downside in replacing nogroups with e.g.: groups.keep audio in its profile?

The users would gain access to this GID, which they didn't have before. Then they could make setgid binaries to keep the rights after Firejail exits.

On distros that default to systemd/pulseaudio, are new users added to an audio group by default? If not, I think that @topimiettinen's multi-seat concern would not apply, as the user would have to be deliberately added to such a group. As in, I think that this responsibility would fall on the user rather than on firejail (though we could document it of course).

I don't think so. At least my user isn't a member in any audio or cdrom groups.

Also, if there are more things needed to unblock (e.g.: specific device files) other than the group, maybe there could be an include like the following:

allow-audio.inc:

ignore nogroups

# alsa
noblacklist /dev/snd/*

# sndio
noblacklist /dev/audio*
noblacklist /dev/midi*

groups.keep audio

That is, adding include allow-audio.inc to relevant profiles rather than replacing nogroups with groups.keep audio on them.

Overriding the above (in e.g.: allow-audio.local) would also permit allowing only specific devices rather than every audio device, which would be even more granular than just groups.keep. Example:

ignore noblacklist /dev/audio*

noblacklist /dev/audio3

write-only /dev/audio3

Note: There is currently no write-only, but having something like the above looks like it could also effectively fix the following issue:

* [audio input is not blocked in default.profile (contrary to video input) #4565](https://github.com/netblue30/firejail/issues/4565)

And if someone would like to avoid allowing any groups at all, then something like ignore include allow-audio.inc (or ignore ignore nogroups) could be added to globals.local.

Nice idea, though I don't think giving access is necessary for logind distros. In my setup, pulseaudio is started from systemd --user and it has access to /dev/snd/ directory, but the DE programs (for example Firefox) inherit the /dev tree from display-manager.service, which has no access to /dev/snd/ at all (PrivateDevices=yes but then BindReadOnlyPaths= for some devices, excluding /dev/snd). Still, sound works fine in the DE programs because they connect to pulseaudio instead of touching the devices directly. Firejailed pulseaudio would need the access of course.

@topimiettinen
Copy link
Collaborator

If we keep adding stuff without eliminating lines, we may end up with something like ignore ignore ignore nogroups

ignore nogroups is enough.

What about nogroups <all|auto|none>?

* `nogroups all` (and alias `nogroups` for backward compatibility) will drop all supplementary groups. (and `noroot` will not change groups [noroot removes all user groups, nogroups redundant #3303](https://github.com/netblue30/firejail/issues/3303))

* `nogroups none` will keep all groups (maybe we don't need this as it is the same as not using `nogroups` and just complicates things)

* `nogroups auto` will autodetect which groups it should keep (whitelisting)
  ```js
  if !arg_nosound:
      drop_group("audio")
  if !arg_novideo:
      drop_group("video")
  if !arg_nodvd:
      drop_group("cdrom")
  if !arg_noinput:
      drop_group("input")
  if !arg_no3d: // /dev/dri/card0 has group video
      drop_group("render")
  if !arg_noprinters:
      drop_group("lp")
  ```

This could work well if also coupled with the logind check, so users on distros with logind would not get extra permissions but others would get at least some groups automatically when needed.

I think your auto concept is interesting more generally. Now there's a lot of heuristics going on in Firejail (to improve user friendliness) but it may be impossible to override them. But we could start introducing sort of auto (heuristics on) and manual modes (everything has to be specified explicitly, like bubblewrap) for each setting with heuristics now.

@crocket
Copy link
Contributor Author

crocket commented Oct 15, 2021

The users would gain access to this GID, which they didn't have before. Then they could make setgid binaries to keep the rights after Firejail exits.

Are you personally using firejail in public multi-seat computers? Isn't seccomp going to disable setting setgid bit?

In single-user computers, your scenario doesn't make sense.

@topimiettinen
Copy link
Collaborator

The users would gain access to this GID, which they didn't have before. Then they could make setgid binaries to keep the rights after Firejail exits.

Are you personally using firejail in public multi-seat computers? Isn't seccomp going to disable setting setgid bit?

Firejail doesn't have a feature similar to systemd's RestrictSUIDSGID=yes.

In single-user computers, your scenario doesn't make sense.

The 'user' in the scenario could be also an attacker, who temporarily gains limited access using for example browser vulnerabilities or indirectly via an organization's shared network file system. We don't know well in advance what makes sense for all future attack scenarios and every little bit of extra security can help weaken the attacker's capabilities. There's no global switch 'security=on' which could block all possible attacks. Instead there are yet unknown weaknesses of various sizes which may lead to vulnerabilities and exploits, and attempts to make attackers' lives more difficult to counter the possibility of weaknesses.

@crocket
Copy link
Contributor Author

crocket commented Oct 15, 2021

For nogroups auto to eliminate all supplementary groups on logind systems and keep relevant groups on other systems makes sense because it improves convenience without reducing security.

Convenience matters because

  • If it's very difficult to use firejail, people won't use it. Not using firejail is a lot worse than keeping some supplementary groups. Most people don't have enough patience or enough attention span to make firejail work on systems without logind.
  • It saves people's time. Time is a valuable resource. It's more valuable than money. We should consider time as one of many factors we optimize for. Security and privacy are important, too.

kmk3 added a commit to kmk3/firejail that referenced this issue Oct 22, 2021
Even when `nogroups` is not used, avoid keeping the audio and video
groups when `nosound` and `novideo` are used, respectively.

Based on @rusty-snake's suggestion:
netblue30#4603 (comment)

Relates to netblue30#4603.
kmk3 added a commit to kmk3/firejail that referenced this issue Oct 22, 2021
Even when `nogroups` is not used, avoid keeping the audio and video
groups when `nosound` and `novideo` are used, respectively.

Based on @rusty-snake's suggestion:
netblue30#4603 (comment)

Relates to netblue30#4603.
kmk3 added a commit to kmk3/firejail that referenced this issue Oct 22, 2021
Even when `nogroups` is not used, avoid keeping the audio and video
groups when `nosound` and `novideo` are used, respectively.

Based on @rusty-snake's suggestion:
netblue30#4603 (comment)

Relates to netblue30#4603.
@kmk3
Copy link
Collaborator

kmk3 commented Oct 23, 2021

@rusty-snake commented on Oct 15:

If we keep adding stuff without eliminating lines, we may end up with
something like ignore ignore ignore nogroups

ignore nogroups is enough.

What about nogroups <all|auto|none>?

  • nogroups all (and alias nogroups for backward compatibility) will drop
    all supplementary groups. (and noroot will not change groups noroot
    removes all user groups, nogroups redundant
    #3303
    )

  • nogroups none will keep all groups (maybe we don't need this as it is the
    same as not using nogroups and just complicates things)

  • nogroups auto will autodetect which groups it should keep (whitelisting)

    if !arg_nosound:
        drop_group("audio")
    if !arg_novideo:
        drop_group("video")
    if !arg_nodvd:
        drop_group("cdrom")
    if !arg_noinput:
        drop_group("input")
    if !arg_no3d: // /dev/dri/card0 has group video
        drop_group("render")
    if !arg_noprinters:
        drop_group("lp")

    in case other group names are used, we can provide mappings in
    firejail.config

I really like the mapping of the "no" options to groups; it seems like an
obvious thing to do. Luckily, it looks like it wouldn't be hard to do
(refactoring to making it work without ACLs is another story though); see the
following related PR:

So, considering the following extra groups from @rusty-snake's code:

  • cdrom
  • input
  • render
  • lp

Thoughts on adding them to the hardcoded "allowed groups" lists and dropping
them based on the no options?

@topimiettinen commented on Oct 15:

if !arg_nosound:
    drop_group("audio")
if !arg_novideo:
    drop_group("video")
if !arg_nodvd:
    drop_group("cdrom")
if !arg_noinput:
    drop_group("input")
if !arg_no3d: // /dev/dri/card0 has group video
    drop_group("render")
if !arg_noprinters:
    drop_group("lp")

This could work well if also coupled with the logind check, so users on
distros with logind would not get extra permissions but others would get at
least some groups automatically when needed.

After looking at the code, I think that combining the above ideas would be
a straightforward way to do it:

  • Dropping groups based on nosound, novideo, etc
  • Checking whether (e)logind is running before handling nogroups

And it wouldn't really require any new command or option.

So how about we do the following:

  • If nosound, always drop audio group and block sound devices in /dev
  • If novideo, always drop video group and block video devices in /dev

("always" above means "regardless of noroot and nogroups/(e)logind")

  • If nogroups and (e)logind is running, drop all non-hardcoded groups
  • If nogroups and (e)logind is not running, keep the audio and video groups
    (if not already dropped) and the hardcoded groups and drop all other groups

Currently, the audio/video groups are only dropped if noroot is used
(AFAICT).

@crocket Can you think of any other group that could be needed? Maybe the lp
group when using the new noprinters command?

Note: From what I've seen, using a variable like e.g.: have_seat_acls where
required might not be something trivial to do, since nogroups is used in
multiple places and since in some of them it currently means just "drop all
groups" in some places. But I haven't looked too much into it.

Maybe there could be a drop_groups(const char* groupnames[]) function (to
only drop certain groups and keep the rest) besides the
clean_supplementary_groups one (which drops all but certain hardcoded
groups)?


Misc: I had written some more comments, but since I wrote some code related to
the above (on #4632 and on a WIP branch), I'd like to get it out of the way
first.

@crocket
Copy link
Contributor Author

crocket commented Oct 24, 2021

New options to consider with regard to nogroups:

  • noprinters

Existing options to consider with regard to nogroups:

  • --no3d
  • --nodvd
  • --noinput
  • --nosound
  • --notv
  • --nou2f
  • --novideo

Other considerations:

  • noroot should not drop groups?

@kmk3
Copy link
Collaborator

kmk3 commented Oct 26, 2021

@crocket commented on Oct 24:

New options to consider with regard to nogroups:

  • noprinters

Existing options to consider with regard to nogroups:

  • --no3d
  • --nodvd
  • --noinput
  • --nosound
  • --notv
  • --nou2f
  • --novideo

Which groups would notv and nou2f map to?

Other considerations:

  • noroot should not drop groups?

I think it's intended to drop only the groups that are related to non-system
users. That is, all groups with a gid between GID_MIN and GID_MAX, as
defined on login.defs(5).

From my testing, the option appears to be working correctly (at least by
itself):

$ firejail --quiet --noprofile --noroot \
  getent group | cut -f 3 -d : | tr '\n' '\000' | xargs -0 -I '{}' sh -c \
  "test '{}' -ge 1000 && printf '%s\n' '{}'"
65534
1000

The following commands output the same amount of groups inside and outside of
firejail (so no system group appears to be dropped):

getent group | cut -f 3 -d : | tr '\n' '\000' | xargs -0 -I '{}' sh -c \
  "test '{}' -lt 1000 && printf '%s\n' '{}'" | wc -l

@crocket
Copy link
Contributor Author

crocket commented Oct 26, 2021

Which groups would notv and nou2f map to?

nou2f blocks /dev/hidraw0 which belongs to root group.
notv blocks /dev/dvb which doesn't exist on my system. So, I don't know which group it belongs to.

I think it's intended to drop only the groups that are related to non-system users.

Man page doesn't say anything about that.

@rusty-snake
Copy link
Collaborator

nou2f blocks /dev/hidraw0

FTR: It blocks /dev/hidraw[0-9] and /dev/usb

{"/dev/hidraw0", RUN_DEV_DIR "/hidraw0", DEV_U2F},
{"/dev/hidraw1", RUN_DEV_DIR "/hidraw1", DEV_U2F},
{"/dev/hidraw2", RUN_DEV_DIR "/hidraw2", DEV_U2F},
{"/dev/hidraw3", RUN_DEV_DIR "/hidraw3", DEV_U2F},
{"/dev/hidraw4", RUN_DEV_DIR "/hidraw4", DEV_U2F},
{"/dev/hidraw5", RUN_DEV_DIR "/hidraw5", DEV_U2F},
{"/dev/hidraw6", RUN_DEV_DIR "/hidraw6", DEV_U2F},
{"/dev/hidraw7", RUN_DEV_DIR "/hidraw7", DEV_U2F},
{"/dev/hidraw8", RUN_DEV_DIR "/hidraw8", DEV_U2F},
{"/dev/hidraw9", RUN_DEV_DIR "/hidraw9", DEV_U2F},
{"/dev/usb", RUN_DEV_DIR "/usb", DEV_U2F}, // USB devices such as Yubikey, U2F

kmk3 added a commit to kmk3/firejail that referenced this issue Nov 30, 2021
Currently, on systems that use seat managers that do not implement
seat-based ACLs (such as seatd), sound is broken whenever `nogroups` is
used.  This happens because without ACLs, access to the audio devices in
/dev is controlled by the standard group permissions and the "audio"
group is always dropped when `nogroups` is used.  This patch makes the
"audio" and "video" groups be dropped if and only if `noaudio` and
`novideo` are in effect, respectively (and independently of `nogroups`).
See netblue30#4603 and the linked issues/discussions for details.

Note: This is a continuation of commit ea564eb ("Consider nosound and
novideo when keeping groups") / PR netblue30#4632.

Relates to netblue30#2042 and netblue30#4531.
kmk3 added a commit to kmk3/firejail that referenced this issue Nov 30, 2021
Mappings of command -> group that this commit adds:

* no3d -> render
* noprinters -> lp
* nodvd -> cdrom (Debian[1] and Gentoo[2]), optical (Arch[3])
* noinput -> input

Mappings that were considered but that are not added:

* notv -> ? (unknown group)
* nou2f -> ? (devices are apparently owned by root; see netblue30#4603)

Based on @rusty-snake's suggestion:
netblue30#4603 (comment)

See the previous commit ("Keep audio and video groups regardless of
nogroups") for details.

Relates to netblue30#2042 and netblue30#4632.

[1] https://wiki.debian.org/SystemGroups
[2] https://api.gentoo.org/uid-gid.txt
[3] https://wiki.archlinux.org/title/Users_and_groups
@crocket
Copy link
Contributor Author

crocket commented Jan 2, 2022

Can this be considered fixed now?

@kmk3
Copy link
Collaborator

kmk3 commented Jan 3, 2022

@crocket commented on Jan 2:

Can this be considered fixed now?

Yes; thanks for the reminder.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature request
Projects
None yet
Development

No branches or pull requests

5 participants