Subject: loadfile_*() returns an incorrect errno?
To: None <tech-install@NetBSD.org>
From: Tetsuya Isaki <isaki@par.odn.ne.jp>
List: tech-install
Date: 11/18/2007 16:58:02
In fdloadfile() (in sys/lib/libsa/loadfile.c),
loadfile_*() returns -1 and sets global variable errno,
if error happened.  But loadfile_*() returns -1 without
setting errno, if read() is short.

Therefore, fdloadfile() may return error code 0 (= success)
when read() in loadfile_*() is short.

I think that loadfile_*() should always set errno when
returns -1.  So, how about the attached patch?  But I'm 
not sure whether ESHORT is good.

P.S. May I do a style fix in sys/lib/libsa?
---
Tetsuya Isaki <isaki@par.odn.ne.jp / isaki@NetBSD.org>

Index: sys/lib/libsa/loadfile_aout.c
===================================================================
RCS file: /cvsroot/src/sys/lib/libsa/loadfile_aout.c,v
retrieving revision 1.9
diff -u -r1.9 loadfile_aout.c
--- sys/lib/libsa/loadfile_aout.c	5 Jun 2007 08:48:50 -0000	1.9
+++ sys/lib/libsa/loadfile_aout.c	10 Nov 2007 12:49:50 -0000
@@ -105,6 +105,7 @@
 	paddr_t offset = marks[MARK_START];
 	u_long magic = N_GETMAGIC(*x);
 	int sub;
+	ssize_t nr;
 
 	/* some ports dont use the offset */
 	offset = offset;
