Skip to content

fix(secure_storage): fix silent error swallowing in GError handling - #242

Draft
aki1770-del wants to merge 1 commit into
toyota-connected:v2.0from
aki1770-del:fix/secure-storage-gerror-handling
Draft

fix(secure_storage): fix silent error swallowing in GError handling#242
aki1770-del wants to merge 1 commit into
toyota-connected:v2.0from
aki1770-del:fix/secure-storage-gerror-handling

Conversation

@aki1770-del

Copy link
Copy Markdown
Contributor

Problem

keyring.h uses the following pattern in storeToKeyring and
readFromKeyring:

std::unique_ptr<GError> err = nullptr;
GError* errPtr = err.get();                 // errPtr == nullptr
secret_password_storev_sync(..., &errPtr);  // libsecret writes into errPtr
if (err) { ... }                            // always false — err never updated

errPtr = err.get() copies the null pointer value into a local variable.
GLib writes a newly-allocated GError* into *(&errPtr) — the local
variable — not into the unique_ptr. The unique_ptr is never updated.

Consequences:

  • libsecret write/read errors are silently swallowed
  • The function returns true (success) when the underlying operation failed
  • Any GError* written into errPtr by libsecret is leaked

Fixes #230

Changes

File: plugins/secure_storage/keyring.h
Methods: storeToKeyring, readFromKeyring

Replace std::unique_ptr<GError> err + GError* errPtr with a plain
GError* err, pass &err directly to the libsecret API, copy the
message string before g_clear_error, then throw.

This brings keyring.h into line with the GError* pattern already
used in this repo — flatpak_shim.cc (two sites) and video_player.cc
(one site). No new pattern is introduced.

Fix Pattern

// Before (broken — err always null, errPtr leaked):
std::unique_ptr<GError> err = nullptr;
GError* errPtr = err.get();
secret_password_storev_sync(..., &errPtr);
if (err) { throw std::runtime_error(err->message); }

// After (correct — matches existing repo pattern):
GError* err = nullptr;
secret_password_storev_sync(..., &err);
if (err) {
  std::string msg = err->message;  // copy before g_clear_error frees the struct
  g_clear_error(&err);
  throw std::runtime_error(msg);
}

Verification

  • Success path: err remains null — behavior unchanged from the caller's
    perspective
  • Error path: err is correctly set by libsecret; message is copied before
    g_clear_error frees the struct; g_clear_error resolves the memory leak;
    exception is thrown with the correct message
  • Callers catching std::runtime_error are unaffected — exception contract
    is unchanged
  • No includes added or removed

Signed-off-by: aki1770-del aki1770@gmail.com

@aki1770-del
aki1770-del marked this pull request as draft August 30, 2026 05:33
@aki1770-del

Copy link
Copy Markdown
Contributor Author

Please don't merge this one — I've moved it to draft.

The change makes a dead throw live. Today err in keyring.h is never reassigned (the callee fills a copy), so both if (err) are false and both throws are unreachable. Fixing that makes them reachable, and there is nothing to catch them: messages.cc has no catch and carries #undef _HAS_EXCEPTIONS at :7, the Flutter C++ client wrapper has none, and the seven in shell/ are on other paths. It reaches the engine's C callback, so std::terminate.

A keyring failure would go from returning a wrong answer to ending the homescreen process. On a head unit that is worse than the bug.

The silent success is also not in the file this PR touches: messages.cc:69/79/83 call api->write(), which returns void, then report true unconditionally. That is Pigeon-generated.

Nothing needed from you. Reworking it against #230.

std::unique_ptr<GError> err initialized to nullptr, followed by
GError* errPtr = err.get(), produces errPtr == nullptr. GLib APIs
write the new GError* into *&errPtr (a local variable), not into
the unique_ptr. The unique_ptr remains null; if (err) is always
false: libsecret errors are silently swallowed, the function may
return true on failure, and any GError allocated by libsecret
is never freed.

Brings keyring.h into line with the GError* + g_clear_error pattern
already used in flatpak_shim.cc and video_player.cc in this repo.
Applied to both storeToKeyring and readFromKeyring.

Fixes toyota-connected#230

Signed-off-by: Akihiko Komada <aki1770@gmail.com>
@aki1770-del
aki1770-del force-pushed the fix/secure-storage-gerror-handling branch from 6620807 to cf96cb3 Compare August 30, 2026 10:16
@aki1770-del aki1770-del closed this Sep 1, 2026
@aki1770-del aki1770-del reopened this Sep 1, 2026
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.

Unsafe GError Handling — std::unique_ptr<GError> Misuse

1 participant