Page MenuHome GnuPG

Kleopatra: system error without error code when encrypting a file to full disk on Windows
Open, NormalPublic

Description

Encrypt a large file in Kleopatra thereby causing the disk to run out of space.
In more than half a dozen tries I got only once "no space left on device", all the other tries are "Signieren Fehlgeschlagen, Systemfehler ohne gesetzten Systemfehlercode" if did sign+encrypt and "Verschlüsseln fehlgeschlagen, Systemfehler ohne gesetzten Systemfehlercode" if I did choose encrypt only.

Expected: Always the message "no space left on device"

Debugview shows:

[5888] org.kde.pim.kleopatra: Task:  "5G.txt"  has no total progress set. 
[5888] org.kde.pim.kleopatra: Kleo::Crypto::SignEncryptTask(0x11613ed0) slotResult job: QGpgME::QGpgMESignEncryptJob(0x6c00650) signing result: "GpgME::SigningResult(\n error:              GpgME::Error(117456893 (Systemfehler ohne gesetzten Systemfehlercode))\n createdSignatures:\n invalidSigningKeys:\n)" encryption result: "GpgME::EncryptionResult(\n error:        GpgME::Error(117456893 (Systemfehler ohne gesetzten Systemfehlercode))\n invalid recipients:\n)"
[5888] org.kde.pim.kleopatra: 0x114e0528
[5888] org.kde.pim.kleopatra: 0x114e0528
[5888] org.kde.pim.kleopatra: 
[5888] inputError : "Unbekannter Fehler" 
[5888] outputError: "Es steht nicht genug Speicherplatz auf dem Datenträger zur Verfügung."
[5888] org.kde.pim.kleopatra: Collection Progress:  1000  total:  1000

gpgme debug:

4 - 2023-10-13 11:49:59 gpgme[5888.1e5c]:         _gpgme_data_inbound_handler: enter: dh=0x069b9f38 fd=4
4 - 2023-10-13 11:49:59 gpgme[5888.1e5c]:           gpgme_data_write: enter: dh=0x069b9f38 buffer=0x0e32ea20, size=4095
4 - 2023-10-13 11:49:59 gpgme[5888.1e5c]:           gpgme_data_write:422: error: No error (0)\n
4 - 2023-10-13 11:49:59 gpgme[5888.1e5c]:         _gpgme_data_inbound_handler:664: error: Systemfehler ohne gesetzten Systemfehlercode <GPGME>\n
4 - 2023-10-13 11:49:59 gpgme[5888.1e5c]:         _gpgme_cancel_with_err: enter: ctx=0x03edc190 ctx_err=117456893, op_err=0
4 - 2023-10-13 11:49:59 gpgme[5888.1e5c]:             _gpgme_remove_io_cb: call: data=0x06c277b8 setting fd 0x0 (item=0x06c27620) done
4 - 2023-10-13 11:49:59 gpgme[5888.1e5c]:             _gpgme_remove_io_cb: call: data=0x06c27878 setting fd 0x2 (item=0x06c282b0) done
4 - 2023-10-13 11:49:59 gpgme[5888.1e5c]:             _gpgme_remove_io_cb: call: data=0x06c28730 setting fd 0x4 (item=0x06c28598) done
4 - 2023-10-13 11:49:59 gpgme[5888.1e5c]:             _gpgme_remove_io_cb: call: data=0x06c28820 setting fd 0x7 (item=0x06c28958) done
4 - 2023-10-13 11:49:59 gpgme[5888.1e5c]:           gpgme:gpg_io_event: call: gpg=0x03ed0460 event 0x6f489437, type 1, type_data 0x0e32faa4
4 - 2023-10-13 11:49:59 gpgme[5888.1e5c]:         _gpgme_cancel_with_err: leave: 
4 - 2023-10-13 11:49:59 gpgme[5888.1e5c]:       gpgme_op_encrypt_sign:175: error: Systemfehler ohne gesetzten Systemfehlercode <GPGME>\n

Tobias analysed this (https://dev.gnupg.org/T6526#177080):

What seems to be happening here is that gpgme reads the errror from errno during write (specifically, this is read from the last gpg_error_from_syserror() in _gpgme_data_inbound_handler() in src/data.c), but this isn't set anywhere. The write operation here is done through the qt parts of gpgme, which ultimately is a WriteFile() in qfsfileengine_win.cpp in qtbase that always leaves errno as 0, apparently.

Adding a patch like below to qtbase makes Kleopatra report the error correctly, but is of course not a solution since it would report every error as ENOSPC.

diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp
index dd4882a..2ea027b 100644
--- a/src/corelib/io/qfsfileengine_win.cpp
+++ b/src/corelib/io/qfsfileengine_win.cpp
@@ -392,6 +392,7 @@ qint64 QFSFileEnginePrivate::nativeWrite(const char *data, qint64 len)
             if (totalWritten == 0) {
                 // Note: Only return error if the first WriteFile failed.
                 q->setError(QFile::WriteError, qt_error_string());
+                errno = ENOSPC;
                 return -1;
             }
             break;

This doesn't quite explain why it worked once for Eva, though. There's a second code path for file writing on windows in qt that does use the normal fwrite, but I don't know why it would randomly use that one time when it used the other code path the rest of the time.

Details

Version
VS-Desktop-3.1.90.246-Beta

Event Timeline

ebo triaged this task as Normal priority.Oct 18 2023, 1:54 PM
ebo created this task.
ikloecker renamed this task from Kleopatra: system error withut error code when enrypting to full disk on windows to Kleopatra: system error without error code when encrypting a file to full disk on Windows.Oct 18 2023, 3:04 PM

Here's a patch that should fix this. It's not amazing since we have to copy the map_w32_to_errno from libgpg-error, as it's not public API there.

Should we have a gpg_error_from_w32() as companion to gpg_error_from_syserror() ?

Should we have a gpg_error_from_w32() as companion to gpg_error_from_syserror() ?

sounds like a good idea, considering that we might face similar problems in other places as well.

Alternatively, the patches attached here export the already existing gpgrt_w32_get_last_err_code function from gpg-error and use that to read the error.