screencast: Don't cast remote desktop sessions to screencast
The replace_restore_token_with_data() function is called both for
remote desktop and screencast sessions. However, it was always
casting and using to ScreenCastSession, even when a remote desktop
session was passed. This could lead to memory corruption.
Be more careful when casting the Session object to ScreenCastSession.
Move the casting entirely to inside replace_restore_token_with_data(),
and make sure the only code paths that perform type casting are safely
guarded by either is_remote_desktop_session or is_screen_cast_session
checks.
This is a regression from the screencast restore PR.
Closes https://github.com/flatpak/xdg-desktop-portal/issues/771
Georges Basile Stavracas Neto authored 2 years ago
Phaedrus Leeds committed 2 years ago
576 | 576 | }; |
577 | 577 | |
578 | 578 | static gboolean |
579 | replace_restore_token_with_data (ScreenCastSession *screen_cast_session, | |
579 | replace_restore_token_with_data (Session *session, | |
580 | 580 | GVariant **in_out_options, |
581 | 581 | GError **error) |
582 | 582 | { |
583 | Session *session = (Session *)screen_cast_session; | |
584 | 583 | GVariantBuilder options_builder; |
585 | 584 | g_autoptr(GVariant) options = NULL; |
585 | PersistMode persist_mode; | |
586 | 586 | gsize i; |
587 | 587 | |
588 | 588 | options = *in_out_options; |
589 | 589 | |
590 | if (!g_variant_lookup (options, "persist_mode", "u", &screen_cast_session->persist_mode)) | |
591 | screen_cast_session->persist_mode = PERSIST_MODE_NONE; | |
592 | ||
593 | if (is_remote_desktop_session (session) && screen_cast_session->persist_mode != PERSIST_MODE_NONE) | |
590 | if (!g_variant_lookup (options, "persist_mode", "u", &persist_mode)) | |
591 | persist_mode = PERSIST_MODE_NONE; | |
592 | ||
593 | if (is_remote_desktop_session (session) && persist_mode != PERSIST_MODE_NONE) | |
594 | 594 | { |
595 | 595 | g_set_error (error, XDG_DESKTOP_PORTAL_ERROR, XDG_DESKTOP_PORTAL_ERROR_INVALID_ARGUMENT, |
596 | 596 | "Remote desktop sessions cannot persist"); |
597 | 597 | return FALSE; |
598 | 598 | } |
599 | 599 | |
600 | if (is_screen_cast_session (session)) | |
601 | { | |
602 | ScreenCastSession *screen_cast_session = (ScreenCastSession *)session; | |
603 | screen_cast_session->persist_mode = persist_mode; | |
604 | } | |
605 | ||
600 | 606 | g_variant_builder_init (&options_builder, G_VARIANT_TYPE_VARDICT); |
601 | 607 | for (i = 0; i < G_N_ELEMENTS (screen_cast_select_sources_options); i++) |
602 | 608 | { |
611 | 617 | |
612 | 618 | if (g_strcmp0 (screen_cast_select_sources_options[i].key, "restore_token") == 0) |
613 | 619 | { |
620 | ScreenCastSession *screen_cast_session; | |
614 | 621 | g_autoptr(GVariant) restore_data = NULL; |
615 | 622 | g_autofree char *restore_token = NULL; |
616 | 623 | |
655 | 662 | * apps can pass random UUIDs and yet predict what the next token will |
656 | 663 | * be. |
657 | 664 | */ |
665 | g_assert (is_screen_cast_session (session)); | |
666 | screen_cast_session = (ScreenCastSession *)session; | |
658 | 667 | screen_cast_session->restore_token = g_steal_pointer (&restore_token); |
659 | 668 | |
660 | 669 | g_debug ("Replacing 'restore_token' with portal-specific data"); |
681 | 690 | { |
682 | 691 | Request *request = request_from_invocation (invocation); |
683 | 692 | Session *session; |
684 | ScreenCastSession *screen_cast_session; | |
685 | 693 | g_autoptr(GError) error = NULL; |
686 | 694 | g_autoptr(XdpDbusImplRequest) impl_request = NULL; |
687 | 695 | GVariantBuilder options_builder; |
785 | 793 | * permission store and / or the GHashTable with transient permissions. |
786 | 794 | * Portal implementations do not have access to the restore token. |
787 | 795 | */ |
788 | screen_cast_session = (ScreenCastSession *) session; | |
789 | if (!replace_restore_token_with_data (screen_cast_session, &options, &error)) | |
796 | if (!replace_restore_token_with_data (session, &options, &error)) | |
790 | 797 | { |
791 | 798 | g_dbus_method_invocation_return_gerror (invocation, error); |
792 | 799 | return G_DBUS_METHOD_INVOCATION_HANDLED; |