Bug 597221

Summary: rngd -r /dev/urandom segfaults
Product: Red Hat Enterprise Linux 6 Reporter: David Howells <dhowells>
Component: rng-toolsAssignee: David Howells <dhowells>
Status: CLOSED CURRENTRELEASE QA Contact:
Severity: urgent Docs Contact:
Priority: urgent    
Version: 6.0CC: borgan, syeghiay, vbenes
Target Milestone: beta   
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: rng-tools-2.7.el6 Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2010-07-02 19:49:34 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On:    
Bug Blocks: 591154    
Attachments:
Description Flags
Fix compile warnings and SEGV in rngd
none
Make do_loop() correctly interpret the return value of iter->xread() none

Description David Howells 2010-05-28 12:36:10 UTC
Description of problem:

When I try to run "rngd -r /dev/urandom" or "rngd -f -r /dev/urandom" it dies immediately with a SEGV.


Version-Release number of selected component (if applicable):

rng-tools-2-6.el6.i686

How reproducible:

100%

Steps to Reproduce:
1. Run "rngd -f -r /dev/urandom"
  
Actual results:

[root@andromeda ~]# rngd -f -r /dev/urandom 
Segmentation fault (core dumped)

Also, more importantly, it SEGV's when put into the background, though it does this after forking:

[root@andromeda ~]# rngd -r /dev/urandom 
[root@andromeda ~]# pidof rngd
[root@andromeda ~]# 

Expected results:

Should just run happily forever.

Comment 1 David Howells 2010-05-28 12:39:01 UTC
This is needed on systems used to build kernels that use module signing because the kernel build creates a new GPG key each time, and requires random data to do it.  If it can't get sufficient the random data immediately, it will just stall until it can.

Comment 3 David Howells 2010-05-28 13:17:11 UTC
(gdb) r -f -r /dev/urandom 
Starting program: /sbin/rngd -f -r /dev/urandom

Program received signal SIGSEGV, Segmentation fault.
0x00000002 in ?? ()
(gdb) bt
#0  0x00000002 in ?? ()
#1  0x08048a76 in do_loop (random_step=64, poll_timeout=60) at rngd.c:217
#2  0x08048c2f in main (argc=4, argv=0xbffff744) at rngd.c:262
(gdb) up
#1  0x08048a76 in do_loop (random_step=64, poll_timeout=60) at rngd.c:217
217                             retval = iter->xread(buf, sizeof buf, iter);
(gdb) p iter
$1 = (struct rng *) 0xbffff63c
(gdb) p *iter
$2 = {rng_name = 0x91735f4 <Address 0x91735f4 out of bounds>, 
  rng_fd = 134519317, xread = 0x2, fipsctx = 0xcbe73567, next = 0x0}
