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...@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

--
Crash-utility mailing list
Crash-utility@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility

Reply via email to