Skip to content

ql_syscall_getdents64 系统调用问题 #773

@3vi1d0g

Description

@3vi1d0g

ql_syscall_getdents 使用的是 linux_dirent结构

struct linux_dirent {
   long           d_ino;
   off_t          d_off;
   unsigned short d_reclen;
   char           d_name[];
   /*
    char           pad;       // Zero padding byte
    char           d_type;    // File type (only since Linux 2.6.4;
                              // offset is (d_reclen - 1))
    */
};

但是 ql_syscall_getdents64 使用的是 linux_dirent64 结构体

struct linux_dirent64 {
	u64		d_ino;
	s64		d_off;
	unsigned short	d_reclen;
	unsigned char	d_type;
	char		d_name[0];
};

所以系统ql_syscall_getdents64 需要将原来的 name 和 type 换位置

def ql_syscall_getdents64(ql, fd, dirp, count, *args, **kw):
    def _type_mapping(ent):
        methods_constants_d = {'is_fifo': 0x1, 'is_char_device': 0x2, 'is_dir': 0x4, 'is_block_device': 0x6,
                                'is_file': 0x8, 'is_symlink': 0xa, 'is_socket': 0xc}
        ent_p = pathlib.Path(ent.path) if isinstance(ent, os.DirEntry) else ent

        for method, constant in methods_constants_d.items():
            if getattr(ent_p, method, None)():
                t = constant
                break
        else:
            t = 0x0 # DT_UNKNOWN

        return bytes([t])

    if ql.os.fd[fd].tell() == 0:
        n = ql.archbit // 8
        total_size = 0
        results = os.scandir(ql.os.fd[fd].name)
        _ent_count = 0

        for result in itertools.chain((pathlib.Path('.'), pathlib.Path('..')), results): # chain speical directories with the results
            d_ino = result.inode() if isinstance(result, os.DirEntry) else result.stat().st_ino
            d_off = 0x0
            d_name = (result.name if isinstance(result, os.DirEntry) else result._str).encode() + b'\x00'
            d_type = _type_mapping(result)
            d_reclen = len(d_name) + n*2 + 3
            #print (d_name)
            ql.mem.write(dirp, ql.pack(d_ino))
            ql.mem.write(dirp+n, ql.pack(d_off))
            ql.mem.write(dirp+n*2, ql.pack16(d_reclen))
            ql.mem.write(dirp+n*2+2, d_type)
            ql.mem.write(dirp+n*2+2+1, d_name)

            dirp += d_reclen
            total_size += d_reclen
            _ent_count += 1

        regreturn = total_size
        ql.os.fd[fd].lseek(0, os.SEEK_END) # mark as end of file for dir_fd
    else:
        _ent_count = 0
        regreturn = 0

    ql.log.debug("getdents(%d, /* %d entries */, 0x%x) = %d" % (fd, _ent_count, count, regreturn))
    return regreturn

测试结果
修复前:
image

修复后:
image

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions