[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#773212: unblock: 0xffff/0.6.1-1



Package: release.debian.org
Severity: normal
User: release.debian.org@packages.debian.org
Usertags: unblock

---Please unblock package 0xffff---

Note: I have not yet uploaded 0.6.1-1 to sid, but its available from
experimental. I sent a mail to debian-release, but have been request to
file an unblock bug instead.

So I've uploaded 0xffff 0.6.1-1 to experimental, which is a minor
upstream release with 90% bug fixes (some of them security relevant).
Since the diff is quite big I wanted to make sure, that the release
team is ok with the changes before uploading them to sid (and let them
transition to testing).

-- Sebastian

$ debdiff 0xffff_0.6-1.dsc 0xffff_0.6.1-1.dsc
diff -Nru 0xffff-0.6/config.mk 0xffff-0.6.1/config.mk
--- 0xffff-0.6/config.mk	2014-05-10 22:39:47.000000000 +0200
+++ 0xffff-0.6.1/config.mk	2014-11-18 23:23:23.000000000 +0100
@@ -1,4 +1,4 @@
-VERSION = 0.6
+VERSION = 0.6.1
 PREFIX = /usr/local
 
 # NetBSD stuff
diff -Nru 0xffff-0.6/debian/changelog 0xffff-0.6.1/debian/changelog
--- 0xffff-0.6/debian/changelog	2014-05-12 19:32:47.000000000 +0200
+++ 0xffff-0.6.1/debian/changelog	2014-12-11 21:53:03.000000000 +0100
@@ -1,3 +1,13 @@
+0xffff (0.6.1-1) experimental; urgency=medium
+
+  * New upstream release
+   - Contains a few security related fixes (memory corruptions & leaks)
+   - Support for -t (filter by type) for -e (dump images)
+   - reattach kernel driver
+   - minor fixes
+
+ -- Sebastian Reichel <sre@debian.org>  Thu, 11 Dec 2014 21:52:53 +0100
+
 0xffff (0.6-1) unstable; urgency=low
 
   * New upstream release
diff -Nru 0xffff-0.6/src/cold-flash.c 0xffff-0.6.1/src/cold-flash.c
--- 0xffff-0.6/src/cold-flash.c	2014-05-10 22:39:47.000000000 +0200
+++ 0xffff-0.6.1/src/cold-flash.c	2014-11-18 23:23:23.000000000 +0100
@@ -130,7 +130,7 @@
 	uint32_t size; /* 4 bytes - size of file */
 	uint32_t crc1; /* 4 bytes - crc32 of file */
 	uint32_t crc2; /* 4 bytes - crc32 of first 12 bytes of message */
-};
+} __attribute__((__packed__));
 
 #define XLOADER_MSG_TYPE_PING	0x6301326E
 #define XLOADER_MSG_TYPE_SEND	0x6302326E
diff -Nru 0xffff-0.6/src/fiasco.c 0xffff-0.6.1/src/fiasco.c
--- 0xffff-0.6/src/fiasco.c	2014-05-10 22:39:47.000000000 +0200
+++ 0xffff-0.6.1/src/fiasco.c	2014-11-18 23:23:23.000000000 +0100
@@ -192,9 +192,12 @@
 					if ( ! hwrevs[0] )
 						strcpy(hwrevs, hwrev);
 					else {
-						/* TODO: check if hwrevs has enough size */
-						strcat(hwrevs, ",");
-						strcat(hwrevs, hwrev);
+						size_t len1 = strlen(hwrevs);
+						size_t len2 = strlen(hwrev);
+						if ( len1 + len2 + 2 < sizeof(hwrevs) ) {
+							hwrevs[len1] = ',';
+							memcpy(hwrevs+len1+1, hwrev, len2+1);
+						}
 					}
 					VERBOSE("       hw revision: %s\n", hwrev);
 					pbuf += strlen(hwrev) + 1;
@@ -410,6 +413,7 @@
 			WRITE_OR_FAIL(file, fd, "2", 1); /* 2 - device & hwrevs */
 			WRITE_OR_FAIL(file, fd, &device_hwrevs_bufs[i][0], 1);
 			WRITE_OR_FAIL(file, fd, device_hwrevs_bufs[i]+1, ((uint8_t *)(device_hwrevs_bufs[i]))[0]);