(gdb) list
212
213             for (;;) {
214                     struct rng *iter;
215                     for (iter = rng_list; iter; iter = iter->next)
216                     {
217                             retval = iter->xread(buf, sizeof buf, iter);
218                             if (retval > 0)
219                                     update_kernel_random(random_step,
220                                                          poll_timeout, buf,
221                                                          iter->fipsctx);

Comment 4 David Howells 2010-05-28 13:29:01 UTC
Starting program: /sbin/rngd 

Breakpoint 1, main (argc=1, argv=0xbffff754) at rngd.c:232
232             argp_parse(&argp, argc, argv, 0, 0, arguments);
(gdb) p rng_list
$3 = (struct rng *) 0x675f5f00


Shouldn't rng_list be allocated from .bss and so be NULL at this point?


(gdb) i files
...
        0x0804b6a4 - 0x0804b6b8 is .bss
        0x0804b6b8 - 0x0804b81c is .dynstr
...
(gdb) p &rng_list
$1 = (struct rng **) 0x804b6b8

Comment 5 David Howells 2010-05-28 13:32:35 UTC
[root@andromeda rng-tools-2]# valgrind ./rngd -f -r /dev/urandom 
==21664== Memcheck, a memory error detector
==21664== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==21664== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info
==21664== Command: ./rngd -f -r /dev/urandom
==21664== 
==21664== Use of uninitialised value of size 4
==21664==    at 0x8048A73: do_loop (rngd.c:217)
==21664==    by 0x8048D2E: main (rngd.c:262)
==21664== 
==21664== Jump to the invalid address stated on the next line
==21664==    at 0x2: ???
==21664==    by 0x8048D2E: main (rngd.c:262)
==21664==  Address 0x2 is not stack'd, malloc'd or (recently) free'd
==21664== 
==21664== 
==21664== Process terminating with default action of signal 11 (SIGSEGV)
==21664==  Bad permissions for mapped region at address 0x2
==21664==    at 0x2: ???
==21664==    by 0x8048D2E: main (rngd.c:262)
==21664== 
==21664== HEAP SUMMARY:
==21664==     in use at exit: 136 bytes in 1 blocks==21664==   total heap usage: 2 allocs, 1 frees, 557 bytes allocated
==21664== 
==21664== LEAK SUMMARY:
==21664==    definitely lost: 0 bytes in 0 blocks
==21664==    indirectly lost: 0 bytes in 0 blocks
==21664==      possibly lost: 0 bytes in 0 blocks
==21664==    still reachable: 136 bytes in 1 blocks
==21664==         suppressed: 0 bytes in 0 blocks
==21664== Rerun with --leak-check=full to see details of leaked memory
==21664== 
==21664== For counts of detected and suppressed errors, rerun with: -v
==21664== Use --track-origins=yes to see where uninitialised values come from
==21664== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 12 from 8)

Comment 6 David Howells 2010-05-28 13:46:24 UTC
(gdb) up
#1  0x08049258 in init_entropy_source (ent_src=0x804b528) at rngd_entsource.c:173
173             list_add(&ent_src);

Shouldn't that be:

                list_add(ent_src);

In fact, that occurs twice in rngd_entsource.c

Comment 7 David Howells 2010-05-28 13:49:39 UTC
Not only that, but list_add() isn't declared in a header file, so though this warning occurs:

rngd_entsource.c: In function ‘init_entropy_source’:
rngd_entsource.c:173: warning: implicit declaration of function ‘list_add’

the compiler doesn't notice the fact that list_add() isn't being called correctly.

Comment 8 David Howells 2010-05-28 14:28:34 UTC
Created attachment 417633 [details]
Fix compile warnings and SEGV in rngd

This patch fixes various compile time warnings in rngd, and thus fixes the SEGV.  I recommend that the %configure line in the specfile be changed as follows:

    CFLAGS="$RPM_OPT_FLAGS -Werror" %configure

However, this doesn't make the program actually work.  It just sits there sucking data continuously from /dev/urandom, but doesn't actually add anything to the /dev/random pool.

Comment 9 David Howells 2010-05-28 14:46:37 UTC
Created attachment 417643 [details]
Make do_loop() correctly interpret the return value of iter->xread()

After this patch, rngd works correctly.

[root@andromeda rng-tools-2]# strace  ./rngd -r /dev/urandom -o /dev/random -f
execve("./rngd", ["./rngd", "-r", "/dev/urandom", "-o", "/dev/random", "-f"], [/* 26 vars */]) = 0
brk(0)                                  = 0x95b4000
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb777b000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY)      = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=27550, ...}) = 0
mmap2(NULL, 27550, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7774000
close(3)                                = 0
open("/lib/libc.so.6", O_RDONLY)        = 3
read(3, "\177ELF\1\1\1\3\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0 \216<\0004\0\0\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=1855552, ...}) = 0
mmap2(0x3b2000, 1620360, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x3b2000
mprotect(0x537000, 4096, PROT_NONE)     = 0
mmap2(0x538000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x185) = 0x538000
mmap2(0x53b000, 10632, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x53b000
close(3)                                = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7773000
set_thread_area({entry_number:-1 -> 6, base_addr:0xb77736c0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
mprotect(0x538000, 8192, PROT_READ)     = 0
mprotect(0x3aa000, 4096, PROT_READ)     = 0
munmap(0xb7774000, 27550)               = 0
brk(0)                                  = 0x95b4000
brk(0x95d5000)                          = 0x95d5000
open("/dev/urandom", O_RDONLY)          = 3
read(3, "\221A\251*", 4)                = 4
read(3, "\364\210\374\371", 4)          = 4
open("/dev/tpm0", O_RDWR)               = -1 ENOENT (No such file or directory)
open("/dev/random", O_RDWR)             = 4
read(3, "P\177\204\377^\305\3024\32'\321x)n\206i\17\17\17l:t\327\2\277\361\232\373\17m\234\3"..., 2500) = 2500
ioctl(4, RNDADDENTROPY, 0xbfc1a240)     = 0
ioctl(4, RNDGETENTCNT, 0xbfc1a2ac)      = 0
ioctl(4, RNDADDENTROPY, 0xbfc1a240)     = 0
ioctl(4, RNDGETENTCNT, 0xbfc1a2ac)      = 0
ioctl(4, RNDADDENTROPY, 0xbfc1a240)     = 0
ioctl(4, RNDGETENTCNT, 0xbfc1a2ac)      = 0
ioctl(4, RNDADDENTROPY, 0xbfc1a240)     = 0
ioctl(4, RNDGETENTCNT, 0xbfc1a2ac)      = 0
poll([{fd=4, events=POLLOUT}], 1, 60000) = 1 ([{fd=4, revents=POLLOUT}])
ioctl(4, RNDADDENTROPY, 0xbfc1a240)     = 0
ioctl(4, RNDGETENTCNT, 0xbfc1a2ac)      = 0
ioctl(4, RNDADDENTROPY, 0xbfc1a240)     = 0
ioctl(4, RNDGETENTCNT, 0xbfc1a2ac)      = 0
ioctl(4, RNDADDENTROPY, 0xbfc1a240)     = 0
ioctl(4, RNDGETENTCNT, 0xbfc1a2ac)      = 0
ioctl(4, RNDADDENTROPY, 0xbfc1a240)     = 0
ioctl(4, RNDGETENTCNT, 0xbfc1a2ac)      = 0
ioctl(4, RNDADDENTROPY, 0xbfc1a240)     = 0
ioctl(4, RNDGETENTCNT, 0xbfc1a2ac)      = 0
poll([{fd=4, events=POLLOUT}], 1, 60000^C <unfinished ...>

Comment 10 Vladimir Benes 2010-06-14 12:28:36 UTC
no segfaults now..

Comment 11 releng-rhel@redhat.com 2010-07-02 19:49:34 UTC
Red Hat Enterprise Linux Beta 2 is now available and should resolve
the problem described in this bug report. This report is therefore being closed
with a resolution of CURRENTRELEASE. You may reopen this bug report if the
solution does not work for you.