#50 [m_sunos5.c] need to check for error return from 2nd pread

v3.8beta
open
nobody
5
2010-05-18
2010-05-18
Mike Chang
No

Regarding file macine/m_sunos5.c in 3.8beta1: Inside the routine getptable(), pread() is called twice. The first pread() checks for error returns; the second one does not. It looks like if you have a process that terminates after the fstat on line 2060 completes, the second pread() at line 2067 is called and fails. In this case, top will happily use the uninitialized memory that's alloc'd at line 2066 as if pread() populated it.

here's what truss reported right when this occurs
21448: pread(4024, "\0\0\0\0\0\0\0\v\0\0\0\0".., 1600, 0) = 1600
21448: pread(4025, "02\0\0\0\0\0\001\0\01ED4".., 416, 0) = 416
21448: fstat(4026, 0xFFFFFFFF7FFFF030) = 0
21448: pread(4026, "\0\0\0\0\0\0\001\0\0\0\0".., 160, 0) = 160
21448: pread(4027, "02\0\0\0\0\0\001\0\0 EFD".., 416, 0) = 416
21448: fstat(4028, 0xFFFFFFFF7FFFF030) = 0
21448: pread(4028, 0x100120ED0, 16, 0) Err#2 ENOENT
<hang>

modifying m_sunos5.c to check for pread() for error and proceeding to the next loop iteration fixes things for me.

Discussion

  • alfred heisner
    alfred heisner
    2013-04-17

    I was experiencing hangs from top on Solaris due to the use of uninitialized memory in the proceeding for loop after that second pread. I used following patch (implements Mike's suggestion), seems to fix things for me too.

    *** top-3.8beta1.a/machine/m_sunos5.c Tue May 6 22:41:38 2008
    --- top-3.8beta1.b/machine/m_sunos5.c Wed Apr 17 16:47:20 2013
    ***************
    *** 2062,2073 ****
    char *p;
    int i;

    /* read the whole file */
    p = malloc(st.st_size);
    ! (void)pread(fd, p, st.st_size, 0);

    /* cache the file descriptor if we can */
    if (fd < maxfiles)
    {
    op->fd_lpsinfo = fd;
    }
    --- 2062,2079 ----
    char *p;
    int i;

    /* read the whole file */
    p = malloc(st.st_size);
    ! if (pread(fd, p, st.st_size, 0) < 0)
    ! {
    ! (void) close (fd);
    ! op->fd_lpsinfo = -1;
    ! continue;
    ! }

    +
    /* cache the file descriptor if we can */
    if (fd < maxfiles)
    {
    op->fd_lpsinfo = fd;
    }