+			/* FIXME: memory leak: device_hwrevs_bufs */
 		}
 		free(device_hwrevs_bufs);
 
@@ -449,9 +453,9 @@
 
 int fiasco_unpack(struct fiasco * fiasco, const char * dir) {
 
-	int fd = -1;
-	char * name = NULL;
-	char * layout_name = NULL;
+	int fd;
+	char * name;
+	char * layout_name;
 	struct image * image;
 	struct image_list * image_list;
 	uint32_t size;
@@ -480,6 +484,10 @@
 
 	while ( image_list ) {
 
+		fd = -1;
+		name = NULL;
+		layout_name = NULL;
+
 		image = image_list->image;
 
 		name = image_name_alloc_from_values(image);
@@ -492,9 +500,11 @@
 
 		if ( image->layout ) {
 
-			layout_name = calloc(1, strlen(name) + strlen(".layout") + 1);
-			if ( ! layout_name )
+			layout_name = calloc(1, strlen(name) + sizeof(".layout")-1 + 1);
+			if ( ! layout_name ) {
+				free(name);
 				ALLOC_ERROR_RETURN(-1);
+			}
 
 			sprintf(layout_name, "%s.layout", name);
 
@@ -508,21 +518,32 @@
 			fd = open(name, O_RDWR|O_CREAT|O_TRUNC, 0644);
 			if ( fd < 0 ) {
 				ERROR_INFO("Cannot create output file %s", name);
+				free(name);
+				free(layout_name);
 				return -1;
 			}
 		}
 
-		free(name);
-
 		image_seek(image, 0);
 		while ( 1 ) {
 			size = image_read(image, buf, sizeof(buf));
 			if ( size == 0 )
 				break;
-			WRITE_OR_FAIL(name, fd, buf, size);
+			if ( ! simulate ) {
+				if ( write(fd, buf, size) != (ssize_t)size ) {
+					ERROR_INFO_STR(name, "Cannot write %d bytes", size);
+					close(fd);
+					free(name);
+					free(layout_name);
+					return -1;
+				}
+			}
 		}
 
-		close(fd);
+		free(name);
+
+		if ( ! simulate )
+			close(fd);
 
 		if ( image->layout ) {
 
@@ -530,15 +551,24 @@
 				fd = open(layout_name, O_RDWR|O_CREAT|O_TRUNC, 0644);
 				if ( fd < 0 ) {
 					ERROR_INFO("Cannot create layout file %s", layout_name);
+					free(layout_name);
+					return -1;
+				}
+
+				size = strlen(image->layout);
+
+				if ( write(fd, image->layout, size) != (ssize_t)size ) {
+					ERROR_INFO_STR(layout_name, "Cannot write %d bytes", size);
+					close(fd);
+					free(layout_name);
 					return -1;
 				}
 			}
 
 			free(layout_name);
 
-			WRITE_OR_FAIL(layout_name, fd, image->layout, (int)strlen(image->layout));
-
-			close(fd);
+			if ( ! simulate )
+				close(fd);
 
 		}
 
diff -Nru 0xffff-0.6/src/image.c 0xffff-0.6.1/src/image.c
--- 0xffff-0.6/src/image.c	2014-05-10 22:39:47.000000000 +0200
+++ 0xffff-0.6.1/src/image.c	2014-11-18 23:23:23.000000000 +0100
@@ -88,14 +88,13 @@
 
 	if ( image->devices && image->devices->device && ! image->devices->hwrevs )
 		image->devices->hwrevs = hwrevs_alloc_from_string(hwrevs);
-	else
-		free(hwrevs);
 
 	if ( ! image->version )
 		image->version = version;
 	else
 		free(version);
 
+	free(hwrevs);
 	free(str);
 
 }
@@ -135,8 +134,10 @@
 		length += 1 + strlen(image->version);
 
 	name = calloc(1, length);
-	if ( ! name )
+	if ( ! name ) {
+		free(hwrevs);
 		ALLOC_ERROR_RETURN(NULL);
+	}
 
 	strcpy(name, type);
 	ptr = name + strlen(name);
