Bug 5292

Summary: SIGSEGV при запуске 'openssl ca'
Product: Sisyphus Reporter: Vladimir Lettiev <crux>
Component: opensslAssignee: Gleb F-Malinovskiy <glebfm>
Status: CLOSED FIXED QA Contact: qa-sisyphus
Severity: normal    
Priority: P2 CC: glebfm
Version: unstable   
Hardware: all   
OS: Linux   

Description Vladimir Lettiev 2004-10-05 23:40:37 MSD
$ openssl ca
Using configuration from /var/lib/ssl/openssl.cnf
Error opening CA private key ./demoCA/private/cakey.pem
10410:error:0E06D06C:configuration file routines:NCONF_get_string:no
value:conf_lib.c:329:group=CA_default name=unique_subject
10410:error:02001002:system library:fopen:No such file or
directory:bss_file.c:276:fopen('./demoCA/private/cakey.pem','r')
10410:error:20074002:BIO routines:FILE_CTRL:system lib:bss_file.c:278:
unable to load CA private key
Segmentation fault

Воспроизводится на двух машинах (openssl-0.9.7d-alt1). Судя по strace очевидна
какая-то проблема(?) с загрузкой /lib/libcrypto.so.4. Вот собственно вывод strace:

execve("/usr/bin/openssl", ["openssl", "ca"], [/* 54 vars */]) = 0
uname({sys="Linux", node="localhost.localdomain", ...}) = 0
brk(0)                                  = 0x8099f2c
open("/etc/ld.so.preload", O_RDONLY)    = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY)      = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=66147, ...}) = 0
mmap2(NULL, 66147, PROT_READ, MAP_PRIVATE, 3, 0) = 0x124000
close(3)                                = 0
open("/lib/libssl.so.4", O_RDONLY)      = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\320\203"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0644, st_size=194616, ...}) = 0
mmap2(NULL, 195312, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x135000
mmap2(0x162000, 12288, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x2d) = 0x162000
close(3)                                = 0
open("/lib/libcrypto.so.4", O_RDONLY)   = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\220\275"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0644, st_size=1008748, ...}) = 0
mmap2(NULL, 1022488, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) =
0x165000
mmap2(0x24a000, 69632, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0xe5) = 0x24a000
mmap2(0x25b000, 14872, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x25b000
close(3)                                = 0
mprotect(0xbffff000, 4096, PROT_READ|PROT_WRITE|PROT_EXEC|PROT_GROWSDOWN) = -1
EINVAL (Invalid argument)
mprotect(0xbfff8000, 32768, PROT_READ|PROT_WRITE|PROT_EXEC) = -1 ENOMEM (Cannot
allocate memory)
mprotect(0xbfffc000, 16384, PROT_READ|PROT_WRITE|PROT_EXEC) = -1 ENOMEM (Cannot
allocate memory)
mprotect(0xbfffe000, 8192, PROT_READ|PROT_WRITE|PROT_EXEC) = 0
mprotect(0xbfffc000, 8192, PROT_READ|PROT_WRITE|PROT_EXEC) = -1 ENOMEM (Cannot
allocate memory)
mprotect(0xbfffd000, 4096, PROT_READ|PROT_WRITE|PROT_EXEC) = -1 ENOMEM (Cannot
allocate memory)
open("/lib/libdl.so.2", O_RDONLY)       = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0P\32\0\000"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=9532, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x25f000
mmap2(NULL, 12412, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x260000
mmap2(0x262000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE,
3, 0x1) = 0x262000
close(3)                                = 0
open("/lib/libc.so.6", O_RDONLY)        = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\320Q\1"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=1094832, ...}) = 0
mmap2(NULL, 1101572, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) =
0x264000
mmap2(0x36b000, 16384, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x107) = 0x36b000
mmap2(0x36f000, 7940, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS,
-1, 0) = 0x36f000
close(3)                                = 0
mprotect(0x36b000, 4096, PROT_READ)     = 0
munmap(0x124000, 66147)                 = 0
brk(0)                                  = 0x8099f2c
brk(0x80baf2c)                          = 0x80baf2c
brk(0)                                  = 0x80baf2c
brk(0x80bb000)                          = 0x80bb000
rt_sigaction(SIGPIPE, {SIG_IGN}, {SIG_DFL}, 8) = 0
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
open("/var/lib/ssl/openssl.cnf", O_RDONLY) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=7809, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x124000
read(3, "#\n# OpenSSL example configuratio"..., 4096) = 4096
read(3, "_name ]\ncountryName\t\t\t= Country "..., 4096) = 3713
read(3, "", 4096)                       = 0
close(3)                                = 0
munmap(0x124000, 4096)                  = 0
open("/etc/mtab", O_RDONLY)             = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=392, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x124000
read(3, "/dev/hda5 / ext3 rw 0 0\nproc /pr"..., 4096) = 392
close(3)                                = 0
munmap(0x124000, 4096)                  = 0
open("/proc/meminfo", O_RDONLY)         = 3
fstat64(3, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x124000
read(3, "        total:    used:    free:"..., 4096) = 522
close(3)                                = 0
munmap(0x124000, 4096)                  = 0
rt_sigaction(SIGPIPE, {SIG_IGN}, {SIG_IGN}, 8) = 0
getpid()                                = 4412
getpid()                                = 4412
write(2, "Using configuration from /var/li"..., 50) = 50
getpid()                                = 4412
getpid()                                = 4412
open("/var/lib/ssl/openssl.cnf", O_RDONLY) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=7809, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x124000
read(3, "#\n# OpenSSL example configuratio"..., 4096) = 4096
read(3, "_name ]\ncountryName\t\t\t= Country "..., 4096) = 3713
read(3, "", 4096)                       = 0
close(3)                                = 0
munmap(0x124000, 4096)                  = 0
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
socket(PF_FILE, SOCK_STREAM, 0)         = 3
connect(3, {sa_family=AF_FILE, path="/home/crux/.rnd"}, 17) = -1 ECONNREFUSED
(Connection refused)
close(3)                                = 0
stat64("/home/crux/.rnd", {st_mode=S_IFREG|0600, st_size=1024, ...}) = 0
open("/home/crux/.rnd", O_RDONLY)       = 3
fstat64(3, {st_mode=S_IFREG|0600, st_size=1024, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x124000
read(3, "\"\302W\10\7\30\204wD\10;\256\314\317cnO\220\233\6\345"..., 4096) = 1024
read(3, "", 4096)                       = 0
close(3)                                = 0
munmap(0x124000, 4096)                  = 0
getpid()                                = 4412
getpid()                                = 4412
open("./demoCA/private/cakey.pem", O_RDONLY) = -1 ENOENT (No such file or directory)
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
write(2, "Error opening CA private key ./d"..., 56) = 56
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
write(2, "4412:error:0E06D06C:configuratio"..., 126) = 126
getpid()                                = 4412
write(2, "4412:error:02001002:system libra"..., 122) = 122
getpid()                                = 4412
write(2, "4412:error:20074002:BIO routines"..., 70) = 70
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
write(2, "unable to load CA private key\n", 30) = 30
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
stat64("/home/crux/.rnd", {st_mode=S_IFREG|0600, st_size=1024, ...}) = 0
open("/home/crux/.rnd", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
chmod("/home/crux/.rnd", 0600)          = 0
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
open("/dev/urandom", O_RDONLY|O_NONBLOCK|O_NOCTTY) = 4
select(5, [4], NULL, NULL, {0, 10000})  = 1 (in [4], left {0, 10000})
read(4, "\"+\241 \302\216R^0\\\2075d~`Y8G`\33\7\235.$u\271vs\210"..., 32) = 32
close(4)                                = 0
getpid()                                = 4412
getpid()                                = 4412
getuid32()                              = 500
getpid()                                = 4412
time(NULL)                              = 1096994452
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
getpid()                                = 4412
fstat64(3, {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x124000
write(3, "&&\300EzDV\1jU1\260\302\1\354\316\263\3\325\313m_\32L\310"..., 1024) =
1024
close(3)                                = 0
munmap(0x124000, 4096)                  = 0
--- SIGSEGV (Segmentation fault) @ 0 (0) ---
+++ killed by SIGSEGV +++
Comment 1 Vladimir Lettiev 2004-10-08 11:21:53 MSD
Сделаю ещё несколько уточнений.

Вот сообщения от gdb:

[crux@host1 crux]$ gdb --args openssl ca
....
(gdb) run
Starting program: /usr/bin/openssl ca
Error while mapping shared library sections:
: Success.
Error while reading shared library symbols:
: No such file or directory.
(no debugging symbols found)...(no debugging symbols found)...(no debugging
symbols found)...(no debugging symbols found)...(no debugging symbols
found)...Error while reading shared library symbols:
: No such file or directory.
Error while reading shared library symbols:
: No such file or directory.
Using configuration from /var/lib/ssl/openssl.cnf
Error opening CA private key ./demoCA/private/cakey.pem
31882:error:0E06D06C:configuration file routines:NCONF_get_string:no
value:conf_lib.c:329:group=CA_default name=unique_subject
31882:error:02001002:system library:fopen:No such file or
directory:bss_file.c:276:fopen('./demoCA/private/cakey.pem','r')
31882:error:20074002:BIO routines:FILE_CTRL:system lib:bss_file.c:278:
unable to load CA private key

Program received signal SIGSEGV, Segmentation fault.
0x0807bdda in password_callback ()
(gdb) where
#0  0x0807bdda in password_callback ()
#1  0x0805fe76 in ?? ()
#2  0x00000000 in ?? ()

Т.о. SIGSEGV получаем в функции password_callback().

Дальше я попробовал проанализировать эту фунцию и вывод strace, в итоге пришёл к
заключению (может я и не прав кончено):

в password_callback() есть код:

if (password)
        {
        res = strlen(password);
        if (res > bufsiz)
                res = bufsiz;
        memcpy(buf, password, res);
        return res;
        }

При этом функция не проверяет равна ли buf NULL. Судя по выводу strace там как
раз такое и происходит:
mmap2(NULL, 131072, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) =
0x40266000

Если я прав, то получается, что все приложения завязанные на libssl могут
сегфолтится при определённых условиях?
Comment 2 Vladimir Lettiev 2004-10-09 10:22:35 MSD
GDB увёл меня в совершенно левую сторону...

Следующий патч лечит данный сегфолт (проверено):

--- openssl-0.9.7d-orig/apps/ca.c       2004-03-08 16:07:07 +0300
+++ openssl-0.9.7d/apps/ca.c    2004-10-09 10:05:38 +0400
@@ -1503,7 +1503,8 @@
        if (free_key && key)
                OPENSSL_free(key);
        BN_free(serial);
-       free_index(db);
+       if (db != NULL)
+               free_index(db);
        EVP_PKEY_free(pkey);
        X509_free(x509);
        X509_CRL_free(crl);


Проблема в том, что перед вызовом функции OPENSSL_free() (ака CRYPTO_free)
требуется проверить параметр на значение NULL иначе сегфолт неизбежен. Посмотрев
исходники прораммы часто можно увидеть такие виды вызовов:
if (a) OPENSSL_free(a);
if (a != NULL) OPENSSL_free(a);
но ещё чаще таких проверок не делается (как и в случае, описанном выше).
Comment 3 Dmitry V. Levin 2005-06-17 19:42:46 MSD
In openssl-0.9.7g, free_index() checks its arguments and handles NULL properly.