[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Bug in FTP/FTPD [PATCH supplied]
Hi!
I found that both ftp and ftpd in kth-krb4 had a problem when
transferring a large file (larger than 0x1000000 bytes on my FreeBSD
system. The size of the file was truncated to a 32 bit quantity.
It turned out that it tried to mmap the file but the mmap only takes a
32 bit argument as the size but the file was larger than that. The
attaced patches correct this and if the file is larger than 0xffffffff
bytes the ordinary read/write loop is used.
I believe it is the same ftp/ftpd program in Heimdal and KTH-KRB
therefore cc: to heimdal list.
/thn
--
---------------------------------------------------------------
Svensk Aktuell Elektronik AB Thomas Nyström
Box 10 Phone: +46 8 35 92 85
S-191 21 Sollentuna Fax: +46 8 59 47 45 36
Sweden Email: thn@saeab.se
---------------------------------------------------------------
--- org/ftpd/ftpd.c Thu Sep 13 11:17:14 2001
+++ ftpd/ftpd.c Thu Oct 3 10:12:41 2002
@@ -1399,8 +1399,13 @@
char *chunk;
int in = fileno(instr);
if(fstat(in, &st) == 0 && S_ISREG(st.st_mode)
- && st.st_size > 0) {
+ && st.st_size > 0 && st.st_size <= 0xffffffffL) {
/*
+ * On some systems st.st_size is 64 bits and mmap size
+ * (second argument is 32 bits. If a large file is to
+ * be transmitted the size of the file would be truncated.
+ * Use ordinary read/write for such a file.
+ *
* mmap zero bytes has potential of loosing, don't do it.
*/
chunk = mmap(0, st.st_size, PROT_READ,
--- org/ftp/ftp.c Fri Sep 7 22:28:10 2001
+++ ftp/ftp.c Thu Oct 3 11:51:45 2002
@@ -575,15 +575,23 @@
*/
if (st.st_size == 0)
return 0;
- chunk = mmap (0, st.st_size, PROT_READ, MAP_SHARED, fileno (from), 0);
- if (chunk != (void *) MAP_FAILED) {
- int res;
+ /*
+ * On some systems st.st_size is 64 bits and mmap size (second
+ * argument) is 32 bits. If a large file is to be transmitted
+ * the size of the file would be truncated.
+ * Use ordinary read/write for such a file.
+ */
+ if (st.st_size <= 0xffffffffL) {
+ chunk = mmap (0, st.st_size, PROT_READ, MAP_SHARED, fileno (from), 0);
+ if (chunk != (void *) MAP_FAILED) {
+ int res;
- res = sec_write (fileno (to), chunk, st.st_size);
- if (munmap (chunk, st.st_size) < 0)
- warn ("munmap");
- sec_fflush (to);
- return res;
+ res = sec_write (fileno (to), chunk, st.st_size);
+ if (munmap (chunk, st.st_size) < 0)
+ warn ("munmap");
+ sec_fflush (to);
+ return res;
+ }
}
}
#endif