diff -Nru 0xffff-0.6/src/local.c 0xffff-0.6.1/src/local.c
--- 0xffff-0.6/src/local.c	2014-05-10 22:39:47.000000000 +0200
+++ 0xffff-0.6.1/src/local.c	2014-11-18 23:23:23.000000000 +0100
@@ -127,9 +127,9 @@
 
 	while ( fgets(buf, sizeof(buf), file) ) {
 
-		if ( strncmp(buf, "Hardware", strlen("Hardware")) == 0 ) {
+		if ( strncmp(buf, "Hardware", sizeof("Hardware")-1) == 0 ) {
 
-			ptr = buf + strlen("Hardware");
+			ptr = buf + sizeof("Hardware")-1;
 
 			while ( ptr < buf + sizeof(buf) && *ptr > 0 && *ptr <= 32 )
 				++ptr;
@@ -316,21 +316,23 @@
 
 		while ( ( dirent = readdir(dir) ) ) {
 
-			snprintf(buf, sizeof(buf), "/sys/class/mmc_host/%s/slot_name", dirent->d_name);
+			if ( snprintf(buf, sizeof(buf), "/sys/class/mmc_host/%s/slot_name", dirent->d_name) <= 0 )
+				continue;
 
 			fd = open(buf, O_RDONLY);
 			if ( fd < 0 )
 				continue;
 
-			buf[0] = 0;
-			if ( read(fd, buf, sizeof(buf)) < 0 )
+			memset(buf, 0, sizeof(buf));
+			if ( read(fd, buf, sizeof(buf)-1) < 0 )
 				buf[0] = 0;
 			close(fd);
 
-			if ( strncmp(buf, "internal", strlen("internal")) != 0 )
+			if ( strncmp(buf, "internal", sizeof("internal")-1) != 0 )
 				continue;
 
-			snprintf(buf, sizeof(buf), "/sys/class/mmc_host/%s/%s:0001/", dirent->d_name, dirent->d_name);
+			if ( snprintf(buf, sizeof(buf), "/sys/class/mmc_host/%s/%s:0001/", dirent->d_name, dirent->d_name) <= 0 )
+				continue;
 
 			dir2 = opendir(buf);
 			if ( ! dir2 )
@@ -338,10 +340,11 @@
 
 			while ( ( dirent2 = readdir(dir2) ) ) {
 
-				if ( strncmp(dirent2->d_name, "block:mmcblk", strlen("block:mmcblk")) != 0 )
+				if ( strncmp(dirent2->d_name, "block:mmcblk", sizeof("block:mmcblk")-1) != 0 )
 					continue;
 
-				snprintf(buf, sizeof(buf), "/sys/class/mmc_host/%s/%s:0001/%s/dev", dirent->d_name, dirent->d_name, dirent2->d_name);
+				if ( snprintf(buf, sizeof(buf), "/sys/class/mmc_host/%s/%s:0001/%s/dev", dirent->d_name, dirent->d_name, dirent2->d_name) <= 0 )
+					continue;
 
 				f = fopen(buf, "r");
 				if ( ! f )
@@ -385,7 +388,8 @@
 
 		while ( ( dirent = readdir(dir) ) ) {
 
-			snprintf(buf, sizeof(buf), "/dev/%s", dirent->d_name);
+			if ( snprintf(buf, sizeof(buf), "/dev/%s", dirent->d_name) <= 0 )
+				continue;
 
 			if ( stat(buf, &st) != 0 )
 				continue;
@@ -410,7 +414,7 @@
 
 		VERBOSE("Detected internal mmc device: '%s'\n", blk);
 
-		strncat(blk, "p1", sizeof(blk));
+		strncat(blk, "p1", sizeof(blk)-strlen(blk)-1);
 
 		printf("Using MyDocs mmc device: '%s'\n", blk);
 
@@ -457,6 +461,10 @@
 		if ( addr[nlen-1] != 0xFF )
 			break;
 
+	for ( ; nlen > 0; --nlen )
+		if ( addr[nlen-1] != 0x00 )
+			break;
+
 	if ( image == IMAGE_MMC )
 		align = 8;
 	else
@@ -532,7 +540,7 @@
 
 int local_get_rd_mode(void) {
 
-	if ( strncmp(rd_mode, "master", strlen("master")) == 0 )
+	if ( strncmp(rd_mode, "master", sizeof("master")-1) == 0 )
 		return 1;
 	else
 		return 0;
@@ -551,8 +559,8 @@
 
 	const char * ptr;
 
-	if ( strncmp(rd_mode, "master", strlen("master")) == 0 )
-		ptr = rd_mode + strlen("master");
+	if ( strncmp(rd_mode, "master", sizeof("master")-1) == 0 )
+		ptr = rd_mode + sizeof("master")-1;
 	else
 		ptr = rd_mode;
 
diff -Nru 0xffff-0.6/src/main.c 0xffff-0.6.1/src/main.c
--- 0xffff-0.6/src/main.c	2014-05-10 22:39:47.000000000 +0200
+++ 0xffff-0.6.1/src/main.c	2014-11-18 23:23:23.000000000 +0100
@@ -53,8 +53,8 @@
 		" -f              flash all specified images\n"
 		" -c              cold flash 2nd and secondary images\n"
 		" -x [/dev/mtd]   check for bad blocks on mtd device (default: all)\n"
-		" -E file         dump all device images to one fiasco image, see -t\n"
-		" -e [dir]        dump all device images to directory, see -t (default: current)\n"
+		" -E file         dump all device images to one fiasco image\n"
+		" -e [dir]        dump all device images (or one -t) to directory (default: current)\n"
 		"\n"
 
 		"Device configuration:\n"
@@ -84,7 +84,7 @@
 		"\n"
 
 		"Image filters:\n"
-		" -t types        filter images by type\n"
+		" -t type         filter images by type\n"
 		" -d dev          filter images by device\n"
 		" -w hw           filter images by HW revision\n"
 		"\n"
@@ -210,7 +210,7 @@
 			exit(1);
 		}
 		lseek(fd, 0, SEEK_SET);
-		layout = malloc(len);
+		layout = malloc(len+1);
 		if ( ! layout ) {
 			ALLOC_ERROR();
 			exit(1);
@@ -219,6 +219,8 @@
 			ERROR_INFO("Cannot read %lu bytes from layout file %s", len, layout_file);
 			exit(1);
 		}
+		layout[len] = 0;
+		close(fd);
 	}
 
 	image = image_alloc_from_file(file, type, device, hwrevs, version, layout);
@@ -661,6 +663,9 @@
 			goto clean;
 		}
 		filter_images_by_type(type, &image_first);
+		/* make sure that fiasco_in has valid images */
+		if ( fiasco_in )
+			fiasco_in->first = image_first;
 	}
 
 	/* filter images by device */
@@ -672,11 +677,18 @@
 			goto clean;
 		}
 		filter_images_by_device(device, &image_first);
+		/* make sure that fiasco_in has valid images */
+		if ( fiasco_in )
+			fiasco_in->first = image_first;
 	}
 
 	/* filter images by hwrev */
-	if ( filter_hwrev )
+	if ( filter_hwrev ) {
 		filter_images_by_hwrev(atoi(filter_hwrev_arg), &image_first);
+		/* make sure that fiasco_in has valid images */
+		if ( fiasco_in )
+			fiasco_in->first = image_first;
+	}
 
 	/* reorder images for flashing (first x-loader, second secondary) */
 	/* set 2nd and secondary images for cold-flashing */
@@ -740,11 +752,29 @@
 			image_ptr = next;
 		}
 