@@ -144,8 +145,13 @@
 	if (flags & LOAD_TEXT) {
 		PROGRESS(("%ld", x->a_text));
 
-		if (READ(fd, maxp, x->a_text - sub) !=
-		    (ssize_t)(x->a_text - sub)) {
+		nr = READ(fd, maxp, x->a_text - sub);
+		if (nr == -1) {
+			WARN(("read text"));
+			return 1;
+		}
+		if (nr != (ssize_t)(x->a_text - sub)) {
+			errno = ESHORT;
 			WARN(("read text"));
 			return 1;
 		}
@@ -180,7 +186,13 @@
 		PROGRESS(("+%ld", x->a_data));
 
 		marks[MARK_DATA] = LOADADDR(maxp);
-		if (READ(fd, maxp, x->a_data) != (ssize_t)x->a_data) {
+		nr = READ(fd, maxp, x->a_data);
+		if (nr == -1) {
+			WARN(("read data"));
+			return 1;
+		}
+		if (nr != (ssize_t)x->a_data) {
+			errno = ESHORT;
 			WARN(("read data"));
 			return 1;
 		}
@@ -225,7 +237,13 @@
 		if (flags & LOAD_SYM) {
 			PROGRESS(("+[%ld", x->a_syms));
 
-			if (READ(fd, maxp, x->a_syms) != (ssize_t)x->a_syms) {
+			nr = READ(fd, maxp, x->a_syms);
+			if (nr == -1) {
+				WARN(("read symbols"));
+				return 1;
+			}
+			if (nr != (ssize_t)x->a_syms) {
+				errno = ESHORT;
 				WARN(("read symbols"));
 				return 1;
 			}
@@ -238,7 +256,13 @@
 		if (flags & (LOAD_SYM|COUNT_SYM))
 			maxp += x->a_syms;
 
-		if (read(fd, &cc, sizeof(cc)) != sizeof(cc)) {
+		nr = read(fd, &cc, sizeof(cc));
+		if (nr == -1) {
+			WARN(("read string table"));
+			return 1;
+		}
+		if (nr != sizeof(cc)) {
+			errno = ESHORT;
 			WARN(("read string table"));
 			return 1;
 		}
@@ -260,7 +284,13 @@
 		}
 
 		if (flags & LOAD_SYM) {
-			if (READ(fd, maxp, cc) != cc) {
+			nr = READ(fd, maxp, cc);
+			if (nr == -1) {
+				WARN(("read strings"));
+				return 1;
+			}
+			if (nr != cc) {
+				errno = ESHORT;
 				WARN(("read strings"));
 				return 1;
 			}
Index: sys/lib/libsa/loadfile_ecoff.c
===================================================================
RCS file: /cvsroot/src/sys/lib/libsa/loadfile_ecoff.c,v
retrieving revision 1.8
diff -u -r1.8 loadfile_ecoff.c
--- sys/lib/libsa/loadfile_ecoff.c	6 Jun 2007 07:56:39 -0000	1.8
+++ sys/lib/libsa/loadfile_ecoff.c	10 Nov 2007 12:49:50 -0000
@@ -66,6 +66,7 @@
 {
 	paddr_t offset = marks[MARK_START];
 	paddr_t minp = ~0, maxp = 0, pos;
+	ssize_t nr;
 
 	/* some ports dont use the offset */
 	offset = offset;
@@ -79,8 +80,12 @@
 	if (coff->a.tsize != 0) {
 		if (flags & LOAD_TEXT) {
 			PROGRESS(("%lu", coff->a.tsize));
-			if (READ(fd, coff->a.text_start, coff->a.tsize) !=
-			    coff->a.tsize) {
+			nr = READ(fd, coff->a.text_start, coff->a.tsize);
+			if (nr == -1) {
+				return 1;
+			}
+			if (nr != coff->a.tsize) {
+				errno = ESHORT;
 				return 1;
 			}
 		}
@@ -104,8 +109,13 @@
 	if (coff->a.dsize != 0) {
 		if (flags & LOAD_DATA) {
 			PROGRESS(("+%lu", coff->a.dsize));
-			if (READ(fd, coff->a.data_start, coff->a.dsize) !=
-			    coff->a.dsize) {
+			nr = READ(fd, coff->a.data_start, coff->a.dsize);
+			if (nr == -1) {
+				WARN(("read data"));
+				return 1;
+			}
+			if (nr != coff->a.dsize) {
+				errno = ESHORT;
 				WARN(("read data"));
 				return 1;
 			}
Index: sys/lib/libsa/loadfile_elf32.c
===================================================================
RCS file: /cvsroot/src/sys/lib/libsa/loadfile_elf32.c,v
retrieving revision 1.17
diff -u -r1.17 loadfile_elf32.c
--- sys/lib/libsa/loadfile_elf32.c	5 Jun 2007 08:48:50 -0000	1.17
+++ sys/lib/libsa/loadfile_elf32.c	10 Nov 2007 12:49:50 -0000
@@ -276,6 +276,7 @@
 	int first;
 	paddr_t minp = ~0, maxp = 0, pos = 0;
 	paddr_t offset = marks[MARK_START], shpp, elfp = 0;
+	ssize_t nr;
 
 	/* some ports dont use the offset */
 	offset = offset;
@@ -289,7 +290,13 @@
 		WARN(("lseek phdr"));
 		goto freephdr;
 	}
-	if (read(fd, phdr, sz) != sz) {
+	nr = read(fd, phdr, sz);
+	if (nr == -1) {
+		WARN(("read program headers"));
+		goto freephdr;
+	}
+	if (nr != sz) {
+		errno = ESHORT;
 		WARN(("read program headers"));
 		goto freephdr;
 	}
@@ -329,8 +336,13 @@
 				WARN(("lseek text"));
 				goto freephdr;
 			}
-			if (READ(fd, phdr[i].p_vaddr, phdr[i].p_filesz) !=
-			    (ssize_t)phdr[i].p_filesz) {
+			nr = READ(fd, phdr[i].p_vaddr, phdr[i].p_filesz);
+			if (nr == -1) {
+				WARN(("read text error"));
+				goto freephdr;
+			}
+			if (nr != (ssize_t)phdr[i].p_filesz) {
+				errno = ESHORT;
 				WARN(("read text"));
 				goto freephdr;
 			}
@@ -380,7 +392,13 @@
 
 		shp = ALLOC(sz);
 
-		if (read(fd, shp, sz) != sz) {
+		nr = read(fd, shp, sz);
+		if (nr == -1) {
+			WARN(("read section headers"));
+			goto freeshp;
+		}
+		if (nr != sz) {
+			errno = ESHORT;
 			WARN(("read section headers"));
 			goto freeshp;
 		}
@@ -422,8 +440,13 @@
 						WARN(("lseek symbols"));
 						goto freeshp;
 					}
-					if (READ(fd, maxp, shp[i].sh_size) !=
-					    (ssize_t)shp[i].sh_size) {
+					nr = READ(fd, maxp, shp[i].sh_size);
+					if (nr == -1) {
+						WARN(("read symbols"));
+						goto freeshp;
+					}
+					if (nr != (ssize_t)shp[i].sh_size) {
+						errno = ESHORT;
 						WARN(("read symbols"));
 						goto freeshp;
 					}
Index: sys/lib/libsa/saerrno.h
===================================================================
RCS file: /cvsroot/src/sys/lib/libsa/saerrno.h,v
retrieving revision 1.9
diff -u -r1.9 saerrno.h
--- sys/lib/libsa/saerrno.h	11 Dec 2005 12:24:46 -0000	1.9
+++ sys/lib/libsa/saerrno.h	10 Nov 2007 12:49:50 -0000
@@ -48,4 +48,5 @@
 #define	EWCK	(ELAST+10)	/* write check error */
 #define	EECC	(ELAST+11)	/* uncorrectable ecc error */
 #define	EHER	(ELAST+12)	/* hard error */
-#define	ESALAST	(ELAST+12)	/* */
+#define	ESHORT	(ELAST+13)	/* short read */
+#define	ESALAST	(ELAST+13)	/* */