Page MenuHome GnuPG

gnupg2 weird memory fault on NetBSD Loongson/mips64el N32
Open, NormalPublic

Description

Hi,

I've been trying to use NetBSD on my Lemote Yeeloong machine which has a Loongson 2F CPU. Most of the things have been running great except for gnupg2, which can be correctly built but all resulted executable programs will crash when run due to memory issue like the following command line session:

$ gpg2

gpg: signal Segmentation fault caught ... exiting
Segmentation fault

And when running in gdb it gets a weird stack corruption like error. I tried to disable most of the compiler flags like _FORTIFY_SOURCE, --disable-optimization, etc. so that the only flags left are -O0 -ggdb, in order to get a sensible backtrace but got no luck. Please find the gdb session below for details:

$ gdb gpg2
GNU gdb (GDB) 7.12
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.    
This GDB was configured as "mips64el--netbsd".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.   
Find the GDB manual and other documentation resources online at:                         
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from gpg2...done.
(gdb) dir g10                                                                            
Source directories searched: /home/pbulk/tmp/gnupg-2.2.33/g10:$cdir:$cwd
(gdb) dir common                                                                         
Source directories searched: /home/pbulk/tmp/gnupg-2.2.33/common:/home/pbulk/tmp/gnupg-2.2.33/g10:$cdir:$cwd
(gdb) start                                                                              
Temporary breakpoint 1 at 0x190a0: file gpg.c, line 2266.
Starting program: /usr/pkg/bin/gpg2                                                      
                                            
Temporary breakpoint 1, main (argc=1, argv=0x7fff78ec) at gpg.c:2266                     
2266    {                                                                                
(gdb) s                                                                                  
2269        int rc=0;
(gdb)                                                                                    
2276        strlist_t remusr = NULL;
(gdb)                                                                                    
2277        strlist_t locusr = NULL;                                                     
(gdb)                                                                                    
2278        strlist_t nrings = NULL;
(gdb)                       
2279        armor_filter_context_t *afx = NULL;
(gdb)                                 
2280        int detached_sig = 0;
(gdb)                                                                                                                                                                     [48/1520]
2280        int detached_sig = 0;                                                                                                                                                  
(gdb)                                       
2281        char *last_configname = NULL;                                                
(gdb)                                                                                    
                                            
2282        const char *configname = NULL; /* NULL or points to last_configname.         
(gdb)                                       
2285        int debug_argparser = 0;      
(gdb)                                       
2286        int default_keyring = 1;
(gdb)                                                                                    
2287        int greeting = 0;                                                            
(gdb)             
2288        int nogreeting = 0;                                                          
(gdb)                                                                                    
2289        char *logfile = NULL;                                                        
(gdb)                                                                                    
2290        int use_random_seed = 1;
(gdb)                                                                                    
2291        enum cmd_and_opt_values cmd = 0;        
(gdb)                                      
2292        const char *debug_level = NULL;
(gdb)                                                                                    
2294        const char *trustdb_name = NULL;     
(gdb)                 
2296        char *def_cipher_string = NULL;                                              
(gdb)                            
2297        char *def_digest_string = NULL;                                              
(gdb)                                                                                    
2298        char *compress_algo_string = NULL;                                           
(gdb)                                                                                                                                                                              
2299        char *cert_digest_string = NULL;                                             
(gdb)                                                                                    
2300        char *s2k_cipher_string = NULL;                                              
(gdb)                                       
2301        char *s2k_digest_string = NULL;                                              
(gdb)                                                                                    
2302        char *pers_cipher_list = NULL;                                               
(gdb)                
2303        char *pers_digest_list = NULL;                                               
(gdb)                               
2304        char *pers_compress_list = NULL;                                             
(gdb)                                                                                    
2305        int eyes_only=0;                                                             
(gdb)                               
2306        int multifile=0;
(gdb)                                                                                    
2307        int pwfd = -1;            
(gdb)  
2308        int ovrseskeyfd = -1;           
(gdb)                                                                                    
2309        int fpr_maybe_cmd = 0; /* --fingerprint maybe a command.  */                 
(gdb)                                       
2310        int any_explicit_recipient = 0;                                              
(gdb)                                       
2311        int default_akl = 1;          
(gdb)                                       
2312        int require_secmem = 0; 
(gdb)                                                                                    
2313        int got_secmem = 0;                                                          
(gdb)             
2328        early_system_init ();                                                        
(gdb)                                                                                    
early_system_init () at init.c:144                                                       
                                                                                         
144     }                           
(gdb)                                                                                    
main (argc=1, argv=0x7fff78ec) at gpg.c:2329        
2329        gnupg_reopen_std (GPG_NAME);   
(gdb)                                      
gnupg_reopen_std (pgmname=0x19f290 "gpg") at sysutils.c:716                              
716       FILE *complain;                                                                
(gdb)                 
717                                                                                      
(gdb)                            
718       if (fcntl (STDIN_FILENO, F_GETFD) == -1 && errno ==EBADF)                      
(gdb)                                                                                    
721             did_stdin = 1;                                                           
(gdb)                                                                                                                                                                              
729             did_stdout = 1;                                                          
(gdb)                                                                                    
warning: GDB can't find the start of the function at 0x781ea290.                         
                                            
    GDB is unable to find the start of the function at 0x781ea290                        
