[Crash-utility] [PATCH] fix open fds display when process using large amount of file descriptors

Tan Hu tan.hu at zte.com.cn
Tue Jul 24 11:36:23 UTC 2018


Usually, structure fd_set only has 1024 bits size, when a process
using large amount of file descriptors that exceed the size of fd_set,
then the display of files and net sockets would mistake caused by the
out of bounds reading in loop.

Signed-off-by: Tan Hu <tan.hu at zte.com.cn>
---
 filesys.c | 24 ++++++++++++++++++------
 net.c     | 17 +++++++++++++----
 2 files changed, 31 insertions(+), 10 deletions(-)

diff --git a/filesys.c b/filesys.c
index 0ace8f4..47f5a24 100755
--- a/filesys.c
+++ b/filesys.c
@@ -2380,7 +2380,8 @@ open_files_dump(ulong task, int flags, struct reference *ref)
 	int max_fdset = 0;
 	int max_fds = 0;
 	ulong open_fds_addr;
-	fd_set open_fds;
+	int open_fds_size;
+	ulong *open_fds;
 	ulong fd;
 	ulong file;
 	ulong value;
@@ -2583,16 +2584,25 @@ open_files_dump(ulong task, int flags, struct reference *ref)
 		open_fds_addr = ULONG(files_struct_buf +
 			OFFSET(files_struct_open_fds));
 
+	open_fds_size = MAX(max_fdset, max_fds) / BITS_PER_BYTE;	
+	open_fds = (ulong *)GETBUF(open_fds_size);
+	if (!open_fds) {
+		if (fdtable_buf)
+			FREEBUF(fdtable_buf);
+		FREEBUF(files_struct_buf);
+		return;
+	}
+
 	if (open_fds_addr) {
 		if (VALID_MEMBER(files_struct_open_fds_init) && 
 		    (open_fds_addr == (files_struct_addr + 
 		    OFFSET(files_struct_open_fds_init)))) 
 			BCOPY(files_struct_buf + 
 			        OFFSET(files_struct_open_fds_init),
-				&open_fds, sizeof(fd_set));
+				open_fds, open_fds_size);
 		else
-			readmem(open_fds_addr, KVADDR, &open_fds,
-				sizeof(fd_set), "fdtable open_fds",
+			readmem(open_fds_addr, KVADDR, open_fds,
+				open_fds_size, "fdtable open_fds",
 				FAULT_ON_ERROR);
 	} 
 
@@ -2607,6 +2617,7 @@ open_files_dump(ulong task, int flags, struct reference *ref)
 		if (fdtable_buf)
 			FREEBUF(fdtable_buf);
 		FREEBUF(files_struct_buf);
+		FREEBUF(open_fds);
 		return;
 	}
 
@@ -2617,11 +2628,11 @@ open_files_dump(ulong task, int flags, struct reference *ref)
 	j = 0;
 	for (;;) {
 		unsigned long set;
-		i = j * __NFDBITS;
+		i = j * BITS_PER_LONG;
 		if (((max_fdset >= 0) && (i >= max_fdset)) || 
 		    (i >= max_fds))
 			 break;
-		set = open_fds.__fds_bits[j++];
+		set = open_fds[j++];
 		while (set) {
 			if (set & 1) {
         			readmem(fd + i*sizeof(struct file *), KVADDR, 
@@ -2665,6 +2676,7 @@ open_files_dump(ulong task, int flags, struct reference *ref)
 	if (fdtable_buf)
 		FREEBUF(fdtable_buf);
 	FREEBUF(files_struct_buf);
+	FREEBUF(open_fds);
 }
 
 /*
diff --git a/net.c b/net.c
index 4199091..f08f22a 100755
--- a/net.c
+++ b/net.c
@@ -1373,7 +1373,8 @@ dump_sockets_workhorse(ulong task, ulong flag, struct reference *ref)
 	int max_fdset = 0;
 	int max_fds = 0;
 	ulong open_fds_addr = 0;
-	fd_set open_fds;
+	ulong *open_fds;
+	int open_fds_size;
 	ulong fd;
 	ulong file;
 	int i, j;
@@ -1446,12 +1447,18 @@ dump_sockets_workhorse(ulong task, ulong flag, struct reference *ref)
             		sizeof(void *), "files_struct fd addr", FAULT_ON_ERROR);
 	}
 
+	open_fds_size = MAX(max_fdset, max_fds) / BITS_PER_BYTE;
+	open_fds = (ulong *)GETBUF(open_fds_size);
+	if (!open_fds)
+		return;
+
 	if (open_fds_addr) 
-		readmem(open_fds_addr, KVADDR, &open_fds, sizeof(fd_set),
+		readmem(open_fds_addr, KVADDR, open_fds, open_fds_size,
 	               	"files_struct open_fds", FAULT_ON_ERROR);
     	if (!open_fds_addr || !fd) { 
 		if (!NET_REFERENCE_CHECK(ref))
 			fprintf(fp, "No open sockets.\n");
+		FREEBUF(open_fds);
         	return;
 	}
 
@@ -1479,10 +1486,10 @@ dump_sockets_workhorse(ulong task, ulong flag, struct reference *ref)
     	j = 0;
     	for (;;) {
 	        unsigned long set;
-	        i = j * __NFDBITS;
+	        i = j * BITS_PER_LONG;
 	        if (((max_fdset >= 0) && (i >= max_fdset)) || (i >= max_fds))
 	            	break;
-	        set = open_fds.__fds_bits[j++];
+	        set = open_fds[j++];
 	        while (set) {
 	            	if (set & 1) {
 		                readmem(fd + i*sizeof(struct file *), KVADDR, 
@@ -1505,6 +1512,8 @@ dump_sockets_workhorse(ulong task, ulong flag, struct reference *ref)
 
 	if (NET_REFERENCE_FOUND(ref))
 		fprintf(fp, "\n");
+
+	FREEBUF(open_fds);
 }
 
 
-- 
1.8.3.1




More information about the Crash-utility mailing list