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

Add support for Wayland security context #4920

Merged
merged 3 commits into from Aug 24, 2023

Conversation

emersion
Copy link
Contributor

@emersion emersion commented May 31, 2022

This exposes a reliable way for Wayland compositors to get
identifying information about a client. Compositors can then
apply security policies if desirable.

TODO: bwrap --sync-fd can only be specified once (only the last param is taken into account), but D-Bus already uses it. Any ideas how to address this?

References: https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/68

common/flatpak-run.c Outdated Show resolved Hide resolved
common/flatpak-run.c Outdated Show resolved Hide resolved
@emersion
Copy link
Contributor Author

Gentle ping

common/flatpak-run.c Outdated Show resolved Hide resolved
@swick
Copy link
Contributor

swick commented Jun 10, 2022

@smcv might also be interested

@emersion emersion force-pushed the wl-security-context branch 2 times, most recently from be03687 to c2823de Compare October 5, 2022 12:57
@emersion emersion force-pushed the wl-security-context branch 5 times, most recently from 40a3a0d to f07412d Compare June 15, 2023 10:04
@@ -487,7 +488,8 @@ flatpak_run_add_environment_args (FlatpakBwrap *bwrap,
flatpak_context_append_bwrap_filesystem (context, bwrap, app_id, app_id_dir,
exports, xdg_dirs_conf, home_access);

flatpak_run_add_socket_args_environment (bwrap, context->shares, context->sockets);
if (instance_id)
flatpak_run_add_socket_args_environment (bwrap, context->shares, context->sockets);
flatpak_run_add_session_dbus_args (bwrap, proxy_arg_bwrap, context, flags, app_id);
flatpak_run_add_system_dbus_args (bwrap, proxy_arg_bwrap, context, flags);
flatpak_run_add_a11y_dbus_args (bwrap, proxy_arg_bwrap, context, flags);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if any of these needs to be added for apply_extra_data() (which is where instance_id can be NULL).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mh, I would even go so far and say it also should not get access to IPC, /dev, dri and shared tmp.

Probably makes sense to separate into a new PR.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally these are no-ops due to the passed in run_flags (e.g. with FLATPAK_RUN_FLAG_NO_SESSION_BUS_PROXY, etc), and the empty app_context that apply_extra_data uses.

Do you have any particular place where it gets this wrong?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In fact, is this check even needed? I don't see how sockets & FLATPAK_CONTEXT_SOCKET_WAYLAND would be set in apply_extra_data?

In fact, isn't it a bad idea to not call flatpak_run_add_socket_args_environment()?
We actively do some things like cover-mount /tmp/.X11, etc, if the x11 flag is not set. So maybe this will actually limit our security measures?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. So instead, would an assert that the instance is not NULL be welcome when setting up Wayland sockets?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the end, what we don't is setting up Wayland socket when we don't have an instance id, which appears to be the case when we arrive here from apply_extra_data().

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. So instead, would an assert that the instance is not NULL be welcome when setting up Wayland sockets?

I guess this makes sense. Assert that instance ID is set if sockets & FLATPAK_CONTEXT_SOCKET_WAYLAND.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I looked into this as well on Friday and noticed that the run flags are not what makes this work. The context doesn't load metadata from anywhere so none of the sockets will get set up.

The --sandboxed argument to flatpak run was added after the apply_extra_data sandbox and does almost the same but not entirely. It does add FLATPAK_RUN_FLAG_NO_PROC as well and I can't tell why and we don't call flatpak_context_make_sandboxed which is fine because we don't load anything else in the context but might be a good idea to call anyway.

Wanted to test this but a lot of tests are failing for me on main because of #5027.

--- a/common/flatpak-dir.c
+++ b/common/flatpak-dir.c
@@ -8328,20 +8328,25 @@ apply_extra_data (FlatpakDir   *self,
                           "--cap-drop", "ALL",
                           NULL);
 
-  /* Might need multiarch in apply_extra (see e.g. #3742).
-   * Should be pretty safe in this limited context */
-  run_flags = (FLATPAK_RUN_FLAG_MULTIARCH |
+  /* Run flags which equal --sandboxed */
+  run_flags = (FLATPAK_RUN_FLAG_SANDBOX |
                FLATPAK_RUN_FLAG_NO_SESSION_HELPER |
-               FLATPAK_RUN_FLAG_NO_PROC |
                FLATPAK_RUN_FLAG_NO_SESSION_BUS_PROXY |
                FLATPAK_RUN_FLAG_NO_SYSTEM_BUS_PROXY |
                FLATPAK_RUN_FLAG_NO_A11Y_BUS_PROXY);
 
+  /* Might need multiarch in apply_extra (see e.g. #3742).
+   * Should be pretty safe in this limited context.
+   * Removing /proc to tighten sandbox even more I guess? */
+  run_flags |= FLATPAK_RUN_FLAG_NO_PROC |
+               FLATPAK_RUN_FLAG_MULTIARCH;
+
   if (!flatpak_run_setup_base_argv (bwrap, runtime_files, NULL, runtime_arch,
                                     run_flags, error))
     return FALSE;
 
   app_context = flatpak_context_new ();
+  flatpak_context_make_sandboxed (app_context);
 
   if (!flatpak_run_add_environment_args (bwrap, NULL, run_flags, id,
                                          app_context, NULL, NULL, -1,

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Created #5466 to maybe discuss this further.

Assert that instance ID is set if sockets & FLATPAK_CONTEXT_SOCKET_WAYLAND

Yeah.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We absolutely don't want NO_PROC. That will break any apps that uses /proc/self/fd, etc which is very common (even used by glibc). And /proc access is not a security problem for regular apps. Only for apply_extra_data() when writing to the system repo. See commit message for cd21428.

And flatpak_context_make_sandboxed() is a complete no-op for the newly created (and thus empty) app_context.

@emersion
Copy link
Contributor Author

Rebased, added Meson support, made instance ID mandatory.

@emersion emersion force-pushed the wl-security-context branch 2 times, most recently from b41dd86 to 643e6fa Compare June 15, 2023 10:40
@davidedmundson
Copy link
Contributor

Can I check that this MR is "acked in principle" and just blocked on the upstream protocol to land?

Obviously it's chicken and egg, but it's also silly to land this in the specs without the most important user of this being officially on-board.

@jadahl
Copy link
Contributor

jadahl commented Jun 22, 2023

Can I check that this MR is "acked in principle" and just blocked on the upstream protocol to land?

There has been no explicit ack from a maintainer yet, but it got some initial review from @alexlarsson. Something more would be appreciated no doubt.

@emersion
Copy link
Contributor Author

Any news about this?

Copy link
Member

@alexlarsson alexlarsson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@emersion
Copy link
Contributor Author

emersion commented Jul 3, 2023

Thank you for having a look, @alexlarsson!

@jadahl
Copy link
Contributor

jadahl commented Jul 3, 2023

Next steps: release wayland-protocols with the new protocol, and bump the version needed by flatpak if enabled.

@alexlarsson
Copy link
Member

Actually, as per the comment above. I think not calling flatpak_run_add_socket_args_environment() is a bad idea.

@jadahl
Copy link
Contributor

jadahl commented Jul 3, 2023

Next steps: release wayland-protocols with the new protocol, and bump the version needed by flatpak if enabled.

Can now depend on 1.32 for this.

@emersion
Copy link
Contributor Author

emersion commented Jul 3, 2023

Added an assert and the wayland-protocols version requirement.

common/flatpak-run-wayland.c Outdated Show resolved Hide resolved
.github/workflows/check.yml Outdated Show resolved Hide resolved
@emersion emersion force-pushed the wl-security-context branch 2 times, most recently from d48b00d to 6010dc1 Compare July 4, 2023 16:09
@swick
Copy link
Contributor

swick commented Jul 4, 2023

LGTM

@emersion
Copy link
Contributor Author

@alexlarsson, does this look good to you?

@emersion
Copy link
Contributor Author

@alexlarsson, anything else I need to do or does this look good to you?

@emersion
Copy link
Contributor Author

@alexlarsson, any news about this?

@emersion
Copy link
Contributor Author

@alexlarsson, any chance to get this merged?

Copy link
Member

@alexlarsson alexlarsson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some very minor indentation issues, but otherwise this looks good to me,

common/flatpak-run-wayland.c Outdated Show resolved Hide resolved
common/flatpak-run-wayland.c Outdated Show resolved Hide resolved
Comment on lines 181 to 191
#ifdef ENABLE_WAYLAND_SECURITY_CONTEXT
gboolean security_context_available = FALSE;
if (flatpak_run_add_wayland_security_context_args (bwrap, app_id, instance_id,
&security_context_available))
return TRUE;
if (security_context_available)
return FALSE;
#endif /* ENABLE_WAYLAND_SECURITY_CONTEXT */
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd appreciate a bit of an explanation on what's going on here.

AIUI, this would mean not running with Wayland at all, if a security_context isn't available, thus running on X11; why is that desired? You'd be breaking things like fractional scaling and mixed monitor scales when doing so. And even a Wayland socket without a security_context is leaps better than an X11 socket on its own.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If security contex is available, we should generally never reach this, only if there is some weird error. And in that case the idea is to prefer not to use wayland.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm still not sure on why we'd not prefer to use Wayland. What if a compositor doesn't support the protocol (like an old Mutter) but doesn't provide any iffy protocol extensions? Then this would mean all Flatpak apps run on X11 (if Flatpak is built with security_context support), which would result in a degraded UX.

It seems more appropriate to log the issue and continue on.

Copy link
Contributor Author

@emersion emersion Aug 24, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the compositor doesn't support the protocol, the current logic will just set up a regular Wayland connection. No X11 used.

I've added a comment to make it clearer why the check is written this way.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems the general flow of the code was confusing me. There's flatpak_run_add_wayland_security_context_args, which does all of the security_context and wayland socket setup, and flatpak_run_add_wayland_args, which does the normal wayland stuff.

flatpak_run_add_wayland_args calls flatpak_run_add_wayland_security_context_args to completely set up the socket from here. If the protocol is available but failed to be set up, it'll bail out, running on X11. I would still prefer that to instead log the error and run on Wayland, but w/e.

But I'm not understanding how the rest of the flatpak_run_add_wayland_args function is called if the compositor doesn't support the protocol. Is the rest of the function that falls back to that behavior done in flatpak_run_add_wayland_security_context_args? If so, would be nice to document that.

The confusion comes from the variable being named security_context_available - the final if check on it makes it sound like it's "if security context is available, fail to set up Wayland", when in reality it's just returning the initial value of the variable, FALSE.

It would be nice if the variable could be set to TRUE initially instead, the security context setup has an else case that sets it to FALSE, and then the final check goes to see if the variable is not true, and returns FALSE in that case. That would make it flow a bit nicer.

Also documenting the functions, their flow, and their behavior would be nice, to make it so conversations like this don't crop up again. I don't want this to be a blocker here, so if I can make it better myself, I can follow up with it in a later PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I don't have plans to address your comments. I think the current logic is fine, especially with the comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment does help, and at most, I'd make it a tiny bit more explicit in the event the compositor doesn't support it:

 /* If security-context is available but we failed to set it up, bail out.
  * If the compositor doesn't support security-context, we'll just
  * set up a plain Wayland socket.
  */

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's just repeating what the code already say.

It's well known convention in flatpak that returning true means "success", so if something say

if (try_security_context(&was_it_even_there))
  return true;
if (was_it_even_there)
  return false;

is very clear. The only question is "why", not "what", which could just as well be in the commit message.

The same logic will be used for Wayland security context.
More complicated setup logic will be added next commit.
@emersion
Copy link
Contributor Author

Indentation now fixed!

This exposes a reliable way for Wayland compositors to get
identifying information about a client. Compositors can then
apply security policies if desirable.

See: https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/68
@alexlarsson alexlarsson merged commit f0e626a into flatpak:main Aug 24, 2023
9 checks passed
@emersion emersion deleted the wl-security-context branch August 24, 2023 10:24
@emersion
Copy link
Contributor Author

Thanks a lot!

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

Successfully merging this pull request may close these issues.

None yet

7 participants