Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package dd_rescue for openSUSE:Factory checked in at 2025-03-15 16:15:10 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/dd_rescue (Old) and /work/SRC/openSUSE:Factory/.dd_rescue.new.19136 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "dd_rescue" Sat Mar 15 16:15:10 2025 rev:66 rq:1253156 version:1.99.21 Changes: -------- --- /work/SRC/openSUSE:Factory/dd_rescue/dd_rescue.changes 2025-01-28 14:58:05.403348756 +0100 +++ /work/SRC/openSUSE:Factory/.dd_rescue.new.19136/dd_rescue.changes 2025-03-15 16:15:22.190275928 +0100 @@ -1,0 +2,13 @@ +Fri Mar 14 18:25:52 CET 2025 - k...@garloff.de + +- Update to dd_rescue-1.99.21: + * New option -H to inject interrupted and short IO calls for + testing. + * Fix handling of receiving short reads after EINTR/EAGAIN. + * Fix handling of short writes and EINTR/EAGAIN. + * When several retries happened in real_writeblock(), we would + corrupt the stack by increasing pointer rather than the + variable pointed to. (This was reported by Sam James and + analyzed with -fsanitizer.) + +------------------------------------------------------------------- Old: ---- dd_rescue-1.99.20.tar.bz2 dd_rescue-1.99.20.tar.bz2.asc New: ---- dd_rescue-1.99.21.tar.bz2 dd_rescue-1.99.21.tar.bz2.asc ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ dd_rescue.spec ++++++ --- /var/tmp/diff_new_pack.nVibmA/_old 2025-03-15 16:15:23.650337187 +0100 +++ /var/tmp/diff_new_pack.nVibmA/_new 2025-03-15 16:15:23.650337187 +0100 @@ -21,7 +21,7 @@ %define _lto_cflags %{nil} %endif Name: dd_rescue -Version: 1.99.20 +Version: 1.99.21 Release: 0 Summary: Data copying in the presence of I/O Errors License: GPL-2.0-only OR GPL-3.0-only ++++++ dd_rescue-1.99.20.tar.bz2 -> dd_rescue-1.99.21.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dd_rescue-1.99.20/Makefile new/dd_rescue-1.99.21/Makefile --- old/dd_rescue-1.99.20/Makefile 2025-01-20 09:03:41.692897770 +0100 +++ new/dd_rescue-1.99.21/Makefile 2025-03-14 17:40:10.516737617 +0100 @@ -1,7 +1,7 @@ # (c) garl...@suse.de, 99/10/09, GNU GPL # (c) k...@garloff.de, 2010 -- 2021, GNU GPL v2 or v3 -VERSION = 1.99.20 +VERSION = 1.99.21 DESTDIR = SRCDIR ?= . @@ -38,7 +38,7 @@ LIBDIR = /usr/$(LIB) COMPILER = $(shell $(CC) --version | head -n1) ID = $(shell git describe --tags || cat REL-ID) -DEFINES = -DVERSION=\"$(VERSION)\" -D__COMPILER__="\"$(COMPILER)\"" -DID=\"$(ID)\" # -DPLUGSEARCH="\"$(LIBDIR)\"" +DEFINES = -DIO_HAVOC=1 -DVERSION=\"$(VERSION)\" -D__COMPILER__="\"$(COMPILER)\"" -DID=\"$(ID)\" # -DPLUGSEARCH="\"$(LIBDIR)\"" OUT = -o dd_rescue PIC = -fPIC PIE = -fPIE @@ -261,7 +261,7 @@ # Automated dependency generation .dep: $(SRCDIR)/Makefile config.h $(SRCDIR)/*.h $(SRCDIR)/*.c #$(CC) $(CFLAGS) -DGEN_DEP $(ARCHFLAGS) -MM $(SRCDIR)/*.c >.dep - $(CC) $(CFLAGS) -DGEN_DEP $(DEP_SSE) -I . -MM $(SRCDIR)/*.c >.dep + $(CC) $(CFLAGS) -DGEN_DEP $(DEP_SSE) -I . -I $(SRCDIR) -MM $(SRCDIR)/*.c >.dep sed 's/\.o:/\.po:/' <.dep >.dep2 cat .dep2 >> .dep rm .dep2 @@ -273,10 +273,10 @@ make .dep # These need optimization -archdep.o: $(SRCDIR)/archdep.c archdep.h config.h +archdep.o: $(SRCDIR)/archdep.c $(SRCDIR)/archdep.h config.h $(CC) $(CFLAGS_OPT) $(ARCHFLAGS) $(PIE) -c $< -archdep.po: $(SRCDIR)/archdep.c archdep.h config.h +archdep.po: $(SRCDIR)/archdep.c $(SRCDIR)/archdep.h config.h $(CC) $(CFLAGS_OPT) $(ARCHFLAGS) $(PIC) -c $< frandom.o: $(SRCDIR)/frandom.c config.h @@ -436,7 +436,7 @@ $(CC) $(CFLAGS_OPT) $(PIE) $(LDPIE) -DSHA1_MAIN -o $@ $< fuzz_lzo: fuzz_lzo.o - $(CC) -o $@ $(LDPIE) $^ -llzo2 + $(CC) -o $@ $(CFLAGS) $(LDPIE) $^ -llzo2 # More dd_rescue variants libfalloc-dl: dd_rescue @@ -476,6 +476,9 @@ pbkdf2: $(SRCDIR)/ossl_pbkdf2.c $(CC) $(CFLAGS) $(PIE) $(LDPIE) -o $@ $< $(CRYPTOLIB) +test_aligned_alloc: $(SRCDIR)/test_aligned_alloc.c + $(CC) $(CFLAGS) $(PIE) $(LDPIE) -o $@ $< + test_aes: $(SRCDIR)/test_aes.c $(AESNI_O) $(AES_ARM64_O) aes_c.o secmem.o sha256.o $(SHAOBJ) archdep.o $(AES_OSSL_O) aes.o $(SRCDIR)/aesni.h $(SRCDIR)/aes_arm64.h config.h $(OBJECTS2) $(CC) $(CFLAGS) $(PIE) $(LDPIE) $(DEF) -o $@ $< $(AESNI_O) $(AES_ARM64_O) aes_c.o secmem.o sha256.o $(SHAOBJ) $(AES_OSSL_O) aes.o archdep.o $(OBJECTS2) $(CRYPTOLIB) @@ -752,28 +755,28 @@ check_sparse: $(TARGETS) @echo "***** dd_rescue sparse tests with plugins *****" - ./test_sparse.sh - ./test_sparse.sh "-L ./libddr_null.so=unsparse" - ./test_sparse.sh "-L ./libddr_hash.so=sha256" - ./test_sparse.sh "-L ./libddr_crypt.so=AES192-CTR:weakrnd:pbkdf2:pass=ABC:skiphole:" "encrypt" "decrypt" - ./test_sparse.sh "-L ./libddr_crypt.so=AES192-CTR:weakrnd:pbkdf2:pass=ABC:" "encrypt" "decrypt" - if test $(HAVE_LZO) = 1; then ./test_sparse.sh "-L ./libddr_lzo.so=" "compress" "decompress"; fi - if test $(HAVE_LZMA) = 1; then ./test_sparse.sh "-L ./libddr_lzma.so=" "compress" "decompress"; fi + ./test_sparse.sh "-H 15" + ./test_sparse.sh "-H 15 -L ./libddr_null.so=unsparse" + ./test_sparse.sh "-H 15 -L ./libddr_hash.so=sha256" + ./test_sparse.sh "-H 15 -L ./libddr_crypt.so=AES192-CTR:weakrnd:pbkdf2:pass=ABC:skiphole:" "encrypt" "decrypt" + ./test_sparse.sh "-H 15 -L ./libddr_crypt.so=AES192-CTR:weakrnd:pbkdf2:pass=ABC:" "encrypt" "decrypt" + if test $(HAVE_LZO) = 1; then ./test_sparse.sh "-H 15 -L ./libddr_lzo.so=" "compress" "decompress"; fi + if test $(HAVE_LZMA) = 1; then ./test_sparse.sh "-H 15 -L ./libddr_lzma.so=" "compress" "decompress"; fi # Sparse files with odd sizes - ./test_sparse.sh "-L ./libddr_null.so=unsparse" "" "" 8388612 - ./test_sparse.sh "-L ./libddr_hash.so=sha256" "" "" 8388612 - ./test_sparse.sh "-L ./libddr_crypt.so=AES192-CTR:weakrnd:pbkdf2:pass=ABC:skiphole:" "encrypt" "decrypt" 8388612 - ./test_sparse.sh "-L ./libddr_crypt.so=AES192-CTR:weakrnd:pbkdf2:pass=ABC:" "encrypt" "decrypt" 8388612 - if test $(HAVE_LZO) = 1; then ./test_sparse.sh "-L ./libddr_lzo.so=" "compress" "decompress" 8388612; fi - if test $(HAVE_LZMA) = 1; then ./test_sparse.sh "-L ./libddr_lzma.so=" "compress" "decompress" 8388612; fi + ./test_sparse.sh "-H 15 -L ./libddr_null.so=unsparse" "" "" 8388612 + ./test_sparse.sh "-H 15 -L ./libddr_hash.so=sha256" "" "" 8388612 + ./test_sparse.sh "-H 15 -L ./libddr_crypt.so=AES192-CTR:weakrnd:pbkdf2:pass=ABC:skiphole:" "encrypt" "decrypt" 8388612 + ./test_sparse.sh "-H 15 -L ./libddr_crypt.so=AES192-CTR:weakrnd:pbkdf2:pass=ABC:" "encrypt" "decrypt" 8388612 + if test $(HAVE_LZO) = 1; then ./test_sparse.sh "-H 15 -L ./libddr_lzo.so=" "compress" "decompress" 8388612; fi + if test $(HAVE_LZMA) = 1; then ./test_sparse.sh "-H 15 -L ./libddr_lzma.so=" "compress" "decompress" 8388612; fi # Sparse files with holes at end and at beginning - ./test_sparse.sh "" "" "" 7596032 1 - ./test_sparse.sh "-L ./libddr_null.so=unsparse" "" "" 7596032 1 - ./test_sparse.sh "-L ./libddr_hash.so=sha256" "" "" 7596032 1 - ./test_sparse.sh "-L ./libddr_crypt.so=AES192-CTR:weakrnd:pbkdf2:pass=ABC:skiphole:" "encrypt" "decrypt" 7596032 1 - ./test_sparse.sh "-L ./libddr_crypt.so=AES192-CTR:weakrnd:pbkdf2:pass=ABC:" "encrypt" "decrypt" 7596032 1 - if test $(HAVE_LZO) = 1; then ./test_sparse.sh "-L ./libddr_lzo.so=" "compress" "decompress" 7596032 1; fi - if test $(HAVE_LZMA) = 1; then ./test_sparse.sh "-L ./libddr_lzma.so=" "compress" "decompress" 7596032 1; fi + ./test_sparse.sh "-H 15 " "" "" 7596032 1 + ./test_sparse.sh "-H 15 -L ./libddr_null.so=unsparse" "" "" 7596032 1 + ./test_sparse.sh "-H 15 -L ./libddr_hash.so=sha256" "" "" 7596032 1 + ./test_sparse.sh "-H 15 -L ./libddr_crypt.so=AES192-CTR:weakrnd:pbkdf2:pass=ABC:skiphole:" "encrypt" "decrypt" 7596032 1 + ./test_sparse.sh "-H 15 -L ./libddr_crypt.so=AES192-CTR:weakrnd:pbkdf2:pass=ABC:" "encrypt" "decrypt" 7596032 1 + if test $(HAVE_LZO) = 1; then ./test_sparse.sh "-H 15 -L ./libddr_lzo.so=" "compress" "decompress" 7596032 1; fi + if test $(HAVE_LZMA) = 1; then ./test_sparse.sh "-H 15 -L ./libddr_lzma.so=" "compress" "decompress" 7596032 1; fi if test $(HAVE_LZO) = 1; then ./test_sparse_compress_crypt.sh; fi if test $(HAVE_LZMA) = 1; then ./test_sparse_compress_crypt.sh lzma; fi diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dd_rescue-1.99.20/README.dd_rescue new/dd_rescue-1.99.21/README.dd_rescue --- old/dd_rescue-1.99.20/README.dd_rescue 2025-01-19 20:49:32.167108800 +0100 +++ new/dd_rescue-1.99.21/README.dd_rescue 2025-03-14 17:40:10.520737718 +0100 @@ -234,6 +234,8 @@ * Double -p makes failure to copy ownership/perms/times/xattrs reported in exit code. Failure on copying ownership/perms will error out early (to avoid exposing sensitive data). +* 1.99.21 was made safe against interrupted and short read/write calls and + the option -H allows to test for this. (This only worked partically before.) Copyright diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dd_rescue-1.99.20/REL-ID new/dd_rescue-1.99.21/REL-ID --- old/dd_rescue-1.99.20/REL-ID 2025-01-20 15:43:43.340943216 +0100 +++ new/dd_rescue-1.99.21/REL-ID 2025-03-14 17:51:28.621171757 +0100 @@ -1 +1 @@ -DD_RESCUE_1_99_20 +DD_RESCUE_1_99_21 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dd_rescue-1.99.20/dd_rescue.1 new/dd_rescue-1.99.21/dd_rescue.1 --- old/dd_rescue-1.99.20/dd_rescue.1 2025-01-19 20:54:07.157626133 +0100 +++ new/dd_rescue-1.99.21/dd_rescue.1 2025-03-14 17:40:10.520737718 +0100 @@ -887,7 +887,18 @@ the middle of a file with -s or reverse copying won't affect the absolute position that is hit with the fault injection. (This has changed since 1.98.) - +.br +The option +.B -H percent +on the command line will cause read and write havoc by returning short +reads and writes and by returning an indication that a read or write +has to be redone as the system call was interrupted or would block. +The percentage given will be evenly split between interrupted calls +and short reads/writes. According to the GNU libc documentation, such +things can happen; the fact they only do happen seldomly and only under +certain circumstances makes it hard to test, thus this option to force +it to randomly happen. (This has led to bug fixes in 1.99.21.) +.br .SH BUGS/LIMITATIONS The source code does use the 64bit functions provided by glibc for file positioning. However, your kernel might not support it, so you might be diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dd_rescue-1.99.20/dd_rescue.c new/dd_rescue-1.99.21/dd_rescue.c --- old/dd_rescue-1.99.20/dd_rescue.c 2025-01-20 15:38:27.925465127 +0100 +++ new/dd_rescue-1.99.21/dd_rescue.c 2025-03-14 17:40:10.524737818 +0100 @@ -200,6 +200,8 @@ #include "pread64.h" #endif +#include "iohavoc.h" + #define MIN(a,b) ((a)<(b)? (a): (b)) #if __WORDSIZE == 64 @@ -1767,7 +1769,7 @@ if (fst->i_chr) rd = read(fd, bf, sz); else - rd = pread64(fd, bf, sz, off); + rd = PREAD64(fd, bf, sz, off); if (rd == (ssize_t)-1 && !op->reverse && fst->fin_ipos && fst->ipos == fst->fin_ipos) { errno = 0; return 0; @@ -1804,15 +1806,15 @@ if (op->avoidwrite) { ssize_t ln = pread64(fd, fst->buf2, sz, off); if (ln < (ssize_t)sz) - return pwrite64(fd, bf, sz, off); + return PWRITE64(fd, bf, sz, off); if (memcmp(bf, fst->buf2, ln)) - return pwrite64(fd, bf, sz, off); + return PWRITE64(fd, bf, sz, off); else { prg->axfer += ln; return ln; } } else - return pwrite64(fd, bf, sz, off); + return PWRITE64(fd, bf, sz, off); } } @@ -1822,14 +1824,18 @@ dpopt_t *dop, dpstate_t *dst) { ssize_t err, rd = 0; - //errno = 0; /* should not be necessary */ do { + //errno = 0; /* should not be necessary */ rd += (err = mypread(fst->ides, fst->buf+rd, toread-rd, fst->ipos+rd-op->reverse*toread, op, fst, rep, dop, dst)); - if (err == -1) - rd++; + if (err == -1) + ++rd; } while ((err == -1 && (errno == EINTR || errno == EAGAIN)) - || (rd < toread && err > 0 && errno == 0)); + || (rd < toread && err > 0 && (errno == 0 || errno == EINTR || errno == EAGAIN))); //if (rd < toread) memset (fst->buf+rd, 0, toread-rd); + //if (rd < toread) + // fplog(stderr, WARN, "Short read %li/%li\n", rd, toread); + if (errno == EINTR || errno == EAGAIN) + errno = 0; return (/*err == -1? err:*/ rd); } @@ -1851,9 +1857,12 @@ fst->opos+wr-op->reverse*towrite, op, fst, prg)); if (err == -1) wr++; - } while ((err == -1 && (errno == EINTR || errno == EAGAIN || !*retry++)) - || (err > 0 && errno == 0 && wr < towrite) - || (err == 0 && !*retry++)); + if (!err) + sched_yield(); + } while ((err == -1 && (errno == EINTR || errno == EAGAIN)) + || (err >= 0 && (errno == 0 || errno == EINTR || errno == EAGAIN) && wr < towrite &&!*retry)); + if (errno == EINTR || errno == EAGAIN) + errno = 0; if (wr < towrite && err != 0) { /* HANDLE write errors here ... */ @@ -1916,7 +1925,7 @@ if (e2 == -1) w2++; } while ((e2 == -1 && (errno == EINTR || errno == EAGAIN)) - || (w2 < towrite && e2 > 0 && errno == 0)); + || (w2 < towrite && e2 >= 0 && (errno == 0 || errno == EINTR || errno == EAGAIN))); if (w2 < towrite && e2 != 0) fplog(stderr, WARN, "2ndary write %s (%skiB): %s\n", oft->name, fmt_kiB(fst->opos, !nocol), strerror(errno)); @@ -2840,7 +2849,7 @@ {"shred3", 1, NULL, '3'}, {"shred4", 1, NULL, '4'}, {"shred2", 1, NULL, '2'}, {"rmvtrim", 0, NULL, 'u'}, {"plugins", 1, NULL, 'L'}, - {"fault", 1, NULL, 'F'}, + {"fault", 1, NULL, 'F'}, {"havoc", 1, NULL, 'H'}, /* GNU ddrescue compat */ {"block-size", 1, NULL, 'B'}, {"input-position", 1, NULL, 's'}, {"output-position", 1, NULL, 'S'}, {"max-size", 1, NULL, 'm'}, @@ -2897,6 +2906,7 @@ fprintf(stderr, " -C limit rateControl: avoid xfer data faster than limit B/s\n"); fprintf(stderr, " -Y oname Secondary output file (multiple possible),\n"); fprintf(stderr, " -F off[-off]r/rep[,off[-off]w/rep[,...]] fault injection (hardbs off) r/w\n"); + fprintf(stderr, " -H pct Inject pct percent EINTR/EAGAIN and short reads/writes\n"); fprintf(stderr, " -q quiet operation,\n"); fprintf(stderr, " -v verbose operation,\n"); fprintf(stderr, " -E loglv set plugin loglevel (0 = verbose, 2 = default, 5 = quiet, max 6),\n"); @@ -2966,6 +2976,12 @@ } } +void ignoredsignal(int sig) +{ + fplog(stderr, WARN, "Caught signal %i \"%s\". Ignore ...\n", + sig, strsignal(sig)); +} + unsigned char* zalloc_aligned_buf(unsigned int bs, unsigned char**obuf) { unsigned char *ptr = 0; @@ -3149,11 +3165,13 @@ ofiles = NULL; int tmpfd = 0; + int pct; + IOHAVOC_INIT(0, 0, 0); #ifdef LACK_GETOPT_LONG - while ((c = getopt(argc, argv, ":rtTfihqvVwWaAdDkMRpPuc:b:B:m:e:s:S:l:L:o:y:z:Z:2:3:4:xY:F:C:E:")) != -1) + while ((c = getopt(argc, argv, ":rtTfihqvVwWaAdDkMRpPuc:b:B:m:e:s:S:l:L:o:y:z:Z:2:3:4:xY:F:C:E:H:")) != -1) #else - while ((c = getopt_long(argc, argv, ":rtTfihqvVwWaAdDkMRpPuc:b:B:m:e:s:S:l:L:o:y:z:Z:2:3:4:xY:F:C:E:", longopts, NULL)) != -1) + while ((c = getopt_long(argc, argv, ":rtTfihqvVwWaAdDkMRpPuc:b:B:m:e:s:S:l:L:o:y:z:Z:2:3:4:xY:F:C:E:H:", longopts, NULL)) != -1) #endif { switch (c) { @@ -3204,6 +3222,7 @@ case 'x': op->extend = 1; break; case 'u': op->rmvtrim = 1; break; case 'F': populate_faultlists(optarg, op); break; + case 'H': pct = atoi(optarg); IOHAVOC_INIT(1, pct, pct); break; case 'Y': do { ofile_t of; of.name = optarg; of.fd = -1; of.cdev = 0; LISTAPPEND(ofiles, of, ofile_t); } while (0); break; case 'z': dop->prng_libc = 1; if (is_filename(optarg)) dop->prng_sfile = optarg; else dop->prng_seed = readint(optarg, 0); break; case 'Z': dop->prng_frnd = 1; if (is_filename(optarg)) dop->prng_sfile = optarg; else dop->prng_seed = readint(optarg, 0); break; @@ -3587,6 +3606,8 @@ static repeat_t _repeat; repeat_t *repeat = &_repeat; + char* iohavoc_report; + /* Initialize: static vars should be zeroed, but better safe than sorry */ memset(dpstate, 0, sizeof(dpstate_t)); memset(fstate, 0, sizeof(fstate_t)); @@ -3690,6 +3711,7 @@ signal(SIGTERM, breakhandler); /* Used to signal clean abort from plugins */ signal(SIGQUIT, breakhandler); + signal(SIGWINCH, ignoredsignal); /* Save time and start to work */ fstate->ipos = opts->init_ipos; @@ -3728,6 +3750,9 @@ printreport(opts, fstate, progress, dpopts); fadvise(1, opts, fstate, progress); err += cleanup(0); + iohavoc_report = IOHAVOC_REPORT(); + if (iohavoc_report) + fplog(stderr, INFO, "%s", iohavoc_report); if (int_by == SIGQUIT) ++err; if (err) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dd_rescue-1.99.20/iohavoc.h new/dd_rescue-1.99.21/iohavoc.h --- old/dd_rescue-1.99.20/iohavoc.h 1970-01-01 01:00:00.000000000 +0100 +++ new/dd_rescue-1.99.21/iohavoc.h 2025-03-14 17:42:43.024528387 +0100 @@ -0,0 +1,186 @@ +/* iohavoc.h + * + * wrapper around read() and write() calls, + * deliberately injecting behavior like + * interrupted system calls returning with EINTR + * or EAGAIN and short reads/writes. + * + * These are things that can happen in real life + * according to glibc documentation, yet do happen + * only rarely and only under certain circumstances, + * which make robustness against these things hard + * to test. + * This collection of wrappers allow to inject such + * things, so we can test robustness. + * + * (c) Kurt Garloff <k...@garloff.de>, 3/2025 + * SPDX-License-Identifier: LGPL-v2.1 + */ + +#ifndef _IOHAVOC_H +#define _IOHAVOC_H + +//#define _FILE_OFFSET_BITS 64 +#include <random.h> +#include <unistd.h> +#include <errno.h> + +/* From GNU libc info pages + * + * read() can return -1 with errno EAGAIN or EINTR, indicating that + * it needs to be called again. + * read() can return only a subset of the requested bytes, + * which means it needs to be called again for the rest. + * read() returning 0 (with a non-zero size param) means EOF. + * pread() and pread64() behave the same way. + * + * write() has the same behavior w.r.t. EAGAIN/EINTR and short + * writes as read(). + * write() returning 0 should be treated as short writes, not EOF. + * pwrite, pwrite64() behaves as write() does. + */ + +#ifdef IO_HAVOC + +static int limit1, limit2; +static long cnt_sh, cnt_in, cnt_reg; + +/* configure limits */ +static inline +void iohavoc_init(int seed, char shortpct, char intrpct) +{ + if (!seed) + seed = time(0); + srand(seed); + assert(intrpct+shortpct <= 100); + /* We generate random numbers + * - If they are below limit1, we do short reads/writes + * - If they are below limit2 (but above limit1), we do EINTR/EAGAIN + * - Else (above limit2), we do normal reads/writes + */ + limit1 = shortpct*(RAND_MAX/100); + limit2 = (shortpct+intrpct)*(RAND_MAX/100); + cnt_sh = 0; cnt_in = 0; cnt_reg = 0; +} + + +/* Call rand and determine action */ +static inline +ssize_t io_determine(ssize_t sz) +{ + int rd = rand(); + /* Full read/write */ + if (rd >= limit2) + return sz; + /* EINTR/EAGAIN */ + if (rd >= limit1) + return rd&1? -EINTR: -EAGAIN; + /* Short read/write */ + ssize_t shortln = sz*rd/limit1; + return shortln - shortln%512; +} + + +#define IOWRAP3(fn, wr, fd, bf, sz) \ + ssize_t nsz = io_determine(sz); \ + if (nsz < 0) { \ + ++cnt_in; \ + errno = -nsz; \ + return -1; \ + } \ + /* Avoid 0-sized read (EOF) */ \ + if (!wr && !nsz) \ + nsz = sz; \ + if (nsz != sz) \ + ++cnt_sh; \ + else \ + ++cnt_reg; \ + /*errno = 0;*/ \ + return fn(fd, bf, nsz); + +#define IOWRAP4(fn, wr, fd, bf, sz, off)\ + ssize_t nsz = io_determine(sz); \ + if (nsz < 0) { \ + ++cnt_in; \ + errno = -nsz; \ + return -1; \ + } \ + /* Avoid 0-sized read (EOF) */ \ + if (!wr && !nsz) \ + nsz = sz; \ + if (nsz != sz) \ + ++cnt_sh; \ + else \ + ++cnt_reg; \ + /*errno = 0;*/ \ + return fn(fd, bf, nsz, off); + + +#define IOHAVOC_INIT(s, sh, in) \ + iohavoc_init(s, sh, in) + +static char _iohavoc_report[80]; +static inline char* IOHAVOC_REPORT() +{ + if (cnt_sh || cnt_in) { + snprintf(_iohavoc_report, 79, "iohavoc stats: %li regular calls, %li short, %li intr\n", + cnt_reg, cnt_sh, cnt_in); + return _iohavoc_report; + } + return NULL; +} + +/* +static inline ssize_t READ(int fd, void *bf, size_t sz) +{ + IOWRAP3(read, 0, fd, bf, sz) +} + +static inline ssize_t WRITE(int fd, void *bf, size_t sz) +{ + IOWRAP3(write, 1, fd, bf, sz) +} +*/ + +static inline ssize_t PREAD64(int fd, void *bf, size_t sz, loff_t off) +{ + IOWRAP4(pread64, 0, fd, bf, sz, off) +} + +static inline ssize_t PWRITE64(int fd, void *bf, size_t sz, loff_t off) +{ + IOWRAP4(pwrite64, 1, fd, bf, sz, off) +} + +#else /* IO_HAVOC */ + +#define IOHAVOC_INIT(s, sh, in) \ + do {} while(0) +#define IOHAVOC_REPORT() NULL + + +/* +static inline ssize_t READ(int fd, void *bf, size_t sz) +{ + return read(fd, bf, sz); +} + +static inline ssize_t WRITE(int fd, void *bf, size_t sz) +{ + return write(fd, bf, sz); +} +*/ + +static inline ssize_t PREAD64(int fd, void *bf, size_t sz, loff_t off) +{ + return pread64(fd, bf, sz, off); +} + +static inline ssize_t PWRITE64(int fd, void *bf, size_t sz, loff_t off) +{ + return pwrite64(fd, bf, sz, off); +} + +#endif /* IO_HAVOC */ + +#endif /* _IOHAVOC_H */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dd_rescue-1.99.20/libddr_crypt.c new/dd_rescue-1.99.21/libddr_crypt.c --- old/dd_rescue-1.99.20/libddr_crypt.c 2025-01-19 18:03:32.932040623 +0100 +++ new/dd_rescue-1.99.21/libddr_crypt.c 2025-02-16 19:49:11.559820366 +0100 @@ -139,7 +139,7 @@ int read_file(unsigned char*, const char*, uint maxlen); char* mystrncpy(unsigned char*, const char*, uint maxlen); int stripcrlf(char* str, uint maxlen); -void whiteout(char* str, char quiet); +void whiteout(char* str, char quiet, const char* opt); int set_flag(char* flg, const char* msg) { @@ -299,7 +299,7 @@ else if (!memcmp(param, "keyhex=", 7)) { //err += parse_hex_u32((unsigned int*)state->sec->userkey1, param+7, state->alg->keylen/(8*sizeof(int))); err += parse_hex(state->sec->userkey1, param+7, state->alg->keylen/8); - whiteout(param+7, opt->quiet); + whiteout(param+7, opt->quiet, "keyhex"); err += set_flag(&state->kset, "key"); } else if (!memcmp(param, "keyfd=", 6)) { err += read_fd(state->sec->userkey1, param+6, 32, "key"); @@ -314,7 +314,7 @@ else if (!memcmp(param, "ivhex=", 6)) { //err += parse_hex_u32((unsigned int*)state->sec->nonce1, param+6, BLKSZ/sizeof(int)); err += parse_hex(state->sec->nonce1, param+6, BLKSZ); - whiteout(param+6, opt->quiet); + whiteout(param+6, opt->quiet, "ivhex"); err += set_flag(&state->iset, "IV"); } else if (!memcmp(param, "ivfd=", 5)) { err += read_fd(state->sec->nonce1, param+5, BLKSZ, "iv"); @@ -328,7 +328,7 @@ state->ivf = 1; else if (!memcmp(param, "pass=", 5)) { mystrncpy(state->sec->passphr, param+5, 128); - whiteout(param+5, opt->quiet); + whiteout(param+5, opt->quiet, "pass"); err += set_flag(&state->pset, "password"); #if 0 } else if (!memcmp(param, "passhex=", 8)) { @@ -350,11 +350,11 @@ } else if (!memcmp(param, "salt=", 5)) { //mystrncpy(state->sec->salt, param+5, 64); gensalt(state->sec->salt, 8, param+5, NULL, 0); - whiteout(param+5, opt->quiet); + whiteout(param+5, opt->quiet, NULL); err += set_flag(&state->sset, "salt"); } else if (!memcmp(param, "salthex=", 8)) { err += parse_hex(state->sec->salt, param+8, 8); - whiteout(param+8, opt->quiet); + whiteout(param+8, opt->quiet, NULL); err += set_flag(&state->sset, "salt"); } else if (!memcmp(param, "saltfd=", 7)) { err += read_fd(state->sec->salt, param+7, 8, "salt"); @@ -699,7 +699,7 @@ return (oln == ln? 0: 1); } -void whiteout(char* str, char quiet) +void whiteout(char* str, char quiet, const char* opt) { #ifndef NO_WRITE_ARGV int ln = strlen(str); @@ -708,8 +708,8 @@ if (ln >= 1) str[0] = 'X'; #endif - if (!quiet) - FPLOG_(-1, WARN, "Don't specify sensitive data on the command line!\n", NULL); + if (!quiet && opt) + FPLOG_(-1, WARN, "Don't specify sensitive data (%s=) on the command line!\n", opt); } const char* mybasenm(const char* nm) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dd_rescue-1.99.20/test_aes.c new/dd_rescue-1.99.21/test_aes.c --- old/dd_rescue-1.99.20/test_aes.c 2024-09-28 23:56:22.962494763 +0200 +++ new/dd_rescue-1.99.21/test_aes.c 2025-03-14 17:40:10.528737918 +0100 @@ -21,7 +21,10 @@ void usage() { - printf("Usage: test_aes [-s[-][N]] [-w] [ALG [REP [SEED [LEN [FILL]]]]]\n"); + printf("Usage: test_aes [-s[-][N]] [-w] [-2] [ALG [REP [SEED [LEN [FILL]]]]]\n"); + printf("-s: shift len by N for repeated runs\n"); + printf("-w: do a warmup round before measuring time\n"); + printf("-2: Disable VAES (fallback to AESNI if avail), x86-64 only\n"); exit(0); }