+		/* make sure that fiasco_in has valid images */
+		if ( fiasco_in )
+			fiasco_in->first = image_first;
+
 	}
 
-	/* make sure that fiasco_in has valid images*/
-	if ( fiasco_in )
-		fiasco_in->first = image_first;
+	/* remove 2nd image when doing normal flash */
+	if ( dev_flash ) {
+		image_ptr = image_first;
+		while ( image_ptr ) {
+			struct image_list * next = image_ptr->next;
+			if ( image_ptr->image->type == IMAGE_2ND ) {
+				if ( image_ptr == image_first )
+					image_first = next;
+				image_list_del(image_ptr);
+			}
+			image_ptr = next;
+		}
+
+		/* make sure that fiasco_in has valid images */
+		if ( fiasco_in )
+			fiasco_in->first = image_first;
+	}
 
 	/* identify images */
 	if ( image_ident ) {
@@ -782,8 +812,9 @@
 			WARNING("Removing unknown image (specified by %s %s)", image_ptr->image->orig_filename ? "file" : "fiasco", image_ptr->image->orig_filename ? image_ptr->image->orig_filename : "image");
 			if ( image_ptr == image_first )
 				image_first = next;
-			image_list_unlink(image_ptr);
-			free(image_ptr);
+			if ( fiasco_in && image_ptr == fiasco_in->first )
+				fiasco_in->first = fiasco_in->first->next;
+			image_list_del(image_ptr);
 		}
 		image_ptr = next;
 	}
