mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
systrap: don't restart the task after replacing a syscall with a function call
PiperOrigin-RevId: 627556852
This commit is contained in:
@@ -186,10 +186,7 @@ restart:
|
||||
return nil, hostarch.NoAccess, err
|
||||
}
|
||||
if needPatch {
|
||||
restart, _ := s.usertrap.PatchSyscall(ctx, ac, mm)
|
||||
if restart {
|
||||
goto restart
|
||||
}
|
||||
s.usertrap.PatchSyscall(ctx, ac, mm)
|
||||
}
|
||||
if !isSyscall && linux.Signal(c.signalInfo.Signo) == linux.SIGILL {
|
||||
err := s.usertrap.HandleFault(ctx, ac, mm)
|
||||
|
||||
@@ -187,12 +187,10 @@ func loadUsertrap(ctx context.Context, mm memoryManager, addr hostarch.Addr) err
|
||||
}
|
||||
|
||||
// PatchSyscall changes the syscall instruction into a function call.
|
||||
//
|
||||
// Returns true if the thread has to be restarted.
|
||||
func (s *State) PatchSyscall(ctx context.Context, ac *arch.Context64, mm memoryManager) (bool, error) {
|
||||
func (s *State) PatchSyscall(ctx context.Context, ac *arch.Context64, mm memoryManager) error {
|
||||
task := kernel.TaskFromContext(ctx)
|
||||
if task == nil {
|
||||
return false, fmt.Errorf("no task found")
|
||||
return fmt.Errorf("no task found")
|
||||
}
|
||||
|
||||
s.mu.Lock()
|
||||
@@ -203,7 +201,7 @@ func (s *State) PatchSyscall(ctx context.Context, ac *arch.Context64, mm memoryM
|
||||
|
||||
prevCode := make([]uint8, len(jmpInst))
|
||||
if _, err := primitive.CopyUint8SliceIn(task.OwnCopyContext(usermem.IOOpts{AddressSpaceActive: false}), hostarch.Addr(patchAddr), prevCode); err != nil {
|
||||
return false, err
|
||||
return err
|
||||
}
|
||||
|
||||
// Check that another thread has not patched this syscall yet.
|
||||
@@ -214,7 +212,7 @@ func (s *State) PatchSyscall(ctx context.Context, ac *arch.Context64, mm memoryM
|
||||
trapAddr, err := s.addTrapLocked(ctx, ac, mm, uint32(sysno))
|
||||
if trapAddr == 0 || err != nil {
|
||||
ctx.Warningf("Failed to add a new trap: %v", err)
|
||||
return false, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// Replace "mov sysno, %eax; syscall" with "jmp trapAddr".
|
||||
@@ -258,24 +256,22 @@ func (s *State) PatchSyscall(ctx context.Context, ac *arch.Context64, mm memoryM
|
||||
// the invalid instruction and restart a patched code.
|
||||
faultInstB := primitive.ByteSlice(faultInst[:])
|
||||
if _, err := faultInstB.CopyOut(ignorePermContext, hostarch.Addr(patchAddr+faultInstOffset)); err != nil {
|
||||
return false, err
|
||||
return err
|
||||
}
|
||||
// The second step is to replace all bytes except the first one
|
||||
// which is the opcode of the mov instruction, so that the first
|
||||
// five bytes remain "mov XXX, %rax".
|
||||
if _, err := primitive.CopyUint8SliceOut(ignorePermContext, hostarch.Addr(patchAddr+1), newCode[1:]); err != nil {
|
||||
return false, err
|
||||
return err
|
||||
}
|
||||
// The final step is to replace the first byte of the patch.
|
||||
// After this point, all threads will read the valid jmp
|
||||
// instruction.
|
||||
if _, err := primitive.CopyUint8SliceOut(ignorePermContext, hostarch.Addr(patchAddr), newCode[0:1]); err != nil {
|
||||
return false, err
|
||||
return err
|
||||
}
|
||||
}
|
||||
ac.RestartSyscall()
|
||||
ac.SetIP(patchAddr)
|
||||
return true, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// HandleFault handles a fault on a patched syscall instruction.
|
||||
|
||||
Reference in New Issue
Block a user