Rumah >Tutorial sistem >LINUX >Pengesanan kernel Linux panggilan sistem Syscall

Pengesanan kernel Linux panggilan sistem Syscall

WBOY
WBOYke hadapan
2024-02-12 21:21:14433semak imbas

Dalam ruang pengguna Linux, kita selalunya perlu memanggil panggilan sistem. Mari kita ambil Linux versi 2.6.37 sebagai contoh untuk menjejaki pelaksanaan panggilan sistem baca. Pelaksanaan panggilan sistem mungkin berbeza antara versi Linux.

Pengesanan kernel Linux panggilan sistem Syscall

Dalam sesetengah aplikasi, kita boleh melihat definisi berikut:

scssCopy code
#define real_read(fd, buf, count ) (syscall(SYS_read, (fd), (buf), (count)))

Sebenarnya, yang sebenarnya dipanggil ialah fungsi sistem syscall(SYS_read), iaitu fungsi sys_read(). Dalam versi Linux 2.6.37, fungsi ini dilaksanakan melalui beberapa definisi makro.

Panggilan sistem Linux (SCI, antara muka panggilan sistem) sebenarnya adalah proses pengagregatan dan penguraian berbilang saluran Titik pengagregatan ialah titik masuk gangguan 0x80 (struktur sistem X86). Maksudnya, semua panggilan sistem diagregatkan dari ruang pengguna ke titik gangguan 0x80, dan nombor panggilan sistem tertentu disimpan pada masa yang sama. Apabila pengendali gangguan 0x80 sedang berjalan, panggilan sistem yang berbeza akan diproses secara berasingan mengikut nombor panggilan sistem, iaitu, fungsi kernel yang berbeza akan dipanggil untuk diproses.

Terdapat dua cara untuk menyebabkan panggilan sistem:

(1) int $0×80, ini adalah satu-satunya cara untuk menyebabkan panggilan sistem dalam versi kernel Linux lama.

(2) arahan pemasangan sysenter

Dalam kernel Linux, kita boleh menggunakan takrifan makro berikut untuk membuat panggilan sistem.

SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count)
{
    struct file *file;
    ssize_t ret = -EBADF;
    int fput_needed;

    file = fget_light(fd, &fput_needed);
    if (file) {
        loff_t pos = file_pos_read(file);
        ret = vfs_read(file, buf, count, &pos);
        file_pos_write(file, pos);
        fput_light(file, fput_needed);
    }

    return ret;
}

Takrifan makro SYSCALL_DEFINE3 adalah seperti berikut:

#define SYSCALL_DEFINE3(name, ...) SYSCALL_DEFINEx(3, _##name, __VA_ARGS__)

## bermaksud menggantikan terus aksara dalam makro,
Jika name = read, maka __NR_##name digantikan dengan __NR_read dalam makro. NR##nama ialah nombor panggilan sistem, ## merujuk kepada dua pengembangan makro. Iaitu, gantikan "nama" dengan nama panggilan sistem sebenar, dan kemudian kembangkan __NR.... Jika nama == ioctl, ia ialah __NR_ioctl.

#ifdef CONFIG_FTRACE_SYSCALLS
#define SYSCALL_DEFINEx(x, sname, ...)                \
    static const char *types_##sname[] = {            \
        __SC_STR_TDECL##x(__VA_ARGS__)            \
    };                            \
    static const char *args_##sname[] = {            \
        __SC_STR_ADECL##x(__VA_ARGS__)            \
    };                            \
    SYSCALL_METADATA(sname, x);                \
    __SYSCALL_DEFINEx(x, sname, __VA_ARGS__)
#else
#define SYSCALL_DEFINEx(x, sname, ...)                \
    __SYSCALL_DEFINEx(x, sname, __VA_ARGS__)
#endif

Tidak kira sama ada makro CONFIG_FTRACE_SYSCALLS ditakrifkan atau tidak, takrif makro berikut akhirnya akan dilaksanakan:

__SYSCALL_DEFINEx(x, sname, VA_ARGS)

#ifdef CONFIG_HAVE_SYSCALL_WRAPPERS

#define SYSCALL_DEFINE(name) static inline 
long SYSC_##name

#define __SYSCALL_DEFINEx(x, name, ...)                    \
    asmlinkage long sys##name(__SC_DECL##x(__VA_ARGS__));        \
    static inline long SYSC##name(__SC_DECL##x(__VA_ARGS__));    \
    asmlinkage long SyS##name(__SC_LONG##x(__VA_ARGS__))        \
    {                                \
        __SC_TEST##x(__VA_ARGS__);                \
        return (long) SYSC##name(__SC_CAST##x(__VA_ARGS__));    \
    }                                \
    SYSCALL_ALIAS(sys##name, SyS##name);                \
    static inline long SYSC##name(__SC_DECL##x(__VA_ARGS__))

#else /*
 CONFIG_HAVE_SYSCALL_WRAPPERS */

#define SYSCALL_DEFINE(name) asmlinkage 
long sys_##name
#define __SYSCALL_DEFINEx(x, name, ...)                    \
    asmlinkage long sys##name(__SC_DECL##x(__VA_ARGS__))

#endif /*
 CONFIG_HAVE_SYSCALL_WRAPPERS */

Jenis takrifan makro berikut akhirnya akan dipanggil:

asmlinkage sys panjang##nama(__SC_DECL##x(VA_ARGS))
Itulah fungsi sistem sys_read() yang kami nyatakan sebelum ini.
asmlinkage memberitahu pengkompil untuk mengekstrak hanya argumen fungsi dari timbunan. Semua panggilan sistem memerlukan kelayakan ini! Ini serupa dengan definisi makro yang disebutkan dalam artikel quagga kami sebelum ini.

Iaitu, kod berikut dalam definisi makro:

struct file *file;
    ssize_t ret = -EBADF;
    int fput_needed;

    file = fget_light(fd, &fput_needed);
    if (file) {
        loff_t pos = file_pos_read(file);
        ret = vfs_read(file, buf, count, &pos);
        file_pos_write(file, pos);
        fput_light(file, fput_needed);
    }

    return ret;

Analisis kod:

  • fget_light(): Menurut indeks yang ditentukan oleh fd, dapatkan semula objek fail yang sepadan daripada deskriptor proses semasa (lihat Rajah 3).
  • Jika objek fail yang ditentukan tidak ditemui, ralat dikembalikan
  • Jika objek fail yang ditentukan ditemui:
  • Panggil fungsi file_pos_read() untuk mendapatkan kedudukan semasa fail dibaca dan ditulis kali ini.
  • Panggil vfs_read() untuk melakukan operasi membaca fail, dan fungsi ini akhirnya memanggil fungsi yang ditunjuk oleh file->f_op.read() Kodnya adalah seperti berikut:

jika (fail->f_op->baca)
ret = fail->f_op->baca(fail, buf, kiraan, pos);

  • Panggil file_pos_write() untuk mengemas kini kedudukan baca dan tulis semasa fail.
  • Panggil fput_light() untuk mengemas kini kiraan rujukan fail.
  • Akhirnya, bilangan bait data yang dibaca dikembalikan.

Pada ketika ini, pemprosesan yang dilakukan oleh lapisan sistem fail maya selesai, dan kawalan diserahkan kepada lapisan sistem fail ext2.

Atas ialah kandungan terperinci Pengesanan kernel Linux panggilan sistem Syscall. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:lxlinux.net. Jika ada pelanggaran, sila hubungi admin@php.cn Padam