Skip to content

ql.os.stop() not work for Linux when multithread=True #884

@cq674350529

Description

@cq674350529

Describe the bug
When emulating a linux binary with multithread=True, calling ql.os.stop() to stop emulation didn't work as expected.

After a simple analysis, it seems that the self.threads of QlLinuxThreadManagement is always empty. No threads are added to it according to the code. As a result, when calling ql.os.stop(), no threads will be killed.

def stop(self):
self.ql.log.debug("[Thread Manager] Stop the world.")
self.ql.emu_stop()
for t in self.threads:
gevent.kill(t)

A possible fix this is to add self.cur_thread into self.threads, maybe in QlLinuxThreadManagement.run() method. Or there is a better place to do it?

By the way, ql.emu_stop() is used for this purpose when multithread=False, and ql.os.stop() is used when multithread=True. Of course, calling ql.os.stop() work well in both cases. To make it consistent, maybe it's better to move ql.os.stop() into ql.stop(). Then use ql.stop() in all cases.

Sample Code
Taken from the examples/hello_x8664_linux_part_debug.py, and make minor changes. In this case, the function dump() will be called multiple times.

def dump(ql, *args, **kw):
    ql.save(reg=False, cpu_context=True, snapshot="/tmp/snapshot.bin")
    ql.log.info("here")
    ql.os.stop()

if __name__ == "__main__":
    ql = Qiling(["rootfs/x8664_linux/bin/sleep_hello"], "rootfs/x8664_linux", verbose=QL_VERBOSE.DEFAULT, multithread=True)
    # load base address from profile file
    X64BASE = int(ql.profile.get("OS64", "load_address"), 16)
    # take a snapshot
    ql.hook_address(dump, X64BASE + 0x1094)
    ql.run()

Metadata

Metadata

Assignees

No one assigned

    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