Перевод документации по модулю REG

Rule Set Based Access Control (RSBAC) для Linux. Переводы документации, описаний и статьи по данной теме.

[ALT Linux Team]

Перевод: Александр Блохин  ]

Регистрация Модулей (REG)

Основы

REG - это не модуль принятия решения. Это - интерфейс для регистрации вашего собственного модуля решения, который может быть, но не обязательно, реализован как модуль ядра Linux. Он допускает регистрацию для всех подходящих запросов к коду решения также как для запросов обслуживания к данным структуирующим выполнение. Начиная с версии 1.1.1-pre4 он также допускает регистрацию системных вызовов в syscall-диспетчере REG.

В rsbac/adf/reg/adf_sample*.c вы можете найти пример модулей ядра. Если вы выберете в конфигурации ядра 'Compile REG samples', то примеры будут скомпилированы и установлены как и все прочие модули.

Если Вы предпочитаете отдельную компиляцию модулей, то в пакете rsbac-admin есть примеры таких модулей с действующим Makefile и (с версии 1.1.1-pre4) демонстрационным инструментарием syscall-диспетчера.

Пожалуйста, обратите внимание, что этот текст ориентирован на RSBAC начиная с версии 1.1.1-pre4, из-за добавленных функциональных возможностей и (я надеюсь) более легкого использования.

Регистрация Модуля

Вся рпоцедура регистрации модуля решения осуществляется с использованием идентификаторов rsbac_reg_handle_t, которые являются 32-битным числом. Как правило положительные значения используются как реальные значения и отрицательные для ошибок.

Типы данных и определения функций REG могут быть найдены в include/rsbac/reg.h, все остальное находятся в include/rsbac/types.h. Эти файлы заголовков должны быть всегда включены в вашу реализацию модели.

Полный список запросов RSBAC с возможными целями находится в targetsrequests.htm.

Callback-функции

Вы можете регистрировать следующие функции:

  • Функция решения, вызываемая перед предоставлением доступа. Возвращаемым значением является одно из NOT_GRANTED, GRANTED, DO_NOT_CARE или UNDEFINED, как определено в include/rsbac/types.h.

int rsbac_reg_request_func_t 
   ( enum rsbac_adf_request_t request, 
                rsbac_pid_t caller_pid, 
      enum rsbac_target_t target, 
      union rsbac_target_id_t tid, 
      enum rsbac_attribute_t attr, 
      union rsbac_attribute_value_t attr_val, 
      rsbac_uid_t owner); /* process owner */
   

  • Функция уведомления, вызываемая из большинства системных запросов как уведомление для обновления данных после выполнения функциональных возможностей системного вызова. Параметры теже-самые, как было указано выше, за исключением new_target и new_tid, где определяются допустимые новые объекты. (например новый файл в CREATE).

int rsbac_reg_set_attr_func_t 
   ( enum rsbac_adf_request_t request, 
                rsbac_pid_t caller_pid, 
                enum rsbac_target_t target, 
                union rsbac_target_id_t tid, 
                enum rsbac_target_t new_target, 
                union rsbac_target_id_t new_tid, 
                enum rsbac_attribute_t attr, 
                union rsbac_attribute_value_t attr_val, 
                rsbac_uid_t owner); /* process owner */
   

  • Функция контроля перезаписи. Эта функция возвращает значения TRUE или FALSE, когда файл, указанный вхождением, должен быть обнулен при усечении или удалении. Если одна модель сказала да, то выполняется обнуление.

boolean rsbac_reg_need_overwrite_func 
    (struct dentry * dentry_p);
   

  • Callback-функция rsbac_write. Эта функция регулярно вызывается rsbacd или когда требуется учесть через запрос системного вызова rsbac_write систематические задания, которые будут выполняться, обычно на диск пишется грязный список атрибутов.

Параметр need_lock сообщает, что в окружение функции write-to-disk должны быть помещены функции ядра lock_kernel() / unlock_kernel(). К сожалению этот параметр меняется в зависимости от функции вызывающего rsbac_write. Возвращаемое значение является числом записанных списков (0 или более) или отрицательным значением ошибки, например значением, возвращенным rsbac_write_open.

