[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: kernel/1671: Not enough random bytes available (GnuPG & OBSD2.8)
- To: bugs_(_at_)_cvs_(_dot_)_openbsd_(_dot_)_org
- Subject: Re: kernel/1671: Not enough random bytes available (GnuPG & OBSD2.8)
- From: Brad Allen <Ulmo_(_at_)_Q_(_dot_)_Net>
- Date: Sat, 10 Feb 2001 17:50:02 -0700 (MST)
- Cc:
- Reply-to: Brad Allen <Ulmo_(_at_)_Q_(_dot_)_Net>
The following reply was made to PR kernel/1671; it has been noted by GNATS.
From: Brad Allen <Ulmo_(_at_)_Q_(_dot_)_Net>
To: deraadt_(_at_)_cvs_(_dot_)_openbsd_(_dot_)_org
Cc: ulmo_(_at_)_BayView_(_dot_)_COM, gnats_(_at_)_openbsd_(_dot_)_org
Subject: Re: kernel/1671: Not enough random bytes available (GnuPG &
OBSD2.8)
Date: Sat, 10 Feb 2001 20:45:35 -0400 (AST)
From: Theo de Raadt <deraadt_(_at_)_cvs_(_dot_)_openbsd_(_dot_)_org>
Subject: Re: kernel/1671: Not enough random bytes available (GnuPG & OBSD2.8)
Date: Tue, 06 Feb 2001 02:51:05 -0700
Message-ID: <200102060951_(_dot_)_f169p5b29957_(_at_)_cvs_(_dot_)_openbsd_(_dot_)_org>
deraadt> I bet that gpg is one of those completely retarded programs
deraadt> that opens /dev/srandom using stdio. Which then tries to go
deraadt> and read 8K which it will never use.
Relevent lines from gnupg-1.0.4.tar.gz: cipher/rndlinux.c: [used for OpenBSD]
81: fd = open( name, O_RDONLY );
106: byte buffer[768];
126: while( length ) {
143:"Not enough random bytes available. Please do some other work to give\n"
"the OS a chance to collect more entropy! (Need %d more bytes)\n"), length );
159: int nbytes = length < sizeof(buffer)? length : sizeof(buffer);
160: n = read(fd, buffer, nbytes );
170: length -= n;
Apparently, you are mistaken: GnuPG in this incarnation knows
precisely how many octets it needs, and then goes after them one by
one. Sticking a debugging line in there to reveal how many octets
it's reading, I find in just one run each (I didn't search very deeply
to see if this changes under conditions):
signing: 0x10 octets
encrypt: 0x10 octets
sign and encrypt: 0x10 octets.
BTW, the problem and fix *might* be related to the RTC (Real Time
Clock). I am preparing a large bug report, and want more time to
polish it off. Just in case it gets lost in time, I will give you
this patch as a clue as to what I think is a clue, and tell you I
haven't had this problem *yet*, but the last time I had it it was
after a few weeks of uptime and I still don't know what the trigger
is:
Index: clock.c
===================================================================
RCS file: /cvs/src/sys/arch/i386/isa/clock.c,v
retrieving revision 1.21
diff -u -r1.21 clock.c
--- clock.c 2000/01/29 04:27:48 1.21
+++ clock.c 2001/02/11 00:35:11
@@ -207,7 +207,62 @@
hardclock(frame);
return 1;
}
+#if 0
+This is what was in FreeBSD:
+
+? log
+? clock.c.annotate
+? clock.c.diff
+Index: clock.c
+===================================================================
+RCS file: /home/ncvs/src/sys/i386/isa/clock.c,v
+retrieving revision 1.79
+retrieving revision 1.80
+diff -u -r1.79 -r1.80
+--- clock.c 1997/03/05 08:08:48 1.79
++++ clock.c 1997/04/06 13:25:48 1.80
+@@ -34,7 +34,7 @@
+ * SUCH DAMAGE.
+ *
+ * from: @(#)clock.c 7.2 (Berkeley) 5/12/91
+- * $Id: clock.c,v 1.78 1997/03/05 00:54:00 gpalmer Exp $
++ * $Id: clock.c,v 1.79 1997/03/05 08:08:48 bde Exp $
+ */
+
+ /*
+@@ -311,15 +311,20 @@
+ *
+ * The RTC chip requires that we read status register C (RTC_INTR)
+ * to acknowledge an interrupt, before it will generate the next one.
++ * Under high interrupt load, rtcintr() can be indefinitely delayed and
++ * the clock can tick immediately after the read from RTC_INTR. In this
++ * case, the mc146818A interrupt signal will not drop for long enough
++ * to register with the 8259 PIC. If an interrupt is missed, the stat
++ * clock will halt, considerably degrading system performance. This is
++ * why we use 'while' rather than a more straightforward 'if' below.
++ * Stat clock ticks can still be lost, causing minor loss of accuracy
++ * in the statistics, but the stat clock will no longer stop.
+ */
+ static void
+ rtcintr(struct clockframe frame)
+ {
+- u_char stat;
+- stat = rtcin(RTC_INTR);
+- if(stat & RTCIR_PERIOD) {
++ while (rtcin(RTC_INTR) & RTCIR_PERIOD)
+ statclock(&frame);
+- }
+ }
+
+ #include "opt_ddb.h"
+
+
+So, my interpretation (and therefore interpolation) will follow.
+
+#endif /* 0 */
+
+
int
rtcintr(arg)
void *arg;
@@ -215,12 +270,38 @@
struct clockframe *frame = arg; /* not strictly neccecary */
u_int stat;
+#if 0
stat = mc146818_read(NULL, MC_REGC);
if (stat & MC_REGC_PF) {
statclock(frame);
return 1;
}
+
+ return 0;
+#elif 0
+ if (!((mc146818_read(NULL, MC_REGC) & MC_REGC_PF))) return 0;
+ do statclock(frame);
+ while (mc146818_read(NULL, MC_REGC) & MC_REGC_PF);
+ return 1;
+#else /* 0 */
+ stat = mc146818_read(NULL, MC_REGC);
+ if (stat & MC_REGC_PF) {
+ repeat:
+ statclock(frame);
+ return 1;
+ }
+ stat = mc146818_read(NULL, MC_REGC);
+ if (stat & MC_REGC_PF) {
+ static u_char gave_mc146818_repeating_message=0;
+ if(!gave_mc146818_repeating_message) {
+ gave_mc146818_repeating_message=1;
+ printf("stat clock repeat"); /* how do I err msg? */
+ }
+ goto repeat;
+ }
+
return 0;
+#endif /* 0 */
}
int
Visit your host, monkey.org