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

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions