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

GaloisKeys serialization crash #249

Closed
bcebere opened this issue Dec 6, 2020 · 5 comments
Closed

GaloisKeys serialization crash #249

bcebere opened this issue Dec 6, 2020 · 5 comments

Comments

@bcebere
Copy link

bcebere commented Dec 6, 2020

With the following code snippet, I'm receiving SIGKILL, it seems to be an infinite loop at the save step.

 #include "seal/seal.h"
 
 using namespace std;
 using namespace seal;
 
 std::string SEALSerialize(const GaloisKeys& sealobj) {
     std::stringstream stream;
     sealobj.save(stream);
 
     return stream.str();
 }
 
 GaloisKeys SEALDeserialize(const SEALContext& sealctx, const string& in) {
     GaloisKeys out;
     std::stringstream stream;
     stream << in;
     out.load(sealctx, stream);
     return out;
 }
 
 int main() {
     EncryptionParameters parameters(scheme_type::ckks);
     parameters.set_poly_modulus_degree(8192);
     parameters.set_coeff_modulus(
         CoeffModulus::Create(8192, {40, 21, 21, 21, 21, 21, 21, 40}));
 
     auto ctx = SEALContext(parameters);
     auto keygen = KeyGenerator(ctx);
     auto sk = SecretKey(keygen.secret_key());
 
     GaloisKeys gk;
     keygen.create_galois_keys(gk);
 
     auto serial = SEALSerialize(gk);
     auto new_gk = SEALDeserialize(ctx, serial);
     SEALSerialize(new_gk);
 
     return 0;
 }

My only "custom" flags for the build system are

set(CMAKE_CXX_STANDARD 17)

I ran the test with strace, and it actually shows an infinite loop of mmaps until it crashes.

mmap(NULL, 79695872, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7efbdca7a000
mmap(NULL, 79958016, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7efbd7e39000
mmap(NULL, 80220160, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7efbd31b8000
mmap(NULL, 80482304, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7efbce4f7000
mmap(NULL, 80744448, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7efbc97f6000
mmap(NULL, 81006592, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7efbc4ab5000
mmap(NULL, 81268736, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7efbbfd34000
mmap(NULL, 81530880, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7efbbaf73000
mmap(NULL, 81793024, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7efbb6172000
mmap(NULL, 82055168, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7efbb1331000
mmap(NULL, 82317312, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7efbac4b0000
mmap(NULL, 82579456, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7efba75ef000
mmap(NULL, 82841600, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7efba26ee000
mmap(NULL, 83103744, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7efb9d7ad000
mmap(NULL, 83365888, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7efb9882c000
mmap(NULL, 83628032, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7efb9386b000
mmap(NULL, 83890176, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7efb8e86a000
mmap(NULL, 84152320, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7efb89829000
+++ killed by SIGKILL +++
Killed

Tested with SEAL 3.6. Ubuntu 20.04. gcc 9.3.0
The code was OK with SEAL 3.5.9, I hope I didn't miss something in the updated API.

@kimlaine
Copy link
Contributor

kimlaine commented Dec 8, 2020

Duplicate of #248

@kimlaine kimlaine marked this as a duplicate of #248 Dec 8, 2020
@kimlaine
Copy link
Contributor

kimlaine commented Dec 8, 2020

Thanks for the helpful report!

This was a pretty serious bug in native/src/seal/util/ztools.cpp. Our in-place Zstandard compression didn't update the "read-head" correctly so that the in-place compression basically didn't work, and all output was always written into temporary buffers. Since the output size continues to grow as more data is compressed, a new allocation was always done for each new size temporary buffer. Since these were allocation from a SEAL memory pool, the memory was not released until the function returned, and you ended up with huge memory drain. Linux killed your process because of this.

We'll release v3.6.1 shortly to fix this.

@bcebere
Copy link
Author

bcebere commented Dec 8, 2020

Thank you for the explanation&fix, @kimlaine! 🚀

@kimlaine
Copy link
Contributor

kimlaine commented Dec 8, 2020

3.6.1 is now available. Please let us know if there are further issues.

@bcebere
Copy link
Author

bcebere commented Dec 9, 2020

The issue doesn't reproduce with 3.6.1.

Thank you so much for the quick fix! 👍

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

No branches or pull requests

2 participants