@@ -983,6 +1014,8 @@
 				filter_images_by_device(dev->detected_device, &image_first);
 			if ( detected_hwrev )
 				filter_images_by_hwrev(dev->detected_hwrev, &image_first);
+			if ( fiasco_in && ( detected_device || detected_hwrev ) )
+				fiasco_in->first = image_first;
 
 			/* set kernel and initfs images for loading */
 			if ( dev_load ) {
@@ -1047,8 +1080,7 @@
 					if ( fiasco_in && image_kernel == fiasco_in->first )
 						fiasco_in->first = fiasco_in->first->next;
 
-					image_list_unlink(image_kernel);
-					free(image_kernel);
+					image_list_del(image_kernel);
 					image_kernel = NULL;
 				}
 
@@ -1059,11 +1091,10 @@
 
 					if ( image_initfs == image_first )
 						image_first = image_first->next;
-					if ( fiasco_in && image_kernel == fiasco_in->first )
+					if ( fiasco_in && image_initfs == fiasco_in->first )
 						fiasco_in->first = fiasco_in->first->next;
 
-					image_list_unlink(image_initfs);
-					free(image_initfs);
+					image_list_del(image_initfs);
 					image_initfs = NULL;
 				}
 			}
@@ -1079,11 +1110,10 @@
 
 					if ( image_ptr == image_first )
 						image_first = image_first->next;
-					if ( fiasco_in && image_kernel == fiasco_in->first )
+					if ( fiasco_in && image_ptr == fiasco_in->first )
 						fiasco_in->first = fiasco_in->first->next;
 
-					image_list_unlink(image_ptr);
-					free(image_ptr);
+					image_list_del(image_ptr);
 					image_ptr = next;
 				}
 			}
@@ -1175,9 +1205,21 @@
 						buf[0] = 0;
 				}
 
-				for ( i = 0; i < IMAGE_COUNT; ++i )
-					if ( image_tmp_name(i) )
-						dev_dump_image(dev, i, image_tmp_name(i));
+				if ( filter_type ) {
+					enum image_type type = image_type_from_string(filter_type_arg);
+					if ( ! type || ! image_tmp_name(type) ) {
+						ERROR("Specified unknown image type for filtering: %s", filter_type_arg);
+						ret = 1;
+						goto clean;
+					}
+					ret = dev_dump_image(dev, type, image_tmp_name(type));
+					if ( ret != 0 )
+						goto clean;
+				} else {
+					for ( i = 0; i < IMAGE_COUNT; ++i )
+						if ( image_tmp_name(i) )
+							dev_dump_image(dev, i, image_tmp_name(i));
+				}
 
 				if ( buf[0] )
 					if ( chdir(buf) < 0 )
@@ -1196,7 +1238,8 @@
 					if ( ! image_tmp_name(i) )
 						continue;
 
-					sprintf(buf, "%hd", dev->detected_hwrev);
+					buf[0] = 0;
+					snprintf(buf, sizeof(buf), "%hd", dev->detected_hwrev);
 
 					switch ( i ) {
 						case IMAGE_2ND:
@@ -1298,14 +1341,16 @@
 							break;
 					}
 