and thus can't determine the size of that function's stack frame.                        
This means that GDB may be unable to access that stack frame, or                         
the frames below it. 
    This problem is most likely caused by an invalid program counter or                  
stack pointer.                      
    However, if you think GDB should simply search farther back                          
from 0x781ea290 for code which looks like the beginning of a                             
function, you can increase the range of the search using the `set                        
heuristic-fence-post' command.      
0x781ea290 in ?? ()         
(gdb)     

The last stepping in result in a jump to an address that gdb cannot find a function at, however according to the source code there seems to be only a fcntl call which succeeded in previous calls. So I suspect there may be some kind of stack corruption but cannot be sure. It would be great to see if anyone has any idea what's happening and how to solve it.

Gpg2 version:

$ gpg2 --version
gpg (GnuPG) 2.2.33
libgcrypt 1.9.4
Copyright (C) 2021 Free Software Foundation, Inc.
License GNU GPL-3.0-or-later <https://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Home: /home/[..snip..]/.gnupg
Supported algorithms:
Pubkey: RSA, ELG, DSA, ECDH, ECDSA, EDDSA
Cipher: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH,
        CAMELLIA128, CAMELLIA192, CAMELLIA256
Hash: SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224
Compression: Uncompressed, ZIP, ZLIB, BZIP2

Details

Version
2.2.33

Event Timeline

werner added a subscriber: werner.

Given that you are already using libgcrypt 1.9, can you please try gnupg 2.3.4.

it might be worth to try strace instead of gdb. This can give some other clues.

Thanks Werner! As I'm on NetBSD I was able to use ktrace instead, and you can find the output at https://termbin.com/zm2c. (It expires in 1 month. Let me know if you would like me to paste the full output here.)

The relevant part for reference:

29448      1 gpg2     RET   netbsd32_write 35/0x23, 2
29448      1 gpg2     CALL  netbsd32_read(0,0x7803e000,0x2000)
29448      1 gpg2     GIO   fd 0 read 5 bytes
      "Test\n"
29448      1 gpg2     RET   netbsd32_read 5, 3
29448      1 gpg2     CALL  netbsd32_read(0,0x7803e000,0x2000)
29448      1 gpg2     GIO   fd 0 read 0 bytes
      ""
29448      1 gpg2     RET   netbsd32_read 0, 3
29448      1 gpg2     CALL  netbsd32_write(2,0x78028800,5)
29448      1 gpg2     GIO   fd 2 wrote 5 bytes
      "gpg: "
29448      1 gpg2     RET   netbsd32_write 5, 2
29448      1 gpg2     CALL  netbsd32_write(2,0x1abdf8,0x1d)
29448      1 gpg2     GIO   fd 2 wrote 29 bytes
      "no valid OpenPGP data found.\n"
29448      1 gpg2     RET   netbsd32_write 29/0x1d, 2
29448      1 gpg2     PSIG  SIGSEGV caught handler=0x187d9c mask=(11): code=SEGV_MAPERR, addr=0xf0429e0f, trap=4)
29448      1 gpg2     CALL  netbsd32_munmap(0x78698000,0x8000)
29448      1 gpg2     RET   netbsd32_munmap 0, 598/0x256
29448      1 gpg2     CALL  netbsd32_write(2,0x1c8388,1)
29448      1 gpg2     GIO   fd 2 wrote 1 bytes
      "\n"
29448      1 gpg2     RET   netbsd32_write 1, -1454662310/0xa94b9d5a
29448      1 gpg2     CALL  netbsd32_write(2,0x1fc1d8,3)
29448      1 gpg2     GIO   fd 2 wrote 3 bytes
      "gpg"
29448      1 gpg2     RET   netbsd32_write 3, 2081241/0x1fc1d9
29448      1 gpg2     CALL  netbsd32_write(2,0x1c8390,9)
29448      1 gpg2     GIO   fd 2 wrote 9 bytes
      ": signal "
29448      1 gpg2     RET   netbsd32_write 9, 2081241/0x1fc1d9
29448      1 gpg2     CALL  netbsd32_write(2,0x782f7f18,0x12)
29448      1 gpg2     GIO   fd 2 wrote 18 bytes
      "Segmentation fault"
29448      1 gpg2     RET   netbsd32_write 18/0x12, 2016378649/0x782f7f19
29448      1 gpg2     CALL  netbsd32_write(2,0x1c83b0,0x14)
29448      1 gpg2     GIO   fd 2 wrote 20 bytes
      " caught ... exiting\n"
29448      1 gpg2     RET   netbsd32_write 20/0x14, 2016378649/0x782f7f19
29448      1 gpg2     CALL  netbsd32___sigaction_sigtramp(SIGSEGV,0x7fff6c58,0,0x78263bc0,2)
29448      1 gpg2     RET   netbsd32___sigaction_sigtramp 0, 2016378649/0x782f7f19
29448      1 gpg2     CALL  _lwp_self
29448      1 gpg2     RET   _lwp_self 1, 998/0x3e6
29448      1 gpg2     CALL  netbsd32__lwp_kill(1,0xb)
29448      1 gpg2     RET   netbsd32__lwp_kill 0, 998/0x3e6
29448      1 gpg2     CALL  netbsd32_setcontext(0x7fff6d58)
29448      1 gpg2     RET   netbsd32_setcontext JUSTRETURN
29448      1 gpg2     PSIG  SIGSEGV SIG_DFL: code=SI_LWP sent by pid=29448, uid=0)

Unfortunately, gdb session log and ktrace log don't have enough information to locate the cause/problem.

While gdb doesn't work well, could you please try to get backtrace when it gets SEGV? Instead of running step by step, let the program run until SEGV, and type "bt" (backtrace command) to see where it fails.

Hi gniibe,

Unfortunately there is not much useful information for the backtrace because the stack was corrupted. The best I can get is at which line of code that the corruption happened in the first post. See below for the details of the backtrace:

$ gdb gpg2
GNU gdb (GDB) 7.12
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "mips64el--netbsd".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from gpg2...done.
(gdb) dir g10
Source directories searched: /home/pbulk/tmp/gnupg-2.2.33/g10:$cdir:$cwd
(gdb) dir common
Source directories searched: /home/pbulk/tmp/gnupg-2.2.33/common:/home/pbulk/tmp/gnupg-2.2.33/g10:$cdir:$cwd
(gdb) r
Starting program: /usr/pkg/bin/gpg2 
warning: GDB can't find the start of the function at 0x781f1154.

    GDB is unable to find the start of the function at 0x781f1154
and thus can't determine the size of that function's stack frame.
This means that GDB may be unable to access that stack frame, or
the frames below it.
    This problem is most likely caused by an invalid program counter or
stack pointer.
    However, if you think GDB should simply search farther back
from 0x781f1154 for code which looks like the beginning of a
function, you can increase the range of the search using the `set
heuristic-fence-post' command.

Program received signal SIGSEGV, Segmentation fault.
0x781f1154 in ?? ()
(gdb) bt
#0  0x781f1154 in ?? ()
(gdb) 
werner triaged this task as Normal priority.Thu, Jan 20, 8:20 PM