From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Date: Mon, 5 Jul 2021 14:11:30 +0300 From: Michael Shigorin To: make-initrd@lists.altlinux.org Message-ID: <20210705111130.GX2168@imap.altlinux.org> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="J5MfuwkIyy7RmF4Q" Content-Disposition: inline Content-Transfer-Encoding: 8bit User-Agent: Mutt/1.10.1 (2018-07-13) Subject: [make-initrd] =?koi8-r?b?cTogxsnewSDEzNEg2sHS2cLMydfBzsnRIFJORw==?= X-BeenThere: make-initrd@lists.altlinux.org X-Mailman-Version: 2.1.12 Precedence: list Reply-To: make-initrd@lists.altlinux.org List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 05 Jul 2021 11:11:31 -0000 Archived-At: List-Archive: --J5MfuwkIyy7RmF4Q Content-Type: text/plain; charset=koi8-r Content-Disposition: inline Content-Transfer-Encoding: 8bit Здравствуйте. Коллеги, в связи с очередной невменяемостью апстрима systemd (по совместительству udevd), в v240 выразившейся в повышении требований к качеству псевдослучайных чисел на ранней стадии загрузки[1,2], и возникающих вследствие этого залипаний этой самой ранней стадии загрузки в ожидании каких-либо событий -- бывает достаточно нажать Shift или вставить USB-флэшку -- предлагаю реализовать фичу, которая бы обеспечивала начальную инициализацию ядерного RNG с опорой на то, что при старте может "дребезжать" (особенно при наличии хоть какого-то RTC). У нас тут образовался хак на скору руку, но он прямо по rc.sysinit и заведомо неоптимален, вследствие чего далее был предложен такой вид кусочка на шелле: --- { # Initialize bash random seed using current time nanoseconds # to avoid possible kernel pool usage RANDOM=$((10#$(date "+%N") % 32768)) seed=$( { dmesg; ls -l /var/log /proc; } | md5_bin | od -h ) for ((i=0; i<64; i++)); do echo $seed $RANDOM $(date "+%s%N") | md5_bin done > /dev/random unset i seed } & --- или даже такой (но это ещё 128 форков): --- { export \ RANDOM=$((10#$(date "+%N") % 32768)) \ seed=$( { dmesg; ls -l /var/log /proc; } | md5_bin | od -h ) for ((i=0; i<64; i++)); do ( echo $seed $RANDOM $(date "+%s%N"); ls -l /proc ) | md5_bin done > /dev/random unset i seed } & --- Прилагаю хак и md5_bin.c, прошу совета: * стоит ли так делать; * как лучше собирать md5_bin имени ilyakurdyukov@; * куда лучше поместить скрипт. [1] http://systemd.io/RANDOM_SEEDS [2] http://github.com/systemd/systemd/blob/v240/NEWS#L200 --  ---- WBR, Michael Shigorin / http://altlinux.org   ------ http://opennet.ru / http://anna-news.info --J5MfuwkIyy7RmF4Q Content-Type: text/x-patch; charset=us-ascii Content-Disposition: attachment; filename="0001-Avoid-randomness-related-udev-induced-boot-stalls.patch" >>From 18fbcd9bde20a2b6baf37a7f1bf732dd39bcf3ee Mon Sep 17 00:00:00 2001 From: Michael Shigorin Date: Sun, 8 Nov 2020 19:32:53 +0300 Subject: [PATCH] Avoid randomness-related udev-induced boot stalls Those responsible for breaking udevd even further don't answer the question: why break what used to work before "improvements"? There are many architectures out there, and even those on x86 aren't really doomed to just trust Intel's hwrng. No reason to toss haveged here as we need a "show starter" here, not a service. So fill the 1024 byte long kernel enthropy pool (512*2 bytes, $RANDOM is 0..2^16-1) with good enough "seed" while getrandom() with GRND_INSECURE flag is not widely available yet (Linux 5.6+). Implemented-by: Andrey Savchenko See-also: http://systemd.io/RANDOM_SEEDS --- data/etc/rc.d/rc.sysinit | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/data/etc/rc.d/rc.sysinit b/data/etc/rc.d/rc.sysinit index e95a6fd..30726b8 100755 --- a/data/etc/rc.d/rc.sysinit +++ b/data/etc/rc.d/rc.sysinit @@ -31,3 +31,14 @@ if shell_var_is_no "$quiet"; then echo "INITRAMFS: version $VERSION_ID" } fi + +{ +# Initialize bash random seed using current time nanoseconds +# to avoid possible kernel pool usage +RANDOM=$((10#$(date "+%N") % 32768)) +for ((i=0; i<512; i++)); do + n=$RANDOM + printf "\x$(printf "%x" $((n>>8)))\x$(printf "%x" $((n%256)))" +done > /dev/random +unset i n +} & -- 2.25.4 --J5MfuwkIyy7RmF4Q Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="md5_bin.c" #include #include #include typedef uint32_t u32; typedef uint64_t u64; #define F1(x, y, z) (z ^ (x & (y ^ z))) #define F2(x, y, z) F1(z, x, y) #define F3(x, y, z) (x ^ y ^ z) #define F4(x, y, z) (y ^ (x | ~z)) #define MD5STEP(f, w, x, y, z, in, s) \ (w += f(x, y, z) + in, w = (w<>(32-s)) + x) static void md5_transform(u32 *hash, u32 const *in) { u32 a, b, c, d; a = hash[0]; b = hash[1]; c = hash[2]; d = hash[3]; MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); hash[0] += a; hash[1] += b; hash[2] += c; hash[3] += d; } #undef MD5STEP #undef F4 #undef F3 #undef F2 #undef F1 struct md5_ctx { u32 hash[4], block[16]; u64 byte_count; }; static void md5_init(struct md5_ctx *ctx) { ctx->hash[0] = 0x67452301; ctx->hash[1] = 0xefcdab89; ctx->hash[2] = 0x98badcfe; ctx->hash[3] = 0x10325476; ctx->byte_count = 0; } static void md5_update(struct md5_ctx *ctx, const char *data, unsigned int len) { const u32 avail = 64 - (ctx->byte_count & 0x3f); ctx->byte_count += len; if (avail > len) { memcpy((char*)ctx->block + (64 - avail), data, len); return; } memcpy((char*)ctx->block + (64 - avail), data, avail); md5_transform(ctx->hash, ctx->block); data += avail; len -= avail; while (len >= 64) { memcpy(ctx->block, data, 64); md5_transform(ctx->hash, ctx->block); data += 64; len -= 64; } memcpy(ctx->block, data, len); } static void md5_final(struct md5_ctx *ctx, unsigned char *out) { const unsigned int offset = ctx->byte_count & 0x3f; char *p = (char*)ctx->block + offset; int padding = 56 - (offset + 1); *p++ = 0x80; if (padding < 0) { memset(p, 0, padding + 8); md5_transform(ctx->hash, ctx->block); p = (char*)ctx->block; padding = 56; } memset(p, 0, padding); ctx->block[14] = ctx->byte_count << 3; ctx->block[15] = ctx->byte_count >> 29; md5_transform(ctx->hash, ctx->block); memcpy(out, ctx->hash, 16); memset(ctx, 0, sizeof(struct md5_ctx)); } int main() { int a; struct md5_ctx md5; unsigned char hash[16]; md5_init(&md5); while ((a = getchar()) != EOF) { char c = a; md5_update(&md5, &c, 1); } md5_final(&md5, hash); return fwrite(hash, sizeof(hash), 1, stdout) != 1; } --J5MfuwkIyy7RmF4Q--