int rsbac_reg_write_func_t(boolean need_lock);
   

  • Callback-функция rsbac_check. Эта функция вызывается через запрос системного вызова rsbac_check для проверки последовательности, обычно раз в день.

Если правильное значение не равно 0, то ошибки должны быть автоматически исправлены. Если check_inode не 0, то числа ссылающиеся на иноды тоже будут проверены. В случае нормального завершения возвращаемое значение - 0, иное - ошибка.

int rsbac_reg_check_func_t(int correct, int check_inode);
   

  • Функция уведомления монтирования файловой системы. Эта функция вызывается в случае монтирования устройства.

int rsbac_reg_mount_func_t(kdev_t kdev);
   

  • Функция уведомления размонтирования файловой системы. Эта функция вызывается в случае, если устройство было размонтировано.

int rsbac_reg_umount_func_t(kdev_t kdev);
   

Функции Регистрации

Для регистрации модуля вы сначала выбираете положительное, 32-х Битное целое со знаком число, это будет ваш персональный дескриптор. Он будет требоваться при всех дальнейших процедурах связанных с регистрацией. Если случится так, что выбранный вами дескриптор в данный момент используется, то вам будет отказано в регистрации со значением ошибки - RSBAC_EEXIST.

rsbac_reg_syscall_entry в struct содержит все необходимые значения. Функция может быть не учтена установкой ее указателя в значение NULL. Ваш модуль позднее будет идентифицирован в сообщениях REG и proc-файлах по его имени. Текущая максимальная длина имени 30 знаков.

Значение переключателя определяет, будет ваш модуль с самого начала включен или выключен. В целях безопасности переключение работает только в том случае, если оно задействовано в конфигурации ядра.

struct rsbac_reg_entry_t 
   { 
       rsbac_reg_handle_t                               handle; 
       char                                             name[RSBAC_REG_NAME_LEN+1]; 
       rsbac_reg_request_func_t                       * request_func; 
       rsbac_reg_set_attr_func_t                      * set_attr_func; 
       rsbac_reg_need_overwrite_func_t                * need_overwrite_func; 
       rsbac_reg_write_func_t                         * write_func; 
       rsbac_reg_mount_func_t                         * mount_func; 
       rsbac_reg_umount_func_t                        * umount_func; 
       boolean                                          switch_on;  /* turned on initially? */ 
};
   

Заданная этой struct регистрация весьма легка. Обычно регистрация происходит в функции init_module() модуля ядра, де-регистрация в cleanup_module(). Выгрузка модуля зарегистрированного REG без де-регистрации убьет вашу систему!

Единственная вещь, добавленная к вхождению struct это значение версии REG, которое позволит производить проверку версий для модулей поставляемых в бинарном виде. Оно должно быть всегда установлено в значение RSBAC_REG_VERSION. Функция регистрации возвратит ва положительный дескриптор или отрицательный код ошибки (для дополнительной информации смотри include/rsbac/reg.h).

rsbac_reg_handle_t rsbac_reg_register 
(        rsbac_version_t      version, 
  struct rsbac_reg_entry_t entry);
   

Единожды зарегистрировавшись вы можете включать или выключать модуль, если это задействовано в конфигурации ядра. Как правило, в случае успеха функция возвращает значение 0 и негативное в случае ошибки.

int rsbac_reg_switch 
   (rsbac_reg_handle_t handle, boolean value);
   

Дерегистрация очень проста.

int rsbac_reg_unregister 
   (rsbac_reg_handle_t handle);
   

ОК! Теперь ваша модель должна работать. Если она также регистрирует syscall- или proc-вхождения, то вы теперь можете взглянуть на его статус.

Позвольте мне снова намекнуть на примеры модулей - использование их, для начала, будет хорошим выбором и предохранит вас от излишнего печатания.

Регистрация Системных Вызовов

Регистрация системных вызовов подобна таковой в модуле принятия решения. Как и с функциями принятия решений, здесь не существует официального ограничения на количество регистрируемых syscall. Только дескрипторы должны каждый раз отличаться.

В целях безопасности, для регистрации и организации syscall должны использоваться разные значения дескрипторов - дескрипторы syscall-диспетчера должны быть доступны для любого использования.

