0

I want to write short Arm Linux assembly code that terminate the thread that call it.

I can't call to function (3) only syscall

I think to get my tid with gettid(2) and then send tkill(2) to this tid?

mov     %r7, $0xe0   /* gettid is syscall #0xe0 */
swi     $0          /* invoke syscall */
/*r0 contains current tid*/

mov     %r1, $9 /* SIGKILL signal */
mov     %r7, $0xee   /* tkill is syscall #0xee */
swi     $0          /* invoke syscall */

Does the code above work? What is the easy and short way?

Frant
  • 5,382
  • 1
  • 16
  • 22
yfr24493AzzrggAcom
  • 159
  • 1
  • 2
  • 13

1 Answers1

1

Testing a C version first with symbols rather than hard-coded values using musl-libc - you can retrieve syscall.h.in and syscall_arch.h form its git repository.

pthread_exit.c - calling _gettid system call:

#include <stdio.h>
#include <signal.h>

#include "syscall.h.in"
#include "syscall_arch.h"

int main(int argc, char** argv) {
  long pid =  __syscall0(__NR_gettid); 
  printf("pid: %ld\n", pid);
//__syscall2(__NR_tkill, pid, SIGKILL); 
  printf("Kilroy should not be here.\n");
}

gcc -o pthread_exit pthread_exit.c

./pthread_exit
pid: 14494
Kilroy should not be here.
./pthread_exit
pid: 14495
Kilroy should not be here.
./pthread_exit
pid: 14496
Kilroy should not be here.

pthread_exit.c - calling _gettid and tkill system calls:

#include <stdio.h>
#include <signal.h>

#include "syscall.h.in"
#include "syscall_arch.h"

int main(int argc, char** argv) {
  long pid =  __syscall0(__NR_gettid); 
  printf("pid: %ld\n", pid);
  __syscall2(__NR_tkill, pid, SIGKILL); 
  printf("Kilroy should not be here.\n");
}

gcc -o pthread_exit pthread_exit.c
./pthread_exit
pid: 14513
Killed
./pthread_exit
pid: 14514
Killed
./pthread_exit
pid: 14515
Killed

Looking at syscall_arch.h:

static inline long __syscall0(long n)
{
    register long r7 __ASM____R7__ = n;
    register long r0 __asm__("r0");
    __asm_syscall(R7_OPERAND);
}

static inline long __syscall2(long n, long a, long b)
{
    register long r7 __ASM____R7__ = n;
    register long r0 __asm__("r0") = a;
    register long r1 __asm__("r1") = b;
    __asm_syscall(R7_OPERAND, "0"(r0), "r"(r1));
}

As you had figured out, the number for the desired system call should reside in r7, and parameters are in r0 to r5 - we just need r0 and r1 here.

So, yes, it works: pthread_exit.s:

        .syntax unified
        .arch armv7-a
        .fpu vfpv3-d16
        .text
        .align  2
        .global main
        .thumb
        .thumb_func
        .type   main, %function
main:
        mov     %r7, $0xe0   /* gettid is syscall #0xe0 */
        swi     $0          /* invoke syscall */
        /*r0 contains current tid*/
        mov     %r1, $9 /* SIGKILL signal */
        mov     %r7, $0xee   /* tkill is syscall #0xee */
        swi     $0          /* invoke syscall */
       .end

Using qemu-user:

qemu-arm pthread_exit
Killed

On a Cortex-A7 system:

 ./pthread_exit
Killed

Not sure this is the correct way to go though - see this discussion.

Frant
  • 5,382
  • 1
  • 16
  • 22
  • [Syscall implementation of exit()](https://stackoverflow.com/q/46903180) that you linked is about making the current thread (or all threads) exit, not *just* another thread but not the current. I would have assumed that `tgkill` is the right way to forcibly terminate another thread, although normally you'd have your other threads run code that chooses to exit after seeing some value in shared variables. – Peter Cordes Dec 18 '20 at 18:22
  • I see, thanks for this precision.in another vein, I would probably rather use `tgkill`, which obsoleted `tkill`. – Frant Dec 18 '20 at 19:24
  • @Frant, can you please explain more? If I want that my thread will suicide ,so `gettid` and `tkill` is the right way,but of I want to kill another thread `tkill` is not the right way? Why is that? – yfr24493AzzrggAcom Dec 19 '20 at 16:08
  • @yfr24493AzzrggAcom: This is not what I meant, I was just wondering if there was a less brutal way of doing it. It should work I guess on another thread as well. – Frant Dec 20 '20 at 00:32
  • @Frant, the problem is that `tkill` kill all the process.not only the current thread, do you have another idea? – yfr24493AzzrggAcom Dec 20 '20 at 22:06
  • I understood your question as: "does my assembly program work the same way the equivalent C program would", and answered yes. If that was not the question you intended to ask, just tell me, I will remove my answer it since it will be irrelevant. You may want to rephrase your question in this case though. And yes, it seems `tkill() ` does kill both the child thread and the main thread. A look at the source code for the `pthread` library would likely provide some insights. – Frant Dec 21 '20 at 13:13