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
interfaces/utils: allow commas in filepaths #12697
Conversation
Currently, this change affects all uses of I'm very open to any comments or suggestions. Thanks! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was initially quite concerned that by allowing a comma it would then allow malicious snaps to inject arbitrary AppArmor rules and hence escape confinement as the comma is used to delimit separate AppArmor rules within AppArmor profiles.
However, there are a number of things that prevent this currently:
NewPathPattern()
appears to only be used in themount-control
andcustom-device
interfaces, both of which need a matching snap declaration from the store to be able to be used, and so a snap publisher can only achieve the ability to inject content with the help of a store admin to grant a matching snap declaration- Both of these interfaces quote the generated path with
""
which ensures that AppArmor treats the supplied argument as a complete path name rather than as say two AppArmor rules, separated by a comma.
This change does however remove an existing defensive measure to stop possible rule injection, so it will require careful attention to any new future users of NewPathPattern()
to ensure they ultimately quote their final argument when emitting AppArmor rules.
So from a security point of view I am not opposed to this change as clearly it is required to allow snaps to specify a custom device path containing a comma which is a real-world use-case.
I wonder if perhaps though it would be worth parameterising NewPathPatter()
with a boolean to allow / deny the use of a comma (and hence pass this parameter on to createRegex()
) so that this new behaviour can be restricted to just the custom-device
interface for now rather than to all / any callers of NewPathPattern()
to keep things safer.
After a bit more discussion, it seems that there are three options regarding when to allow commas:
|
Rather than allowing any caller of `NewPathPattern()` to successfully validate paths containing commas, this change adds a boolean argument which explicitly specifies whether commas should be allowed in the filepath. There are some risks involved with allowing commas in filepaths (see discussion at snapcore#12697), so it is desirable to restrict when commas are allowed based on the caller. In particular, superprivileged interfaces (such as `custom-device` and `mount-control`) have valid needs for commas in filepaths, and users of these interfaces are individually verified, so it is safe for them to use `NewPathPattern()` with commas allowed. Other callers (particularly unprivileged interfaces) should probably not allow commas. I was unsure whether `overlord/hookstate/ctlcmd/mount.go` should call `NewPathPattern()` with commas allowed or not, but since commas had previously been disallowed and tests continue to pass with `allowCommas=false`, then I decided to leave it as `false`. Signed-off-by: Oliver Calder <oliver.calder@canonical.com>
I opted for the second option of those listed above. I think a boolean parameter is the most flexible while minimizing duplicate code or execution paths. One question is whether |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
did a pass
interfaces/builtin/custom_device.go
Outdated
@@ -76,7 +76,7 @@ func (iface *customDeviceInterface) validateFilePath(path string, attrName strin | |||
return fmt.Errorf(`custom-device %q path is not clean: %q`, attrName, path) | |||
} | |||
|
|||
if _, err := utils.NewPathPattern(path); err != nil { | |||
if _, err := utils.NewPathPattern(path, true); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
when we rarely use boolean args we use constants to help reading:
const allowCommas = true
... utils.NewPathPattern(path, allowCommas) ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this needs a corresponding unit test
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good.
Left two minor comments.
For the mount control use case, do we currently need comma path support for more than functionfs?
Thanks for the review and suggestions @ernestl Since commas are allowed in filepaths on Linux generally, I don't see why it wouldn't be the case that a user of the mount-control interface might need to mount a device with a comma in its path or mount to a mount point with a comma in its path, regardless of filesystem type. However, I don't think this has yet been a problem in the field. I'm happy to restrict it to the custom-device interface, if that's desirable (particularly with respect to security review). |
Some device paths contain commas outside of groups (i.e. {a,b}) or classes (i.e. [,.:;'"]). For example, `/dev/foo,bar` is a valid device path which one might with to use with the custom-device interface. Most filesystems allow commas in filepaths, as does apparmor: https://gitlab.com/apparmor/apparmor/-/blob/master/parser/parser_regex.c#L340 Previously, createRegex() would throw an error if a comma was used outside of a group or class. This commit removes that error and instead treats commas outside of groups and classes as literal commas. The accompanying tests are also adjusted to reflect this change. Signed-off-by: Oliver Calder <oliver.calder@canonical.com>
Rather than allowing any caller of `NewPathPattern()` to successfully validate paths containing commas, this change adds a boolean argument which explicitly specifies whether commas should be allowed in the filepath. There are some risks involved with allowing commas in filepaths (see discussion at snapcore#12697), so it is desirable to restrict when commas are allowed based on the caller. In particular, superprivileged interfaces (such as `custom-device` and `mount-control`) have valid needs for commas in filepaths, and users of these interfaces are individually verified, so it is safe for them to use `NewPathPattern()` with commas allowed. Other callers (particularly unprivileged interfaces) should probably not allow commas. I was unsure whether `overlord/hookstate/ctlcmd/mount.go` should call `NewPathPattern()` with commas allowed or not, but since commas had previously been disallowed and tests continue to pass with `allowCommas=false`, then I decided to leave it as `false`. Signed-off-by: Oliver Calder <oliver.calder@canonical.com>
Also, switched `overlord/hookstate/ctlcmd/mount.go` to allow commas (previously did not, but this should match what is allowed in `interfaces/builtin/mount_control.go`. Signed-off-by: Oliver Calder <oliver.calder@canonical.com>
Signed-off-by: Oliver Calder <oliver.calder@canonical.com>
Since `,` is not a regex special character, the `QuoteMeta` call is unnecessary. Signed-off-by: Oliver Calder <oliver.calder@canonical.com>
Signed-off-by: Oliver Calder <oliver.calder@canonical.com>
c6c768a
to
730d51a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this looks good but needs matching unit test extensions
…=true Signed-off-by: Oliver Calder <oliver.calder@canonical.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks
* interfaces/utils: allow commas in filepaths Some device paths contain commas outside of groups (i.e. {a,b}) or classes (i.e. [,.:;'"]). For example, `/dev/foo,bar` is a valid device path which one might with to use with the custom-device interface. Most filesystems allow commas in filepaths, as does apparmor: https://gitlab.com/apparmor/apparmor/-/blob/master/parser/parser_regex.c#L340 Previously, createRegex() would throw an error if a comma was used outside of a group or class. This commit removes that error and instead treats commas outside of groups and classes as literal commas. The accompanying tests are also adjusted to reflect this change. Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * interfaces/utils: added argument to allow commas in filepaths Rather than allowing any caller of `NewPathPattern()` to successfully validate paths containing commas, this change adds a boolean argument which explicitly specifies whether commas should be allowed in the filepath. There are some risks involved with allowing commas in filepaths (see discussion at #12697), so it is desirable to restrict when commas are allowed based on the caller. In particular, superprivileged interfaces (such as `custom-device` and `mount-control`) have valid needs for commas in filepaths, and users of these interfaces are individually verified, so it is safe for them to use `NewPathPattern()` with commas allowed. Other callers (particularly unprivileged interfaces) should probably not allow commas. I was unsure whether `overlord/hookstate/ctlcmd/mount.go` should call `NewPathPattern()` with commas allowed or not, but since commas had previously been disallowed and tests continue to pass with `allowCommas=false`, then I decided to leave it as `false`. Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * interfaces/{builtin,utils}: added named variables for allowCommas Also, switched `overlord/hookstate/ctlcmd/mount.go` to allow commas (previously did not, but this should match what is allowed in `interfaces/builtin/mount_control.go`. Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * interfaces/utils: added unit tests for commas in paths Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * interfaces/utils: remove `QuoteMeta` when adding `","` to path regex Since `,` is not a regex special character, the `QuoteMeta` call is unnecessary. Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * interfaces/utils: renamed TestCommasInRegex to TestCreateRegexWithCommas Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * many: added unit tests for callers of NewPathPattern with allowCommas=true Signed-off-by: Oliver Calder <oliver.calder@canonical.com> --------- Signed-off-by: Oliver Calder <oliver.calder@canonical.com> Co-authored-by: Michael Vogt <mvo@ubuntu.com>
* interfaces/utils: allow commas in filepaths Some device paths contain commas outside of groups (i.e. {a,b}) or classes (i.e. [,.:;'"]). For example, `/dev/foo,bar` is a valid device path which one might with to use with the custom-device interface. Most filesystems allow commas in filepaths, as does apparmor: https://gitlab.com/apparmor/apparmor/-/blob/master/parser/parser_regex.c#L340 Previously, createRegex() would throw an error if a comma was used outside of a group or class. This commit removes that error and instead treats commas outside of groups and classes as literal commas. The accompanying tests are also adjusted to reflect this change. Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * interfaces/utils: added argument to allow commas in filepaths Rather than allowing any caller of `NewPathPattern()` to successfully validate paths containing commas, this change adds a boolean argument which explicitly specifies whether commas should be allowed in the filepath. There are some risks involved with allowing commas in filepaths (see discussion at snapcore#12697), so it is desirable to restrict when commas are allowed based on the caller. In particular, superprivileged interfaces (such as `custom-device` and `mount-control`) have valid needs for commas in filepaths, and users of these interfaces are individually verified, so it is safe for them to use `NewPathPattern()` with commas allowed. Other callers (particularly unprivileged interfaces) should probably not allow commas. I was unsure whether `overlord/hookstate/ctlcmd/mount.go` should call `NewPathPattern()` with commas allowed or not, but since commas had previously been disallowed and tests continue to pass with `allowCommas=false`, then I decided to leave it as `false`. Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * interfaces/{builtin,utils}: added named variables for allowCommas Also, switched `overlord/hookstate/ctlcmd/mount.go` to allow commas (previously did not, but this should match what is allowed in `interfaces/builtin/mount_control.go`. Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * interfaces/utils: added unit tests for commas in paths Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * interfaces/utils: remove `QuoteMeta` when adding `","` to path regex Since `,` is not a regex special character, the `QuoteMeta` call is unnecessary. Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * interfaces/utils: renamed TestCommasInRegex to TestCreateRegexWithCommas Signed-off-by: Oliver Calder <oliver.calder@canonical.com> * many: added unit tests for callers of NewPathPattern with allowCommas=true Signed-off-by: Oliver Calder <oliver.calder@canonical.com> --------- Signed-off-by: Oliver Calder <oliver.calder@canonical.com> Co-authored-by: Michael Vogt <mvo@ubuntu.com>
Some device paths contain commas outside of groups (i.e.
{a,b}
) or classes (i.e.[,.:;'"]
). For example,/dev/foo,bar
is a valid device path which one might wish to use with the custom-device interface.Most filesystems allow commas in filepaths, as does apparmor: https://gitlab.com/apparmor/apparmor/-/blob/master/parser/parser_regex.c#L340
Previously,
createRegex()
would throw an error if a comma was used outside of a group or class. This commit removes that error and instead treats commas outside of groups and classes as literal commas. The accompanying tests are also adjusted to reflect this change.