Неравномерное поведение в разных системных вызовах - PullRequest
0 голосов
/ 30 сентября 2018

Я работаю над проектом, в котором я перехватил вызов системы open.Когда пользователь пытается открыть файл, я хочу, чтобы sys_open заблокировал действие, если текущая задача (pid или tgid, которые в «черном списке») могут вытечь файл из хоста.

В любом случае,Сам перехват работал нормально на sys_read и sys_write (у меня есть несколько printk внутри фальшивой функции в качестве индикатора).

но, когда япопробуйте подключить функцию sys_open, ничего не распечатывается - означает, что переопределение не удалось.Я распечатал адрес вызова sys до и после переопределения, так что это может не быть проблемой.

Я не совсем понимаю, что может вызвать такое неравномерное поведение при подключении различных функций.

будьте рады некоторому вкладу здесь.спасибо!

примеры вывода dmesg:

при подключенной записи -

...

[2989.500485] в моей записи ...

[2989.500585] в моем письме ...

при открытом подключении, с пометкой напечатано, но здесь какой-то "отладочный" вывод -

[890.709696]найден адрес 00000000103d42f6

[890.709697] Адрес до - 0000000006d29c3a

[890.709698] Адрес после - 00000000a5117c6a

[948.533339] BYE ​​!!!

используя lubuntu vm (ядро v 4.15.0.20).

вот исходный код:

#include <linux/init.h>             // Macros used to mark up functions e.g., __init __exit
#include <linux/module.h>           
#include <linux/kernel.h>           
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/syscalls.h>
#include <linux/sched.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
#include <asm/page.h>
#include <linux/kallsyms.h>
#include <linux/semaphore.h>
#include <asm/cacheflush.h>
#include <linux/set_memory.h>
#include <linux/cred.h>
#include <linux/user.h>


MODULE_LICENSE("GPL");                                     
MODULE_AUTHOR("ABC"); 
MODULE_VERSION("0.1");



asmlinkage long (*original_call)( char __user *filename, int flags, umode_t mode);    // for read or  write:  (unsigned int fd, char __user *buf, size_t count);
asmlinkage long my_sys_READ(unsigned int fd, char __user *buf, size_t count);
asmlinkage long my_sys_WRITE(unsigned int fd, char __user *buf, size_t count);
asmlinkage long my_sys_OPEN( char __user *filename, int flags, umode_t mode);

unsigned long* find_sys_call_table(void);
void set_page_rw( unsigned long addr);
void set_page_ro( unsigned long addr);
const struct cred *_cred = NULL ; 
struct user_struct *user =NULL ;
unsigned long* sys_call_table = NULL;


void set_page_rw(unsigned long addr)
{

    unsigned int level;
    pte_t *pte = lookup_address(addr, &level);
    if (pte->pte &~ _PAGE_RW) pte->pte |= _PAGE_RW;
}

void set_page_ro( unsigned long addr)
{

    unsigned int level;
    pte_t *pte = lookup_address(addr, &level);
    pte->pte = pte->pte &~_PAGE_RW;
}

/*
asmlinkage long my_sys_READ(unsigned int fd, char __user *buf, size_t count)
{
    //_cred = current_cred();
    user =  get_current_user();
    if( (int)(*user).uid.val == uid )
    {
        printk(KERN_ALERT"in my read ... hacked !");    
        return original_call(fd,  buf, count);
    }
    printk(KERN_ALERT"in my read ... hacked !");
    return original_call(fd,  buf, count);
}


asmlinkage long my_sys_WRITE(unsigned int fd, char __user *buf, size_t count)
{
    //_cred = current_cred();
    user =  get_current_user();
    if( (int)(*user).uid.val == uid )
    {
        printk(KERN_ALERT"in my write ... hacked !");   
        return original_call(fd,  buf, count);
    }
    printk(KERN_ALERT"in my write ... hacked !");
    return original_call(fd,  buf, count);
}
*/

asmlinkage long my_sys_OPEN( char __user *filename, int flags, umode_t mode)
{

    printk(KERN_ALERT"in my open ... hacked !");
    return original_call(filename, flags, mode);

}

unsigned long* find_sys_call_table(void)  
{
    return   (unsigned long *)kallsyms_lookup_name("sys_call_table");

}


int init_module()
{

    printk(KERN_ALERT "I'm dangerous. I hope you did a ");
    printk(KERN_ALERT "sync before you insmod'ed me.\n");

    sys_call_table = find_sys_call_table();
    printk(KERN_INFO"address found %p \n",sys_call_table);
    original_call = (void *)sys_call_table[__NR_open];
    set_page_rw((unsigned long)sys_call_table);

    printk(KERN_INFO"  Address before -  %p", (void *)sys_call_table[__NR_open]);
    sys_call_table[__NR_open] = (unsigned long)my_sys_OPEN;
    printk(KERN_INFO"  Address after -  %p", (void *)sys_call_table[__NR_open]);
    return 0;
}
/*
* Cleanup − unregister the appropriate file from /proc
*/
void cleanup_module()
{
    /*
    * Return the system call back to normal

    */

    if (sys_call_table[__NR_open] != (unsigned long)my_sys_OPEN) {
        printk(KERN_ALERT "Somebody else also played with the ");
        printk(KERN_ALERT "open system call\n");

    }
    printk(KERN_ALERT "BYE !!!\n");

    sys_call_table[__NR_open] = (unsigned long)original_call;
}

1 Ответ

0 голосов
/ 01 октября 2018

Ваша версия Ubuntu основана на glibc 2.27.

версия glibc 2.26 переключена на реализацию open с openat:

commit b41152d716ee9c5ba34495a54e64ea2b732139b5
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date:   Fri Nov 11 15:00:03 2016 -0200

    Consolidate Linux open implementation

    This patch consolidates the open Linux syscall implementation on
    sysdeps/unix/sysv/linux/open{64}.c.  The changes are:

      1. Remove open{64} from auto-generation syscalls.list.
      2. Add a new open{64}.c implementation.  For architectures that
         define __OFF_T_MATCHES_OFF64_T the default open64 will create
         alias to required open symbols.
      3. Use __NR_openat as default syscall for open{64}.

У вас будетв результате подключить openat в дополнение к open.

Обратите внимание, что ядро ​​Linux предоставляет соответствующий интерфейс для этого в виде fanotify interface .Если вы используете это, вам не придется беспокоиться о таких деталях.

...