Ваш системный вызов, будучи однажды зарегистрированным, может быть вызван официальным системным вызовом:

int sys_rsbac_reg 
  (rsbac_reg_handle_t handle, 
   void * arg);
  

Дескриптором является дескриптор диспетчера, зарегистрированного с вашей syscall-функцией, указатель arg будет передан непосредственно вашей функции. Это возвращаемое значение будет возвращаемым значением системного вызова.

Функции Обратного Вызова

Ваша -syscall-функция должна выглядеть следующим образом:

int rsbac_reg_syscall_func_t(void * data);
   

Указатель этой функции теперь получит пользовательский указатель. Для работы с вашими данными вы должны сначала получить его из пользовательской области при помощи:

#include rsbac/helpers.h>
int rsbac_get_user 
    (unsigned char * kern_p, unsigned char * user_p, int size);
   

Возвращаемый код вашей функции будет передан вызывающему процессу.

Функции Регистрации.

Теперь, для регистрации syscall, вы выбираете положительное, 32-х Битное целое со знаком число, как ваш персональный дескриптор и другое, подписанное 32-х Битное со знаком значение, как ваш публичный дескриптор syscall-диспетчера. Все действия, связанные с регистрацией, позднее будут нуждаться в этом уникальном секретном дескрипторе. Если случится так, что ваш дескриптор в данный момент используется, то вам будет отказано в регистрации со значением ошибки - RSBAC_EEXIST.

struct rsbac_reg_syscall_entry хранит в себе все необходимые значения. Может быть не учтено только имя. Ваш системный вызов позже будет идентифицирован в сообщениях REG и proc-файлах по их имени и дескриптору публичного диспетчера. Текущая максимальная длина имени ограничена 30 знаками.

struct rsbac_reg_syscall_entry_t 
   { 
       rsbac_reg_handle_t              registration_handle; 
       rsbac_reg_handle_t              dispatcher_handle; 
       char                            name[RSBAC_REG_NAME_LEN+1]; 
       rsbac_reg_syscall_func_t      * syscall_func; 
   };
   

Заданная этой struct регистрация похожа на регистрацию модулем принятия решения. Выгрузка модуля с зарегистрированным syscall без де-регистрации убьет вашу системы при следующем обращении к syscall-функции!

Заново добавленное во вхождение struct является значением версии REG, что позволит производить проверку версии для модулей полученных в бинарном виде. Оно всегда должно быть установлено в RSBAC_REG_VERSION. Функция регистрации возвратит ваш положительный дескриптор или отрицательный код ошибки (для дополнительной информации смотри include/rsbac/reg.h)

rsbac_reg_handle_t rsbac_reg_register_syscall 
    (        rsbac_version_t           version, 
      struct rsbac_reg_syscall_entry_t entry);
   

Однажды зарегистрировав, вы сможете использовать ваши системные вызовы. Де-регистрация теперь проста.

int rsbac_reg_unregister_syscall 
  (rsbac_reg_handle_t registration_handle);
   

Очередной намек на примеры модулей: использование их, для начала, будет хорошим выбором и предохранит вас от излишнего печатания.

Вспомогательные Функции RSBAC

Структура RSBAC предоставляет много вспомогательных функций и переменных, которые могут быть использованы вашим модулем в случае их пригодности.

Общие Списки

С версии 1.1.2 RSBAC предоставляет постоянные общие списки с настраиваемым индексом и размером данных и автоматическим созданием резервных proc-файлов. Полное описание будет в ближайшее время. А пока, пожалуйста, смотрите заголовочный файл include/rsbac/lists.h.

Преобразование Значения в Имя

Все эти функции требуют предопределенного пространства для строки имени. Для удобства возвращается тот же самый указатель действия. Декларации

char name[RSBAC_MAXNAMELEN];
   

достаточно для всех функции, за исключением target_id_name, если в конфигурации ядра задействовано использование полного имени в протоколировании. В этом случае делается один лист (Linux macro PAGE_SIZE).

Эти, и некоторые name-to-value-функции, могут быть также использованы в пользовательском инструментарии, просто скопируйте getname.c, скомпилируйте его в getname.o и соедините с вашей программой. Загляните в инструментарий администратора RSBAC, что бы видеть как это используется.

