Skip to content

getpriority(PRIO_PROCESS, tid) returns ESRCH for live guest threads #231

Description

@doanbaotrung

getpriority(PRIO_PROCESS, tid) returns ESRCH for live guest threads

Description

A multithreaded guest program can abort when it calls
getpriority(PRIO_PROCESS, tid) for a live guest thread id.

On Linux, PRIO_PROCESS accepts a process id, and Linux thread ids are valid
targets because threads are represented as tasks. If tid refers to a live
thread in the same process, getpriority(PRIO_PROCESS, tid) should return that
task's nice value.

In elfuse, getpriority currently appears to accept only who == 0 or
who == guest_pid. When a guest runtime calls getpriority(PRIO_PROCESS, 2)
for a live guest thread, elfuse returns -ESRCH.

Observed Behavior

Verbose elfuse log:

syscall 141 ... (0x0, 0x2, ...)
  -> -3

On AArch64:

syscall 141 = getpriority
x0 = 0 = PRIO_PROCESS
x1 = 2 = target guest tid
return -3 = -ESRCH

The guest then aborts because getpriority unexpectedly failed with
ESRCH:

Check failed: niceness != -1 || errno == 0  No such process

Expected Behavior

If who names a live guest thread, elfuse should treat it as a valid
PRIO_PROCESS target and return the emulated nice value.

For example:

getpriority(PRIO_PROCESS, 0)          -> current nice value
getpriority(PRIO_PROCESS, guest_pid)  -> current nice value
getpriority(PRIO_PROCESS, live_tid)   -> current nice value
getpriority(PRIO_PROCESS, dead_tid)   -> -ESRCH

setpriority(PRIO_PROCESS, tid, prio) should likely follow the same target
validation rules.

Suspected Root Cause

proc_sys_getpriority() only accepts self or the process id:

if (who != 0 && who != (int) guest_pid)
    return -LINUX_ESRCH;

This rejects valid guest thread ids even though elfuse tracks them in the thread
table.

Suggested Fix

For PRIO_PROCESS, accept:

  • who == 0
  • who == guest_pid
  • thread_tid_alive(who)

Then return 20 - emu_nice.

Apply equivalent target validation to proc_sys_setpriority().

Test Suggestion

Add a regression test that creates a guest thread and calls:

getpriority(PRIO_PROCESS, child_tid)

Expected result should be the current nice value, not -ESRCH.

Also test:

setpriority(PRIO_PROCESS, child_tid, 5);
getpriority(PRIO_PROCESS, child_tid);

Expected result should reflect the emulated nice value.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions