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

RPC policy rule syntax: the difference between target= and default_target= can be confusing #7723

Open
andrewdavidwong opened this issue Aug 30, 2022 · 7 comments
Labels
affects-4.1 This issue affects Qubes OS 4.1. affects-4.2 This issue affects Qubes OS 4.2. C: core P: major Priority: major. Between "default" and "critical" in severity. ux User experience

Comments

@andrewdavidwong
Copy link
Member

How to file a helpful issue

Qubes OS release

4.1.1

Description

This issue is branched from #7720. It concerns the parts in bold below.

@marmarek wrote in #7720 (comment):

Those rules, with the current policy semantic, does not allow the call. The default_target selects default target from targets allowed (ask or allow) by other rules already. This is different from target, which overrides target regardless of whether it is otherwise allowed or not. See https://github.com/QubesOS/qubes-core-qrexec/blob/master/doc/qubes-policy.rst (hmm, it seems we don't have this rendered anywhere else).
And indeed no other rule allows calls to @dispvm:dvm-default (@dispvm means @dispvm:dvm-other when it has dvm-other set as default_dispvm).

So, we have few points here:

  1. Error handling - it should be clear message what really happened, not AssertionError
  2. Confusing difference between target= and default_target= - the later requires another rule that would allow/ask the call, while the former does not
  3. Setting just ask target= does not select that target as default, even though it makes it the only allowed choice. You'd need to specify both target= and default_target= for that.

The first point is an obvious bug. The second is intended semantics, but I can be persuaded to change it. The third one was intentional choice, but when looking at it now, I think it was a wrong one and should be changed.

Therefore, this issue is for deciding how to handle the semantics of target= and default_target= with the aim of reducing potential user confusion regarding the difference between them.

Related issues

The other points mentioned in the quoted text above are handled in other issues:

@andrewdavidwong andrewdavidwong added T: bug C: core ux User experience P: default Priority: default. Default priority for new issues, to be replaced given sufficient information. labels Aug 30, 2022
@andrewdavidwong andrewdavidwong added this to the Release 4.1 updates milestone Aug 30, 2022
@andrewdavidwong andrewdavidwong added the affects-4.1 This issue affects Qubes OS 4.1. label Aug 8, 2023
@andrewdavidwong andrewdavidwong removed this from the Release 4.1 updates milestone Aug 13, 2023
@marmarek
Copy link
Member

Continuing from #8227 (comment) (by @ben-grande):

understand it is intentional. It is okay to override the destination on the same line by using target=, but is it okay to ignore previous deny rules to that destination?
My PR aboves consider previous deny rules and if encounters none, uses the redirect target=.

No, it additionally requires other "allow" rule to be present.

Generally, the current behavior of target= rule is meant o limit leaking target name (or possibility to enumerate qubes) to the source qube.
Consider the following example:

some.service * source @default target=destination

With current implementation, only the call with @default target will get redirected to destination. Specifying any call target explicitly (being actual destination or something else) will get denied. With your change, all calls (also with @default target) will get denied, as collect_targets_for_ask will return an empty list.
But then, if you add an allow rule:

some.service * source destination allow
some.service * source @default allow target=destination

the source qube can make a call to destination explicitly and confirm its existence this way.

Note also, in this (and few other) examples, the order of allow/deny rules rarely matter if you override the target, as the original target will usually be different than the overridden one. For example, with your change:

some.service * source dest-1 deny
some.service * source dest-2 allow target=dest-1

is the same as

some.service * source dest-2 allow target=dest-1
some.service * source dest-1 deny

because dest-2 != dest-1, so collect_targets_for_ask will consider both rules.

All that said, even with your change, it's still possible to prevent source qube learning real target name, by using different rule(s):

some.service * source @anyvm allow target=destination

This, instead of refusing other calls (requested to actual destination or elsewhere), will allow them but redirect. This may be a bit confusing when configuring your system (you think you make a call to target1, but actually it gets redirected to target2), but OTOH arguably the current behavior of target= is even more confusing.

@ben-grande
Copy link

ben-grande commented Nov 27, 2023 via email

@marmarek
Copy link
Member

Email parsing mangled formatting and masked out some keywords...

@marmarek
Copy link
Member

marmarek commented Nov 27, 2023

The call will be allowed (with interaction):

qubes.GitInit * dev @AnyVM deny
qubes.GitInit * dev @default ask default_target=sys-git target=sys-git

No, it won't. @anyvm matches also @default, so it will never reach the ask action.

But I think you meant this example instead:

qubes.GitInit * dev sys-git deny
qubes.GitInit * dev @default ask default_target=sys-git target=sys-git

With your patch indeed this will be denied (which wasn't the case before your patch).

Note to self: the patch indeed considers only earlier rules, not later ones (even though target column may not match) only because collect_targets_for_ask prefers target= field if present over the target column.

I don't find the behavior of target= confusing and I don't think the issues were duplicate.

The change you propose fixes part of this issue, the difference in allowed targets between

qubes.GitInit * dev sys-git deny
# with or without default_target=
qubes.GitInit * dev @default ask target=sys-git

and

qubes.GitInit * dev sys-git deny
qubes.GitInit * dev @default ask default_target=sys-git

Before your change, the first will have one possible target, while the latter will have possible targets list empty (effectively denying the call). After your change, both will have empty targets list.

But indeed, the difference remains without the earlier deny rule. So it isn't fully the same issue, but I'd call it still close enough, especially since that's the difference that was considered to be changed.

@marmarek
Copy link
Member

So, generally I agree with the proposed change. But we need some safe approach to deploy it, because it is a semantic change of existing rules. The qrexec-legacy-convert tool uses qrexec-policy-graph before and after to verify if semantic remained the same (BTW, thanks for helping with improving this tool!), but that was about changing rule files, not changing meaning of rules without changing rules themselves.

The change should only result in some actions to be denied that were previously allowed, so it is a "safer" direction, but still it may break user setups in unintended ways. This also means it is too late to deploy it into R4.2, I think.

@andrewdavidwong andrewdavidwong added P: major Priority: major. Between "default" and "critical" in severity. affects-4.2 This issue affects Qubes OS 4.2. and removed P: default Priority: default. Default priority for new issues, to be replaced given sufficient information. labels Nov 27, 2023
@DemiMarie
Copy link

The change should only result in some actions to be denied that were previously allowed, so it is a "safer" direction, but still it may break user setups in unintended ways. This also means it is too late to deploy it into R4.2, I think.

With the default rules this change is a no-op, so it is definitely safe to deploy in that case. What about:

  • Making the change conditional on some setting.
  • Enabling the setting by default if it would be a no-op.
  • Allowing users to opt-in manually if this was not done automatically.

@ben-grande
Copy link

So, generally I agree with the proposed change. But we need some safe approach to deploy it, because it is a semantic change of existing rules. The qrexec-legacy-convert tool uses qrexec-policy-graph before and after to verify if semantic remained the same (BTW, thanks for helping with improving this tool!),

Thanks for reviewing!

but that was about changing rule files, not changing meaning of rules without changing rules themselves.

As far as I can see, this migration would be difficult because it needs to change the rules order. The destination can have tokens such as tags which the policy doesn't know which qube has that. Placing all deny rules at the bottom of the file would facilitate not having to find the correct line number to but the rule below, but this would mess even further with user setups by leaving ask and allow at the top and deny at the bottom, but without semantic changes.

But.... unman and andrew and me were expecting for this to be already the behavior and Qubes default policies also put deny rules after ask and allow that have redirects.

The change should only result in some actions to be denied that were previously allowed, so it is a "safer" direction, but still it may break user setups in unintended ways. This also means it is too late to deploy it into R4.2, I think.

I understand it is not safe to assume how the user has configured their own system... and maybe I am overcomplicating how difficult it is to do this migration. I don't think it is too late for R4.2, maybe for the first release yes, but for a point release it might be okay depending on how much you consider this a breaking change.

The change should only result in some actions to be denied that were previously allowed, so it is a "safer" direction, but still it may break user setups in unintended ways. This also means it is too late to deploy it into R4.2, I think.

With the default rules this change is a no-op, so it is definitely safe to deploy in that case. What about:

  • Making the change conditional on some setting.
  • Enabling the setting by default if it would be a no-op.
  • Allowing users to opt-in manually if this was not done automatically.

If it is worth it, !compat-4.1 can be used, which can be set on 35-compat.policy or another file if that one can not be replaced.

@marmarek marmarek removed their assignment Mar 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
affects-4.1 This issue affects Qubes OS 4.1. affects-4.2 This issue affects Qubes OS 4.2. C: core P: major Priority: major. Between "default" and "critical" in severity. ux User experience
Projects
None yet
Development

No branches or pull requests

4 participants