-					sprintf(buf, "%s-%s:%hd_%s", image_type_to_string(i), device_to_string(dev->detected_device), dev->detected_hwrev, ptr);
+					buf[0] = 0;
+					snprintf(buf, sizeof(buf), "%s-%s:%hd_%s", image_type_to_string(i), device_to_string(dev->detected_device), dev->detected_hwrev, ptr);
 					printf("Renaming %s image file to %s...\n", image_type_to_string(i), buf);
 
 					if ( rename(image_tmp_name(i), buf) < 0 ) {
 
 						ERROR_INFO("Renaming failed");
 
-						sprintf(buf, "%s-%s_%s", image_type_to_string(i), device_to_string(dev->detected_device), ptr);
+						buf[0] = 0;
+						snprintf(buf, sizeof(buf), "%s-%s_%s", image_type_to_string(i), device_to_string(dev->detected_device), ptr);
 						printf("Trying to rename %s image file to %s...\n", image_type_to_string(i), buf);
 
 						if ( rename(image_tmp_name(i), buf) < 0 )
diff -Nru 0xffff-0.6/src/Makefile 0xffff-0.6.1/src/Makefile
--- 0xffff-0.6/src/Makefile	2014-05-10 22:39:47.000000000 +0200
+++ 0xffff-0.6.1/src/Makefile	2014-11-18 23:23:23.000000000 +0100
@@ -31,10 +31,10 @@
 	mv $@.tmp $@
 
 libusb-sniff-32.so: libusb-sniff.c $(DEPENDS)
-	$(CC) $(CFLAGS) $(LDFLAGS) -fPIC -ldl -shared -m32 -o $@ $<
+	$(CC) $(CFLAGS) $(LDFLAGS) -fPIC $< -ldl -shared -m32 -o $@
 
 libusb-sniff-64.so: libusb-sniff.c $(DEPENDS)
-	$(CC) $(CFLAGS) $(LDFLAGS) -fPIC -ldl -shared -m64 -o $@ $<
+	$(CC) $(CFLAGS) $(LDFLAGS) -fPIC $< -ldl -shared -m64 -o $@
 
 %.o: %.c $(DEPENDS)
 	$(CROSS_CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
diff -Nru 0xffff-0.6/src/nolo.c 0xffff-0.6.1/src/nolo.c
--- 0xffff-0.6/src/nolo.c	2014-05-10 22:39:47.000000000 +0200
+++ 0xffff-0.6.1/src/nolo.c	2014-11-18 23:23:23.000000000 +0100
@@ -84,12 +84,14 @@
 
 	char buf[2048];
 	size_t i, count;
+	int ret;
 
 	for ( count = 0; count < 20; ++count ) {
 
 		memset(buf, 0, sizeof(buf));
 
-		if ( usb_control_msg(dev->udev, NOLO_QUERY, NOLO_ERROR_LOG, 0, 0, buf, sizeof(buf), 2000) <= 0 )
+		ret = usb_control_msg(dev->udev, NOLO_QUERY, NOLO_ERROR_LOG, 0, 0, buf, sizeof(buf), 2000);
+		if ( ret < 0 )
 			break;
 
 		if ( ! only_clear ) {
@@ -103,6 +105,9 @@
 
 		}
 
+		if ( (size_t)ret < sizeof(buf) )
+			break;
+
 	}
 
 }
@@ -176,14 +181,14 @@
 	if ( strlen(str) > 500 )
 		return -1;
 
-	sprintf(buf, "version:%s", str);
+	if ( sprintf(buf, "version:%s", str) <= 0 )
+		return -1;
 
 	ret = nolo_get_string(dev, buf, out, size);
-
-	nolo_error_log(dev, 1);
-
-	if ( ret < 0 )
+	if ( ret < 0 ) {
+		nolo_error_log(dev, 1);
 		return ret;
+	}
 
 	if ( ! out[0] )
 		return -1;
@@ -311,7 +316,7 @@
 		if ( bufs ) {
 
 			memset(buf, 0, sizeof(buf));
-			snprintf(buf, 8, "%d", dev->hwrev);
+			snprintf(buf, 8+1, "%d", dev->hwrev);
 
 			for ( i = 0; bufs[i]; ++i ) {
 				len = ((uint8_t*)bufs[i])[0];
@@ -418,8 +423,8 @@
 	unsigned long long int part;
 	unsigned long long int total;
 	unsigned long long int last_total;
-	char status[20];
 	char buf[128];
+	char * ptr;
 
 	if ( image->type == IMAGE_ROOTFS )
 		flash = 1;
@@ -463,7 +468,7 @@
 		if ( nolo_get_string(dev, "cmt:status", buf, sizeof(buf)) < 0 )
 			NOLO_ERROR_RETURN("cmt:status failed", -1);
 
-		if ( strncmp(buf, "idle", strlen("idle")) == 0 )
+		if ( strncmp(buf, "idle", sizeof("idle")-1) == 0 )
 			state = 4;
 		else
 			printf("Erasing CMT...\n");
@@ -475,7 +480,7 @@
 				NOLO_ERROR_RETURN("cmt:status failed", -1);
 			}
 
-			if ( strncmp(buf, "finished", strlen("finished")) == 0 ) {
+			if ( strncmp(buf, "finished", sizeof("finished")-1) == 0 ) {
 
 				if ( state <= 0 ) {
 					printf_progressbar(last_total, last_total);
@@ -490,18 +495,29 @@
 
 				state = 4;
 
+			} else if ( strncmp(buf, "error", sizeof("error")-1) == 0 ) {
+
+				PRINTF_ERROR_RETURN("cmt:status error", -1);
+
 			} else {
 
-				if ( sscanf(buf, "%s:%llu/%llu", status, &part, &total) != 3 )
+				ptr = strchr(buf, ':');
+				if ( ! ptr )
+					PRINTF_ERROR_RETURN("cmt:status unknown", -1);
+
+				*ptr = 0;
+				ptr++;
+
+				if ( sscanf(ptr, "%llu/%llu", &part, &total) != 2 )
 					PRINTF_ERROR_RETURN("cmt:status unknown", -1);
 
-				if ( strcmp(status, "program") == 0 && state <= 0 ) {
+				if ( strcmp(buf, "program") == 0 && state <= 0 ) {
 					printf_progressbar(last_total, last_total);
 					printf("Done\n");
 					state = 1;
 				}
 
-				if ( strcmp(status, "program") == 0 && state <= 1 ) {
+				if ( strcmp(buf, "program") == 0 && state <= 1 ) {
 					printf("Programming CMT...\n");
 					state = 2;
 				}
@@ -509,12 +525,12 @@
 				printf_progressbar(part, total);
 				last_total = total;
 
-				if ( strcmp(status, "erase") == 0 && state <= 0 && part == total ) {
+				if ( strcmp(buf, "erase") == 0 && state <= 0 && part == total ) {
 					printf("Done\n");
 					state = 1;
 				}
 
-				if ( strcmp(status, "program") == 0 && state <= 2 && part == total ) {
+				if ( strcmp(buf, "program") == 0 && state <= 2 && part == total ) {
 					printf("Done\n");
 					state = 3;
 				}
@@ -536,9 +552,9 @@
 	int size = 0;
 	int mode = NOLO_BOOT_MODE_NORMAL;
 
-	if ( cmdline && strncmp(cmdline, "update", strlen("update")) == 0 && cmdline[strlen("update")] <= 32 ) {
+	if ( cmdline && strncmp(cmdline, "update", sizeof("update")-1) == 0 && cmdline[sizeof("update")-1] <= 32 ) {
 		mode = NOLO_BOOT_MODE_UPDATE;
-		cmdline += strlen("update");
+		cmdline += sizeof("update")-1;
 		if ( *cmdline ) ++cmdline;
 		while ( *cmdline && *cmdline <= 32 )
 			++cmdline;
@@ -763,7 +779,7 @@
 
 	char buf[9];
 	memset(buf, 0, sizeof(buf));
-	snprintf(buf, 8, "%d", hwrev);
+	snprintf(buf, sizeof(buf), "%d", hwrev);
 	printf("Setting HW revision to: %s\n", buf);
 	return nolo_set_string(dev, "hw_rev", buf);
 
diff -Nru 0xffff-0.6/src/printf-utils.c 0xffff-0.6.1/src/printf-utils.c
--- 0xffff-0.6/src/printf-utils.c	2014-05-10 22:39:47.000000000 +0200
+++ 0xffff-0.6.1/src/printf-utils.c	2014-11-18 23:23:23.000000000 +0100
@@ -39,7 +39,7 @@
 	int tmp, cols = 80;
 
 	/* percentage calculation */
-	pc = (int)(part*100/total);
+	pc = total==0?100:(int)(part*100/total);
 	(pc<0)?pc=0:(pc>100)?pc=100:0;
 
 	PRINTF_BACK();
diff -Nru 0xffff-0.6/src/usb-device.c 0xffff-0.6.1/src/usb-device.c
--- 0xffff-0.6/src/usb-device.c	2014-05-10 22:39:47.000000000 +0200
+++ 0xffff-0.6.1/src/usb-device.c	2014-11-18 23:23:23.000000000 +0100
@@ -27,6 +27,10 @@
 
 #include <usb.h>
 
+#ifdef LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP
+#include <sys/ioctl.h>
+#endif
+
 #include "global.h"
 #include "device.h"
 #include "usb-device.h"
@@ -73,6 +77,25 @@
 
 }
 
+static void usb_reattach_kernel_driver(usb_dev_handle * udev, int interface) {
+
+#ifdef LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP
+	struct {
+		int ifno;
+		int ioctl_code;
+		void * data;
+	} command = {
+		.ifno = interface,
+		.ioctl_code = _IO('U', 23),
+		.data = NULL,
+	};
+
+	usb_release_interface(udev, interface);
+	ioctl(*((int *)udev), _IOWR('U', 18, command), &command);
+#endif
+
+}
+
 static void usb_descriptor_info_print(usb_dev_handle * udev, struct usb_device * dev, char * product, size_t size) {
 
 	char buf[1024];
@@ -145,6 +168,7 @@
 			if ( usb_claim_interface(udev, usb_devices[i].interface) < 0 ) {
 				PRINTF_ERROR("usb_claim_interface failed");
 				fprintf(stderr, "\n");
+				usb_reattach_kernel_driver(udev, usb_devices[i].interface);
 				usb_close(udev);
 				return NULL;
 			}
@@ -154,6 +178,7 @@
 				if ( usb_set_altinterface(udev, usb_devices[i].alternate) < 0 ) {
 					PRINTF_ERROR("usb_claim_interface failed");
 					fprintf(stderr, "\n");
+					usb_reattach_kernel_driver(udev, usb_devices[i].interface);
 					usb_close(udev);
 					return NULL;
 				}
@@ -164,6 +189,7 @@
 				if ( usb_set_configuration(udev, usb_devices[i].configuration) < 0 ) {
 					PRINTF_ERROR("usb_set_configuration failed");
 					fprintf(stderr, "\n");
+					usb_reattach_kernel_driver(udev, usb_devices[i].interface);
 					usb_close(udev);
 					return NULL;
 				}
@@ -172,6 +198,7 @@
 			ret = calloc(1, sizeof(struct usb_device_info));
 			if ( ! ret ) {
 				ALLOC_ERROR();
+				usb_reattach_kernel_driver(udev, usb_devices[i].interface);
 				usb_close(udev);
 				return NULL;
 			}
@@ -197,7 +224,9 @@
 				if ( ! *device ) {
 					ERROR("Device mishmash");
 					fprintf(stderr, "\n");
+					usb_reattach_kernel_driver(udev, usb_devices[i].interface);
 					usb_close(udev);
+					free(ret);
 					return NULL;
 				}
 			}
@@ -308,6 +337,7 @@
 
 void usb_close_device(struct usb_device_info * dev) {
 
+	usb_reattach_kernel_driver(dev->udev, dev->flash_device->interface);
 	usb_close(dev->udev);
 	free(dev);
 
diff -Nru 0xffff-0.6/.travis.yml 0xffff-0.6.1/.travis.yml
--- 0xffff-0.6/.travis.yml	1970-01-01 01:00:00.000000000 +0100
+++ 0xffff-0.6.1/.travis.yml	2014-11-18 23:23:23.000000000 +0100
@@ -0,0 +1,20 @@
+language: c
+compiler:
+  - gcc
+before_install:
+  - sudo apt-get update -qq
+  - sudo apt-get install -qq -y libusb-dev
+script: if [ ${COVERITY_SCAN_BRANCH} != 1 ]; then make ; fi
+
+env:
+  global:
+   - secure: "JdUp+xFykPZoYA4aRfmYk2CtilLapniQllWPKo2dDdJd1vzdawfTvVxIAKjy7ac9RKwZzg3Chq3RsMEXPv8BtaLbssw266C7RDLMgjacl1eFLcmGRj/Gkk9peDSZ6vVdGEcA2j+6KDSfpCa/XjFjvOufZOgKw6m+3+d0A4G45SI="
+
+addons:
+  coverity_scan:
+    project:
+      name: "pali/0xFFFF"
+      description: "Build submitted via Travis CI"
+    notification_email: pali.rohar@gmail.com
+    build_command: "make"
+    branch_pattern: master


Reply to: