Join GitHub today
GitHub is home to over 20 million developers working together to host and review code, manage projects, and build software together.
interfaces/builtin/account_control: use gid owning /etc/shadow to setup seccomp rules #4185
Conversation
| @@ -59,8 +59,8 @@ capability fsetid, | ||
| // Needed because useradd uses a netlink socket | ||
| const accountControlConnectedPlugSecComp = ` | ||
| # useradd requires chowning to 'shadow' | ||
| -fchown - u:root g:shadow | ||
| -fchown32 - u:root g:shadow | ||
| +fchown - u:root |
mvo5
requested a review
from
jdstrand
Nov 9, 2017
|
|
bboozzoo
referenced this pull request
Nov 9, 2017
Closed
osutil: replace cgo bits with non-cgo, vendored os/user #4188
codecov-io
commented
Nov 9, 2017
•
Codecov Report
@@ Coverage Diff @@
## master #4185 +/- ##
==========================================
- Coverage 75.87% 75.87% -0.01%
==========================================
Files 440 440
Lines 38273 38293 +20
==========================================
+ Hits 29039 29053 +14
- Misses 7220 7224 +4
- Partials 2014 2016 +2
Continue to review full report at Codecov.
|
jdstrand
requested changes
Nov 9, 2017
NAK. While this patch is super clean, it also means that the account-control interface is now allowed to change any file it has write access to an arbitrary group. This is wrong and we shouldn't weaken policy because we don't want to perform a gid lookup.
I don't understand why the facility needs to be removed-- it is useful and we may in the future want to be able to perform other uid and gid lookups from within snapd (that's why I added it in the first place). I always envisioned this section of code would either have a mapping that snapd would maintain (if Debian/Ubuntu use g:shadow, if Arch use g:root, if Solus use...) or we would look up the file's group like you did in the first attempt at fixing this. The fact that Go doesn't offer what we need by default and the apparent strong desire to move away from cgo further supports my historical reservations for moving to bpf caching within Go in the first place and Go's suitability for lowlevel OS operations. :\
If cgo is so terrible that it must be removed, instead of weakening the policy, how about shelling out to getent group <gid> or writing a small C helper that snap-seccomp can shell out to for the operations not yet supported in Go. Specifically, write cmd/snap-lookup-helper that can perform getgrnam() and adjust snapd to detect if user.LookupGroup is available, and use snap-lookup-helper if it isn't. You could then drop all the cgo code around LookupGroup. Then to properly fix this PR, lookup the file's group and add getgrgid() to snap-lookup-helper (heck, you don't even need getgrgid() to do this: simply lookup the group of /etc/shadow (which gives you the gid) and make the rule simple by fchown - u:root <gid> (as opposed to fchown - u:root g:<group> like you had before)).
Shelling out is an extra exec of course, but it is only going to happen when the bpf cache is regenerated (ie, on security profile changes). If we make it conditional on Go's support of LookupGroup, it will also go away in the fullness of time.
|
To be clear, since |
bboozzoo
referenced this pull request
Nov 9, 2017
Merged
osutil: add helper for obtaining group ID of given file path #4192
bboozzoo
added some commits
Nov 9, 2017
|
I've updated the account control interface setup to poke /etc/shadow, and use owning gid to setup seccomp. |
jdstrand
approved these changes
Nov 9, 2017
Thank you for making this change. With this, any cgo changes/removals can happen in a subsequent PR.
| +// Needed because useradd uses a netlink socket, {{group}} is used as a | ||
| +// placeholder argument for the actual ID of a group owning /etc/shadow | ||
| +const accountControlConnectedPlugSecCompTemplate = ` | ||
| +# useradd requires chowning to '{{group}}' |
jdstrand
Nov 9, 2017
Contributor
Can you update this to be:
# useradd requires chowning to 0:'{{group}}'
| + implicitOnClassic: true, | ||
| + baseDeclarationSlots: accountControlBaseDeclarationSlots, | ||
| + connectedPlugAppArmor: accountControlConnectedPlugAppArmor, | ||
| + // handled by SecCompConnectedPlug |
jdstrand
Nov 9, 2017
Contributor
I think you don't need to change init in this manner. Can't you simply:
- connectedPlugSecComp: accountControlConnectedPlugSecComp,
+ connectedPlugSecComp: getSecCompSnippet(),
(or similar)
bboozzoo
Nov 9, 2017
Contributor
In theory stat() may fail and there's no other way to return errors in init() other than panicking
zyga
Nov 10, 2017
Contributor
Not a strong opinion but I think we could just use init and handle the error internally.
bboozzoo
changed the title from
interfaces/builtin/account_control: drop group filter from seccomp rules
to
interfaces/builtin/account_control: use gid owning /etc/shadow to setup seccomp rules
Nov 9, 2017
|
There's a silly mistake right here: https://github.com/snapcore/snapd/pull/4185/files#diff-3bc8ebdf9693ccc7718f010fe1d991a6R91 The relevant unit test failed as expected:
Interestingly /etc/shadow is owned by 0:42 in Ubuntu. |
|
Travis build failed with:
502 on fedora mirrors again? |
|
The fedora mirror situation is not changed. We believe that it fails to sync while the mirror itself is being updated. |
zyga
approved these changes
Nov 10, 2017
Some comments for your consideration, otherwise +1
| + commonInterface | ||
| +} | ||
| + | ||
| +func makeAccountControlSecCompSnippet() (string, error) { |
| +func (iface *accountControlInterface) SecCompConnectedPlug(spec *seccomp.Specification, plug *interfaces.Plug, Attrs map[string]interface{}, slot *interfaces.Slot, slotAttrs map[string]interface{}) error { | ||
| + if snippet, err := makeAccountControlSecCompSnippet(); err != nil { | ||
| + return err | ||
| + } else { |
| + implicitOnClassic: true, | ||
| + baseDeclarationSlots: accountControlBaseDeclarationSlots, | ||
| + connectedPlugAppArmor: accountControlConnectedPlugAppArmor, | ||
| + // handled by SecCompConnectedPlug |
jdstrand
Nov 9, 2017
Contributor
I think you don't need to change init in this manner. Can't you simply:
- connectedPlugSecComp: accountControlConnectedPlugSecComp,
+ connectedPlugSecComp: getSecCompSnippet(),
(or similar)
bboozzoo
Nov 9, 2017
Contributor
In theory stat() may fail and there's no other way to return errors in init() other than panicking
zyga
Nov 10, 2017
Contributor
Not a strong opinion but I think we could just use init and handle the error internally.
Don't know why, but I cannot respond under the comment. In order to avoid a Something like this:
Edit: I pushed this as a commit here: bboozzoo/snapd@f94bfe9 in case anyone wants to take a look. |
bboozzoo
referenced this pull request
Nov 13, 2017
Merged
snapstate: add support for refresh.schedule=managed #4161
| +} | ||
| + | ||
| +func (iface *accountControlInterface) SecCompConnectedPlug(spec *seccomp.Specification, plug *interfaces.Plug, Attrs map[string]interface{}, slot *interfaces.Slot, slotAttrs map[string]interface{}) error { | ||
| + if iface.secCompSnippet == "" { |
zyga
Nov 13, 2017
Contributor
Can you please add a comment like this:
// Cache the snippet after it is computed once.
| - connectedPlugSecComp: accountControlConnectedPlugSecComp, | ||
| - reservedForOS: true, | ||
| + registerIface(&accountControlInterface{ | ||
| + commonInterface: commonInterface{ |
zyga
Nov 13, 2017
Contributor
If you put this on the preceding line does go fmt let it through? If so this could be a nice way to address common/custom interface transitions without big deltas.
bboozzoo
added some commits
Nov 14, 2017
|
Is this one good to go? |
bboozzoo commentedNov 9, 2017
The /etc/shadow file is owned by user root across all supported distributions.
However, the group owning that file is either 'shadow' or 'root' (Arch). Drop
the group filter to avoid the need for detecting the right group at runtime.
This is the first part of changes related to weeding out cgo from snapd proper. @niemeyer @zyga @mvo5 want to take a look?