NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

bin/38891: ktruss shows wrong data for lstat()



>Number:         38891
>Category:       bin
>Synopsis:       ktruss shows wrong data for lstat()
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    bin-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sun Jun 08 15:05:00 +0000 2008
>Originator:     Michael van Elst
>Release:        NetBSD 4.99.64
>Organization:
        
>Environment:
        
        
System: NetBSD volans 4.99.64 NetBSD 4.99.64 (VOLANS) #17: Sun Jun 8 09:19:11 
CEST 2008 spz@volans:/home/netbsd/src/sys/arch/i386/compile/obj/VOLANS i386
Architecture: i386
Machine: i386
>Description:
When tracing the savecore program ktruss showed bad parameters
for the lstat() system call. Using ktrace/kdump is fine.

Here is an example program excercising the problem:

#include <dirent.h>
#include <errno.h>
#include <paths.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <util.h>
#include <syslog.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>

char *          
find_dev(dev_t dev, int type)
{       
        DIR *dfd;
        struct dirent *dir;
        struct stat sb;
        char *dp, device[MAXPATHLEN + 1], *p;
        size_t l;
                
        if ((dfd = opendir(_PATH_DEV)) == NULL) {
                syslog(LOG_ERR, "%s: %m", _PATH_DEV);
                exit(1);
        }
        strlcpy(device, _PATH_DEV, sizeof(device));
        p = &device[strlen(device)];
        l = sizeof(device) - strlen(device);
        while ((dir = readdir(dfd))) { 
                strlcpy(p, dir->d_name, l);
                printf("%s %s\n",device,p);
                fflush(stdout);
                if (lstat(device, &sb)) {
                        syslog(LOG_ERR, "%s: %m", device);
                        continue;
                }           
                printf("%s %s %o %d\n",device,p,sb.st_mode,sb.st_rdev);
                fflush(stdout);
                if ((sb.st_mode & S_IFMT) != type)
                        continue;
                if (dev == sb.st_rdev) {
                        closedir(dfd);
                        if ((dp = strdup(device)) == NULL) {
                                syslog(LOG_ERR, "%m"); 
                                exit(1);
                        }
                        return (dp);
                }
        }       
        closedir(dfd);  
        syslog(LOG_ERR, "can't find device %d/%d", major(dev), minor(dev));
        exit(1);
}        

main()
{
        find_dev(0, S_IFCHR);
}

This is what ktruss shows (stripped to relevant part):

 17941      1 a.out    write(0x1, 0xbb904000, 0x15) = 21
       "/dev/console console\n"
 17941      1 a.out    __lstat30("/dev/..", 0xbfbfe80c) = 0
 17941      1 a.out    write(0x1, 0xbb904000, 0x1d) = 29
       "/dev/console console 20622 0\n"

This is what kdump shows:

 13619      1 a.out    CALL  write(1,0xbb904000,0x15)
 13619      1 a.out    GIO   fd 1 wrote 21 bytes
       "/dev/console console\n"
 13619      1 a.out    RET   write 21/0x15
 13619      1 a.out    CALL  __lstat30(0xbfbfe40b,0xbfbfe80c)
 13619      1 a.out    NAMI  "/dev/console"
 13619      1 a.out    RET   __lstat30 0
 13619      1 a.out    CALL  write(1,0xbb904000,0x1d)
 13619      1 a.out    GIO   fd 1 wrote 29 bytes
       "/dev/console console 20622 0\n"
 13619      1 a.out    RET   write 29/0x1d
 13619      1 a.out    CALL  close(3)
 13619      1 a.out    RET   close 0
 13619      1 a.out    CALL  exit(0xbb901040)

The "/dev/.." is the path used by the previous __lstat30() call.

I can repeat this on -current/i386 and -current/amd64.

netbsd-4 is fine.

>How-To-Repeat:
Trace lstat() call.

>Fix:
        

>Unformatted:
        
        


Home | Main Index | Thread Index | Old Index