Вопрос о написании моего системного вызова во FreeBSD - PullRequest
4 голосов
/ 01 июля 2011

ОК, поэтому я только что закончил читать реализацию kill (2) во FreeBSD и пытаюсь написать свое собственное "kill". Этот системный вызов принимает uid и signum и отправляет сигнал процессам, принадлежащим uid, за исключением вызывающего процесса.

Как я могу передать uid системному вызову? В kill (2) pid находится в аргументе struct kill_args. Есть ли структура, которая содержит uid так, как struct kill_args содержит pid? Если нет, могу ли я определить структуру вне ядра?

1 Ответ

8 голосов
/ 01 июля 2011

Это просто, но довольно сложный процесс.Вот модуль, который устанавливает системный вызов.

Включает кучу вещей

#include <sys/types.h>
#include <sys/param.h>
#include <sys/proc.h>
#include <sys/module.h>
#include <sys/sysent.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/sysproto.h>

Определите структуру для хранения аргументов

struct mykill_args {
    int pid;
    int signo;
};

Определите функцию обработки

static int
mykill(struct thread *td, void *args)
{
    struct mykill_args *uap = args;

    uprintf("mykill called. pid=%d, signo=%d\n", uap->pid, uap->signo);

    return 0;
}

Вам нужен объект sysent

static struct sysent mykill_sysent = {
    2,          /* number of arguments */
    mykill      /* function handling system call */
};

И смещение, при котором будет установлен системный вызов.

/* Choose "the next" value later. */
static int offset = NO_SYSCALL;

load function

static int
load(struct module *module, int cmd, void *arg)
{
    int error = 0;

    switch (cmd) {
        case MOD_LOAD:
            uprintf("Loading module. Installing syscall at"
                " offset %d\n", offset);
            break;
        case MOD_UNLOAD:
            uprintf("Unloading module. syscall uninstalled from"
                " offset %d\n", offset);
            break;
        default:
            error = EOPNOTSUPP;
            break;
    }

    return error;
}

Установка системного вызова

SYSCALL_MODULE(mykill, &offset, &mykill_sysent, load, NULL);

Вы можете запустить системный вызов, используя syscall(2).Или используя perl :)).Вот пример

[root@aiur /home/cnicutar/kld-syscall]# kldload ./mykill.ko
Loading module. Installing syscall at offset 210

[cnicutar@aiur ~/kld-syscall]$ perl -e 'syscall(210, 30, 15);'
mykill called. pid=30, signo=15
...