Conversation
Codecov Report
@@ Coverage Diff @@
## master #10739 +/- ##
==========================================
+ Coverage 78.21% 78.32% +0.11%
==========================================
Files 916 919 +3
Lines 103800 104430 +630
==========================================
+ Hits 81187 81800 +613
- Misses 17520 17533 +13
- Partials 5093 5097 +4
Flags with carried forward coverage won't be shown. Click here to find out more.
Continue to review full report at Codecov.
|
50fa4b6 to
cdb82f3
Compare
cdb82f3 to
7eca140
Compare
pedronis
left a comment
There was a problem hiding this comment.
did a first pass, some comments
4a45cdd to
802c540
Compare
There was a problem hiding this comment.
It would be great to get @jrjohansen to give this function a once-over.
There was a problem hiding this comment.
how faithful does the conversion from aa globbing to re need to be? The conversion does not appear to be correct in some cases
alexmurray
left a comment
There was a problem hiding this comment.
There are a few places that worry me so I would like to see some more validation of various things like the filesystem types and some more tests added to try and make sure we can avoid snaps trying to abuse this interface.
There was a problem hiding this comment.
Please add type validation (this could be similar to option validation where items are checked against an allow-list) so that we can ensure the generated apparmor profile cannot have malicious content inserted into it, ie if a type was specified as: auto) options=() path/to/malicious/content /var/lib/snapd/hostfs/...,\n mount fstype=( - then I think currently this could allow a snap to mount over parts of the root file-system or some other trusted location, or they could inject other apparmor policy bits as well to gain additional accesses.
There was a problem hiding this comment.
I added a simple regular expression for alphanumeric characters, instead of a full list of possible options. This should address the security issue you raised, while remaining open to support any FS type. Please let me know, if you see a reason for an explicit list.
f062c0d to
33dd45b
Compare
pedronis
left a comment
There was a problem hiding this comment.
thanks
the slot-side base declaration needs some changes.
some happy paths are not hit by unit tests
anonymouse64
left a comment
There was a problem hiding this comment.
I haven't looked at the unit tests, but I have some thoughts :-)
let me know if you have any questions about my proposals, but the main problem I see right now is that we allow any filesystem type when we should be at least denying some specific filesystems that could be easily abused with this interface otherwise
There was a problem hiding this comment.
thanks for this unit test
There was a problem hiding this comment.
I'm a bit torn on this function, on the one hand, this interface is super-privileged so nothing will be uploadable to the store to be released without approval, but on the other hand, we've seen many instances of using system-files where a user declares something super wildly permissive and finds that it "just works" locally during development and goes to upload only to find that we actually don't encourage/allow/condone/permit that sort of usage of system-files, and many days I find myself wishing that whomever used system-files this way would have been warned during development that what they are doing is not encouraged or in many ways supported.
So on the one hand, I'm looking ahead and thinking of how people could abuse this when all they need to have to make this work locally is to have an absolute path that is clean, but on the other hand there may be legitimate use cases for mounting /sys/fs/kernel/give/me/all/your/secrets to /snap/foo/current/not-your-secrets.txt and we don't want to have to push out an update to snapd to allow this at the last minute like we have had to for other interfaces.
Also, I think system-files is uniquely more likely to be abused since it is about the single most frustrating aspect of apparmor confinement for snaps - arbitrary file access, whereas this interface is about arbitrary mount access which is not nearly as common of a requirement as arbitrary file access.
There was a problem hiding this comment.
as mentioned below, this is not enough, we should be disallowing certain kinds of filesystems from being mounted
There was a problem hiding this comment.
OK. I've added one more check
There was a problem hiding this comment.
unless I am reading this wrong, character class within an alrenation is not handled correctly. eg {[,],} -> ([|]|) when it should be ([,]|)
There was a problem hiding this comment.
It works correctly, it actually produces ^([,]|)$; I've added a unit test for this now.
There was a problem hiding this comment.
this doesn't looks wrong for the convertion when in a char class as well
There was a problem hiding this comment.
Sorry, I don't understand what you mean here. Maybe the most practical approach is if you tell me some example patterns to test, and we see what this code produces for them?
There was a problem hiding this comment.
okay, so I have been through this 3 separate times now trying to see what I thought I was seeing before, and I don't see it. I think this is good
84921ed to
f59ae19
Compare
|
Hmm I wonder about |
Makes sense. Removed! |
anonymouse64
left a comment
There was a problem hiding this comment.
Unfortunately this needs more work around validating what/where and perhaps needs a fundamental rethinking about what sort of strings we want to accept in what/where.
There was a problem hiding this comment.
now that we have an allow list, it is sort of unnecessary to have the regexp too, but I think it's fine to leave in
6c4e45a to
01230e1
Compare
pedronis
left a comment
There was a problem hiding this comment.
did another pass, some questions
There was a problem hiding this comment.
why /media ? I think in principle we want to allow / and control what is perimtted in terms of absolute targets in the snap-declaration?
There was a problem hiding this comment.
shouldn't we also prevent $ from appearing multiple times?
There was a problem hiding this comment.
@pedronis I assume by "allow / and ..." you mean to allow arbitrary absolute paths and not to allow mounting something at "/" exactly which would be very weird and break many things?
Assuming you meant absolute paths, maybe where should be something like:
whereRegexp = regexp.MustCompile(`^(/[^\$"@]+|\$SNAP_DATA|\$SNAP_COMMON)[^\$"@]*$`)which will disallow "/" or any other string starting with an env var (except $SNAP_DATA or $SNAP_COMMON), but otherwise allow anything underneath $SNAP_DATA or $SNAP_COMMON, as well as disallowing any other env vars in the string, any @ or any ". It also disallows $SNAP_DATA/$SNAP_DATA
There was a problem hiding this comment.
yes, I meant any absolute path (at this level)
There was a problem hiding this comment.
The dollar sign is not dangerous (AppArmor wouldn't treat it specially), but it sounds so suspicious that I think it's fine to disallow it.
I would suggest using a slightly simpler regexp:
whereRegexp = regexp.MustCompile(`^(\$SNAP_COMMON|\$SNAP_DATA)?/[^\$"@]+$`)
The only practical difference from Ian's is that this disallows having just $SNAP_COMMON or $SNAP_DATA as the target, but requires $SNAP_DATA/something, which looks a reasonable restriction to me.
There was a problem hiding this comment.
There was a problem hiding this comment.
I'm fine with the simplified proposal.
anonymouse64
left a comment
There was a problem hiding this comment.
overall looking really close, I have a few testing suggestions and some questions about the parsing code, also see the suggestion from @pedronis too
There was a problem hiding this comment.
| return fmt.Errorf(`mount-control "what" attribute is invalid: must start with / and not contain special characters`) | |
| return fmt.Errorf(`mount-control "what" attribute is invalid: must start with /, $SNAP_DATA, or $SNAP_COMMON and not contain special characters`) |
though the message is getting rather long now
There was a problem hiding this comment.
I'll accept the suggestion and remove the "is invalid:" bit to save some characters
There was a problem hiding this comment.
ok, but I don't see the suggestion accepted? the original error message I commented on is still in the diff (unless this is another github UI bug?)
There was a problem hiding this comment.
Ah, it's because I changed it in a different way: I think you accidentally commented on this one, thinking that it was about the "where" attribute. But this error is on the "what" attribute, for which we don't have the $SNAP_DATA or $SNAP_COMMON restriction.
There was a problem hiding this comment.
whatever the result of the ^ and $ question I asked above is, we should have those covered in tests here either in the happy paths or in the unhappy paths
There was a problem hiding this comment.
does it not work to define this in the environment section?
There was a problem hiding this comment.
you could also just have a check which exits the test if os.query is-opensuse-tumbleweed is true before doing these checks, it would make the nested if's here a bit more readable/less indented
There was a problem hiding this comment.
can we also have negative cases for the options not matching and for the filesystem not matching?
anonymouse64
left a comment
There was a problem hiding this comment.
thanks for all the changes, I left a few suggestions, but we can take those in followups since this PR is essentially ready to go I think, let's land it :-)
There was a problem hiding this comment.
ok, but I don't see the suggestion accepted? the original error message I commented on is still in the diff (unless this is another github UI bug?)
There was a problem hiding this comment.
this error message shouldn't mention /media anymore
There was a problem hiding this comment.
if there isn't a usage of counting the number of mount entries in follow up PR's, I have a slight preference for this to be a boolean instead as it's ever so slightly more readable to do:
hasMountEntries := false
err := enumerateMounts(plug, func(mountInfo *MountInfo) error {
hasMountEntries = true
return validateMountInfo(mountInfo)
})
if err != nil {
return err
}
if !hasMountEntries {
return mountAttrTypeError
}There was a problem hiding this comment.
IIRC it won't be used. Updated.
There was a problem hiding this comment.
since this is unexpected to happen, can you make this an internal error?
There was a problem hiding this comment.
I'm not sure what an "internal error" is; I just added "internal error:" at the beginning of the message :-)
There was a problem hiding this comment.
that's exactly what I meant, just add "internal error" to the start of the error message 😄
anonymouse64
left a comment
There was a problem hiding this comment.
last commit 6f8fc3458bdcc15b37e3e74e88b0716cbd14ea77 looks good to me, but there is now a conflict
6f8fc34 to
05ff793
Compare
It's because of the merge of the kernel-module-load interface. I've now rebased the branch and squashed most commits, let's see how it goes :-) |
This is the second part of the mount-control saga: this adds the interface itself and a spread test.
The full (draft) MR is here, whereas the first part (which this branch depends on) is #10653.