From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from imap1.codethink.co.uk (imap1.codethink.co.uk [176.9.8.82]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.server123.net (Postfix) with ESMTPS for ; Thu, 18 Jul 2019 13:41:23 +0200 (CEST) References: <40fa6a57-ac08-1f50-dbce-cadefcbf1ff4@codethink.co.uk> <0ce29b38-3f32-d2bc-651e-071075941d43@gmail.com> From: Tom Eccles Message-ID: Date: Thu, 18 Jul 2019 12:41:21 +0100 MIME-Version: 1.0 In-Reply-To: <0ce29b38-3f32-d2bc-651e-071075941d43@gmail.com> Content-Type: multipart/mixed; boundary="------------4F46AE36770EB388DA0CF6AB" Content-Language: en-GB Subject: Re: [dm-crypt] veritysetup forward error correction failure List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: dm-crypt@saout.de Cc: richardmaw@codethink.co.uk This is a multi-part message in MIME format. --------------4F46AE36770EB388DA0CF6AB Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit On 17/07/2019 8:49 pm, Milan Broz wrote: > If you can still reproduce it, please send version of the utility and > kernel (and --debug output as suggested in another mail) and if you have some > data/hash/fec images that can be used to reproduce it, let me know where I can find it. Attached is a bash script gen_image.sh which should reproduce the issue. find_and_corrupt.c should be in the working directory when gen_image.sh is run. find_and_corrupt.c corrupts the disk image by simply searching for a known string and introducing an error (see the diff outputted by gen_image.sh). See in particular the error and dmesg sample when reading the corrupted file (gen_image.sh:77) and the success when running veritysetup verify (gen_image.sh:86). I have created an issue at https://gitlab.com/cryptsetup/cryptsetup/issues/462 Thanks, Tom --------------4F46AE36770EB388DA0CF6AB Content-Type: text/x-csrc; name="find_and_corrupt.c" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="find_and_corrupt.c" #include #include #include #include #include #include #include #include #include // n <-> o is 0x6e <-> 0x6f so it is a single bit change #define SEARCH_TEXT "Can you spot this error?" #define REPLACE_TEXT "Cao you spot this error?" #define READ_SIZE 4096 // command line args enum { PROG_NAME, PATH, MAX_ARGS }; // so that we don't spend all our time in syscall overhead struct read_buf { char *buffer; ssize_t len; ssize_t read_ptr; int fd; }; static struct read_buf *read_buf_init(ssize_t size, int fd) { if (fd < 0) { return NULL; } struct read_buf *buf = malloc(sizeof(*buf)); if (buf == NULL) { return NULL; } buf->buffer = malloc(size); if (buf->buffer == NULL) { free(buf); return NULL; } buf->len = size; buf->read_ptr = -1; buf->fd = fd; return buf; } static void read_buf_free(struct read_buf *buf) { free(buf->buffer); free(buf); // doesn't close fd } static inline int read_buf_getc(struct read_buf *buf, char *out) { // if we need to do another read if (buf->read_ptr == -1 || buf->read_ptr == buf->len) { // TODO partial read ssize_t count = read(buf->fd, buf->buffer, buf->len); if (count != buf->len) { fprintf(stderr, "Read %lli, wanted %lli: %s\n", (long long) count, (long long) buf->len, strerror(errno)); return EXIT_FAILURE; } buf->read_ptr = 0; } *out = buf->buffer[buf->read_ptr++]; return EXIT_SUCCESS; } // seek through fd until we find text. // Position the file pointer at the start of the text static int find_text(const int fd, const char *text) { int ret = EXIT_FAILURE; const size_t len = strlen(text); size_t n_matching = 0; off_t offset = lseek(fd, 0, SEEK_CUR);; if (offset == -1) { fprintf(stderr, "Failed to get current offset: %s\n", strerror(errno)); return EXIT_FAILURE; } struct read_buf *buf = read_buf_init(READ_SIZE, fd); if (buf == NULL) { fprintf(stderr, "Couldn't allocate read_buf\n"); return EXIT_FAILURE; } printf("Searching for \"%s\"\n", text); while (n_matching < len) { char readc; if (read_buf_getc(buf, &readc) != EXIT_SUCCESS) { fprintf(stderr, "read_buf_getc failed\n"); goto free_buffer; } ++offset; if (readc == text[n_matching]) { ++n_matching; if (n_matching == len) { break; } } else { // not a match if (n_matching) { n_matching = 0; } } } // go back to the beginning of the text off_t err = lseek(fd, offset - len, SEEK_SET); if (err == -1) { fprintf(stderr, "Lseek error: %s\n", strerror(errno)); goto free_buffer; } printf("Found at %lli!\n", (long long) offset); ret = EXIT_SUCCESS; free_buffer: read_buf_free(buf); return ret; } static int find_and_replace(const int fd, const char *search_text, const char *replace_text) { if (find_text(fd, search_text) != EXIT_SUCCESS) { return EXIT_FAILURE; } const ssize_t len = strlen(replace_text); printf("Overwriting with \"%s\"\n", replace_text); ssize_t count = write(fd, replace_text, len); // TODO partial write if (count != len) { fprintf(stderr, "write error: %s\n", strerror(errno)); return EXIT_FAILURE; } return EXIT_SUCCESS; } static void print_help(const char *name) { fprintf(stderr, "Usage: %s FILE\n", name); } int main(int argc, char **argv) { int ret = EXIT_FAILURE; if (argc != MAX_ARGS) { print_help(argv[PROG_NAME]); return EXIT_FAILURE; } if (strcmp("--help", argv[1]) == 0 || strcmp("-h", argv[1]) == 0) { print_help(argv[PROG_NAME]); return EXIT_SUCCESS; } const char *path = argv[PATH]; int fd = open(path, O_RDWR); if (fd == -1) { int err = errno; fprintf(stderr, "Can't open %s: %i: %s\n", path, err, strerror(err)); return EXIT_FAILURE; } ret = find_and_replace(fd, SEARCH_TEXT, REPLACE_TEXT); close(fd); return ret; } --------------4F46AE36770EB388DA0CF6AB Content-Type: application/x-shellscript; name="gen_image.sh" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="gen_image.sh" IyEvYmluL2Jhc2gKCnJlYWRvbmx5IElNR19TSVpFPSI4TSIKcmVhZG9ubHkgSU1HX1BBVEg9 ImRhdGEkSU1HX1NJWkUuaW1nIgpyZWFkb25seSBDT1JSVVBUX0lNR19QQVRIPSIkSU1HX1BB VEguY29ycnVwdCIKCnJlYWRvbmx5IE1PVU5UUE9JTlQ9Im1udCIKcmVhZG9ubHkgVEVTVF9T VFI9IkNhbiB5b3Ugc3BvdCB0aGlzIGVycm9yPyIKcmVhZG9ubHkgVEVTVF9GSUxFPSIkTU9V TlRQT0lOVC90ZXN0X2ZpbGUudHh0IgoKcmVhZG9ubHkgRkVDX0lNRz0iZmVjLWltZyIKcmVh ZG9ubHkgSEFTSF9JTUc9Imhhc2gtaW1nIgoKcmVhZG9ubHkgVkVSSVRZU0VUVVBfQVJHUz0i LS12ZXJib3NlIC0tZGVidWcgLS1mZWMtZGV2aWNlIFwiJEZFQ19JTUdcIiAtLWZlYy1yb290 cyAyNCIKcmVhZG9ubHkgVkVSSVRZU0VUVVBfT1VUPSJ2ZXJpdHlzZXR1cF9mb3JtYXQub3V0 IgpyZWFkb25seSBETV9OQU1FPSJ2ZXJpdHkiCgpyZWFkb25seSBGSU5EX0FORF9DT1JSVVBU PSJmaW5kX2FuZF9jb3JydXB0IgoKcHJfZXJyKCkKewoJZWNobyAiRVJST1I6ICQqIiAxPiYy CglleGl0IDEKfQoKYXNzZXJ0X25vZXJyKCkKewoJZWNobyAiJCoiCglpZiAhIGV2YWwgIiQq IjsgdGhlbgoJCXByX2VyciAiJCoiCglmaQp9CgojIHNldCB1cCBkbS12ZXJpdHkgdm9sdW1l Cgphc3NlcnRfbm9lcnIgc3VkbyBkZCBpZj0vZGV2L3plcm8gb2Y9IiRJTUdfUEFUSCIgYnM9 IiRJTUdfU0laRSIgY291bnQ9MQoKYXNzZXJ0X25vZXJyIHN1ZG8gbWtmcy5leHQ0IC1iIDQw OTYgLUwgdmVyaXR5LWRhdGEgIiRJTUdfUEFUSCIKCmlmICEgWyAtZCAiJE1PVU5UUE9JTlQi IF07IHRoZW4KCWFzc2VydF9ub2VyciBta2RpciAiJE1PVU5UUE9JTlQiCmZpCgphc3NlcnRf bm9lcnIgc3VkbyBtb3VudCAtdCBleHQ0ICIkSU1HX1BBVEgiICIkTU9VTlRQT0lOVCIKCmFz c2VydF9ub2VyciAiZWNobyBcIiRURVNUX1NUUlwiIHwgc3VkbyB0ZWUgXCIkVEVTVF9GSUxF XCIiCgphc3NlcnRfbm9lcnIgc3VkbyB1bW91bnQgIiRJTUdfUEFUSCIKCmFzc2VydF9ub2Vy ciBzdWRvICJ2ZXJpdHlzZXR1cCAkVkVSSVRZU0VUVVBfQVJHUyBmb3JtYXQgXCIkSU1HX1BB VEhcIiBcIiRIQVNIX0lNR1wiID4gXCIkVkVSSVRZU0VUVVBfT1VUXCIiCgojIGNyZWF0ZSBh IGNvcnJ1cHRlZCB2ZXJzaW9uIG9mIHRoZSBkYXRhIGltYWdlCgppZiAhIFsgLXggIiRGSU5E X0FORF9DT1JSVVBUIiBdOyB0aGVuCglhc3NlcnRfbm9lcnIgY2MgLVdhbGwgLVdleHRyYSAt V3BlZGFudGljIC1XZXJyb3IgLU8yIGZpbmRfYW5kX2NvcnJ1cHQuYyAtbyAiJEZJTkRfQU5E X0NPUlJVUFQiCmZpCgphc3NlcnRfbm9lcnIgY3AgIiRJTUdfUEFUSCIgIiRDT1JSVVBUX0lN R19QQVRIIgoKYXNzZXJ0X25vZXJyICIuLyRGSU5EX0FORF9DT1JSVVBUIiAiJENPUlJVUFRf SU1HX1BBVEgiCgojICJDYW4iIC0+ICJDYW8iIGlzIGEgMS1iaXQgY2hhbmdlOiAweDYzIC0+ IDB4NmYKZGlmZiAtdSA8KHh4ZCAiJElNR19QQVRIIikgPCh4eGQgIiRDT1JSVVBUX0lNR19Q QVRIIikKCiMgQWNjZXNzIHZpYSB2ZXJpdHkgb3BlbgoKaGFzaD0kKGdyZXAgIlJvb3QgaGFz aDoiICIkVkVSSVRZU0VUVVBfT1VUIiB8IGN1dCAtZiAyKQppZiBbICQ/ICE9IDAgXTsgdGhl bgoJcHJfZXJyICJGYWlsZWQgdG8gZ2V0IGhhc2giCmZpCgphc3NlcnRfbm9lcnIgc3VkbyB2 ZXJpdHlzZXR1cCAiJFZFUklUWVNFVFVQX0FSR1MiIG9wZW4gIiRDT1JSVVBUX0lNR19QQVRI IiAiJERNX05BTUUiICIkSEFTSF9JTUciICIkaGFzaCIKCmFzc2VydF9ub2VyciBzdWRvIG1v dW50IC10IGV4dDQgLW8gcm8gIi9kZXYvbWFwcGVyLyRETV9OQU1FIiAiJE1PVU5UUE9JTlQi CgojIGJ1ZyBoZXJlOgpjYXQgIiRURVNUX0ZJTEUiCnN1ZG8gZG1lc2cgfCB0YWlsCgphc3Nl cnRfbm9lcnIgc3VkbyB1bW91bnQgIiRNT1VOVFBPSU5UIgoKYXNzZXJ0X25vZXJyIHN1ZG8g dmVyaXR5c2V0dXAgY2xvc2UgIiRETV9OQU1FIgoKIyBkZW1vbnN0cmF0ZSB0aGF0IHRoZSBl cnJvciBpcyBjb3JyZWN0YWJsZSBieSB2ZXJpdHlzZXR1cCB2ZXJpZnkKCmFzc2VydF9ub2Vy ciBzdWRvIHZlcml0eXNldHVwICIkVkVSSVRZU0VUVVBfQVJHUyIgdmVyaWZ5ICIkQ09SUlVQ VF9JTUdfUEFUSCIgIiRIQVNIX0lNRyIgIiRoYXNoIgoKZWNobyAiU3VjY2VzcyIK --------------4F46AE36770EB388DA0CF6AB--