wxsqlite3 icon indicating copy to clipboard operation
wxsqlite3 copied to clipboard

Calling sqlite_key () function returns slowly.

Open liuxu-cmyk opened this issue 6 months ago • 1 comments

After the linux system is powered on, calling sqlite3_open function and calling sqlite_key function, it is found that calling sqlite_key returns very slowly, and the reason is that the value of/proc/sys/kernel/random/entropy _ avail has not reached 128. In this case, how can I make sqlite_key return quickly?

liuxu-cmyk avatar Jun 10 '25 06:06 liuxu-cmyk

Could you please provide more detailed information about your environment?

  • Which Linux distribution are you using?
  • Which version of wxSQLite3 are you using?
  • Which version of wxWidgets are you using?
  • Which compiler version are you using?
  • Which cipher scheme of wxSQLite3 are you using?

After the linux system is powered on, calling sqlite3_open function and calling sqlite_key function, it is found that calling sqlite_key returns very slowly, and the reason is that the value of/proc/sys/kernel/random/entropy _ avail has not reached 128.

Hm, usually the number of available entropy bytes is only low in a very early stage of system initialization. It is not very typical for wxWidgets-based applications to be called that early during system start. At least up to now you are the first reporting such a problem. Could you please describe the nature of your application?

In this case, how can I make sqlite_key return quickly?

First, it would be necessary to know, which method to retrieve entropy is used. Could you provide a call stack, so that it becomes clear which implementation within function entropy() is used? The code of function entropy() looks like this:

static size_t entropy(void* buf, size_t n)
{
#if defined(__APPLE__) && MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
  if (SecRandomCopyBytes(kSecRandomDefault, n, (uint8_t*) buf) == 0)
    return n;
#elif defined(__linux__) && defined(SYS_getrandom)
  if (syscall(SYS_getrandom, buf, n, 0) == n)
    return n;
#elif defined(__linux__) && defined(SYS_getentropy)
  if (syscall(SYS_getentropy, buf, n) == 0)
    return n;
#endif
  return read_urandom(buf, n);

For Linux systems there are 3 possibilities:

  1. syscall(SYS_getrandom,...)
  2. syscall(SYS_getentropy,...)
  3. read_urandom(buf, n)

Which one is it in your case?

Actually, only 44 bytes of entropy are asked for in the underlying code of wxSQLite3. So, it is unclear why your system blocks until /proc/sys/kernel/random/entropy_avail has reached 128 - at least this variable is not queried by wxSQLite3 itself..

utelle avatar Jun 10 '25 09:06 utelle

Closing, because no further details were provided. IMHO there nothing wrong with wxSQLite3 here.

utelle avatar Jun 26 '25 08:06 utelle

Sorry, I replied earlier, but maybe because of network problems, I didn't update the content of the reply to github. The following is my last reply. Calling the sqlite_key () function returns a slow thank-you reply. I found that the entropy function came to the branch of # elifdefined (Linux)&& defined (sys _ getrandom) by using printf to print logs. Then it got stuck here for 2 minutes.

The kernel version is 4.19. gcc version:9.4.0 Database version: 3.47.1 I don't know the rest of the versions. I changed syscall(SYS_getrandom,bufmn,0) to read_urandom(buf,n). There is no problem after such modification.

liuxu-cmyk avatar Jun 26 '25 10:06 liuxu-cmyk

At present, I have also encountered a problem. When calling the sqlite_key function during system startup, this log display occasionally appears. Setting key failed,Encryption is not supported by the VFS 。 The probability of this log appearing is very low.

liuxu-cmyk avatar Jun 26 '25 10:06 liuxu-cmyk

Sorry, I replied earlier, but maybe because of network problems, I didn't update the content of the reply to github.

Well, as you could check for yourself, your reply wasn't visible on GitHub.

The following is my last reply. Calling the sqlite_key () function returns a slow thank-you reply.

What do you mean by "thank-you" reply. sqlite3_key() returns SQLITE_OK(= 0) in case of success.

I found that the entropy function came to the branch of # elifdefined (Linux)&& defined (sys _ getrandom) by using printf to print logs. Then it got stuck here for 2 minutes.

As far as I know getrandom blocks, if not enough entropy is available. But this should usually only happen, if you call it very early during system startup. I don't have the slightest idea, why this takes 2 minutes.

The kernel version is 4.19.

This is really a very old kernel version. The LTS release reached its end of life (EOL) in December 2024. There seems to be a SLTS release, which gets support until January 2029. However, this old kernel version could well be the cause of the problems you experience.

gcc version:9.4.0

The C compiler version is less important, although it is also quite dated.

Database version: 3.47.1

There was never a release of wxSQLite3 combined with SQLite 3.47.1. Therefore I suspect that you actually use SQLite3 Multiple Ciphers 1.9.1.

In principle, you can continue to use that version. However, both SQLite and SQLite3 Multiple Ciphers received important updates in the meantime.

I don't know the rest of the versions.

I understand that regarding wxSQLite3 and wxWidgets, because most likely you are not using them at all. However, you should be able to tell, which Linux distribution you are using.

I changed syscall(SYS_getrandom,bufmn,0) to read_urandom(buf,n). There is no problem after such modification.

As said above, I suspect that the problem may be related to the dated kernel version of your system.

utelle avatar Jun 26 '25 15:06 utelle

At present, I have also encountered a problem. When calling the sqlite_key function during system startup, this log display occasionally appears. Setting key failed,Encryption is not supported by the VFS 。 The probability of this log appearing is very low.

Without knowing what exactly your application is doing, it is nearly impossible to guess what is going on. However, another user detected end of February a race condition in a multi-threaded environment. The issue was fixed in SQLite3 Multiple Ciphers 2.1.0.

Maybe upgrading to the latest version (2.1.3) solves this issue.

utelle avatar Jun 26 '25 15:06 utelle

The kernel version is 4.19. [...]

As said above, I suspect that the problem may be related to the dated kernel version of your system.

In the meantime I did some research. AFAICT it is definitely a kernel issue. For kernel versions below 5.6 the getrandom method blocks, until the CRNG is fully initialized - and that can take quite a while. For kernel versions 5.6 and above getrandom does block only until enough random data is available, not until CRNG is fully initialized. However, this means that the random data retrieved are potentially cryptographically insecure (by the way, the same holds true for reading /dev/urandom).

In theory, it would be possible to detect the kernel version at runtime and to call getrandom only, if the kernel version is 5.6 or higher. However, you are the first and only user reporting this issue. Therefore, you are free to implement such a check on your own, if you really have to stick with kernel version 4.19, but I don't intend to add such a check in the official source base of SQLite3 Multiple Ciphers.

Conclusion: use one of the following approaches:

  1. Live with the application blocking until CRNG is fully initialized
  2. Upgrade your system to a kernel version 5.6 or higher
  3. Remove the code for calling getrandom and use read_urandom instead
  4. Add a check for the kernel version and call read_urandom if the version is below 5.6

utelle avatar Jun 27 '25 09:06 utelle

The kernel version is 4.19. [...]

As said above, I suspect that the problem may be related to the dated kernel version of your system.

In the meantime I did some research. AFAICT it is definitely a kernel issue. For kernel versions below 5.6 the getrandom method blocks, until the CRNG is fully initialized - and that can take quite a while. For kernel versions 5.6 and above getrandom does block only until enough random data is available, not until CRNG is fully initialized. However, this means that the random data retrieved are potentially cryptographically insecure (by the way, the same holds true for reading /dev/urandom).

In theory, it would be possible to detect the kernel version at runtime and to call getrandom only, if the kernel version is 5.6 or higher. However, you are the first and only user reporting this issue. Therefore, you are free to implement such a check on your own, if you really have to stick with kernel version 4.19, but I don't intend to add such a check in the official source base of SQLite3 Multiple Ciphers.

Conclusion: use one of the following approaches:

  1. Live with the application blocking until CRNG is fully initialized
  2. Upgrade your system to a kernel version 5.6 or higher
  3. Remove the code for calling getrandom and use read_urandom instead
  4. Add a check for the kernel version and call read_urandom if the version is below 5.6

==>The kernel version can't be updated for the time being. I'll adopt read_urandom for the time being.

liuxu-cmyk avatar Jun 27 '25 09:06 liuxu-cmyk

At present, I have also encountered a problem. When calling the sqlite_key function during system startup, this log display occasionally appears. Setting key failed,Encryption is not supported by the VFS 。 The probability of this log appearing is very low.

Without knowing what exactly your application is doing, it is nearly impossible to guess what is going on. However, another user detected end of February a race condition in a multi-threaded environment. The issue was fixed in SQLite3 Multiple Ciphers 2.1.0.

Maybe upgrading to the latest version (2.1.3) solves this issue.

==》I guess it may also be caused by multithreading. I will use the latest code to confirm.

liuxu-cmyk avatar Jun 27 '25 09:06 liuxu-cmyk