#include  rsbac/getname.h>

      char * get_request_name
        (char * request_name, 
         enum rsbac_adf_request_t request);
      char * get_attribute_name
        (char * attr_name, 
         enum rsbac_attribute_t attr);
      char * get_scd_type_name
        (char * res_name, 
         enum rsbac_scd_type_t res);
      сhar * get_target_name
        (char * target_type_name, 
         enum rsbac_target_t target, 
         char * target_id_name, 
         union rsbac_target_id_t tid);
      /* returns target_type_name. */
      /* target_id_name includes full identification
         with id numbers and path */
      char * get_switch_target_name
        (char * switch_name, 
         enum rsbac_switch_target_t target);
       /* fixed module names */

      char * get_error_name
        (char * error_name, 
         int error);
      /* RSBAC error names only, other values are
         returned as decimal numbers. */
   

Протоколирование в Системе

#include rsbac/debug.h>

     extern int rsbac_printk(const char *, ...); 
     /* log to rsbac log - use like printk(9) */
   

Доступ в Пользовательское Пространство

#include rsbac/helpers.h>

     int rsbac_get_user 
       (unsigned char * kern_p, unsigned char * user_p, int len); 
     /* get data from user space */
     int rsbac_put_user 
        (unsigned char * kern_p, unsigned char * user_p, int len); 
      /* put data to user space */
         char * rsbac_getname(const char * name); 
      /* allocate a page and copy name from userspace */
         void rsbac_putname(const char * name); 
      /* deallocate the page */ 
   

Главные Атрибуты

Пожалуйста, не меняйте значения и не удаляйте пункты, если вы не уверены в том, что вы знаете что делаете, так как на них завязаны другие модели.

#include rsbac/aci.h>

     int rsbac_get_attr 
       (enum rsbac_target_t target, 
        union rsbac_target_id_t tid, 
        enum rsbac_attribute_t attr, 
        union rsbac_attribute_value_t * attr_val_p, boolean inherit); 
     /* read an attribute value, possibly inherited */
     int rsbac_set_attr 
       (enum rsbac_target_t target, 
        union rsbac_target_id_t tid, 
        enum rsbac_attribute_t attr, 
        union rsbac_attribute_value_t attr_val); 
      /* modify attribute value - automatically creates 
         a list item, if not yet there */
      int rsbac_remove_target 
        (enum rsbac_target_t target, 
         union rsbac_target_id_t tid); 
      /* remove list item -> reset all values to defaults */
   

Доступ к Базе ACI

Обратите пожалуйста внимание, что файловый доступ в каталогах /rsbac к файлам и каталогам не должен выполняться со стандартными системными вызовами - они будут перехватываться и, по возможности, блокироваться. Предохраняйте rsbac_write_sem от открытия раньше, чем файл будет закрыт.

Предупреждение: чтение и запись из и в область ядра требует изменение дескриптора сегмента - смотрите reg_sample2.c как пример того, как это все делается.

#include rsbac/aci_data_structures.h>

    kdev_t rsbac_root_dev; /* System root device */
    extern struct semaphore rsbac_write_sem; 
    /* semaphore, to be held when writing to rsbac dir */

    int rsbac_read_open (char *filename, 
                         struct file *file, 
                         kdev_t dev);
    /* read-open a file in protected rsbac dir on 
       device dev. filename must be basename (no /). */
    int rsbac_write_open(char *filename, 
                         struct file *file, 
                         kdev_t kdev);
    /* same for write-open */
       void rsbac_read_close(struct file *); 
    /* close with cleanup */
       void rsbac_write_close(struct file *);
  

Регистрация Proc файлов/каталогов

Для регистрации в этих каталогах используйте пожалуйста стандартные функции ядра Linux create_proc_entry() и remove_proc_entry().

#include rsbac/procfs.h>

    struct proc_dir_entry * proc_rsbac_root_p; 
    /* rsbac proc root for /proc/rsbac-info */
    struct proc_dir_entry * proc_rsbac_backup_p; 
    /* /proc/rsbac-info/backup for ds raw backup */

   


[Источник ALT Linux Team]

[ опубликовано 22/10/2001 ]

ALT Linux Team - Перевод документации по модулю REG   Версия для печати