LINUX.ORG.RU

одсчитать число операций чтения/записи с файлом


0

0

Стоит задача - подсчитать число операций чтения/записи, произведённых с файлом системы (или всех файлов из директории рекурсивно). На вскидку не сложно написать модуль ядра, который считает сумму и отдаёт инфу в /proc. Интересует готовое решение.

Инет обыскал, не нашёл.

anonymous

> Стоит задача - подсчитать число операций чтения/записи, произведённых с файлом системы (или всех файлов из директории рекурсивно). На вскидку не сложно написать модуль ядра, который считает сумму и отдаёт инфу в /proc.

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

> Интересует готовое решение.

я что-то сомневаюсь, что для такой IMHO весьма специфической хотелки есть готовое решение :-/

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от sergej

> Если процесс один или не очень много и это нужно для отладки - то strace+grep...

..и если падение производительности наблюдаемого процесса не важно.. :)

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от klalafuda

strace мне кажется здесь не особенно поможет - нужно отслеживать запись/чтение в определённый(st) inode(ы). сделать можно - смотрите в сторону LKM-троянов (их исходный код), иначе придётся модифицировать (включить проверку на отслеживание записи/чтения) код отвечающий за работу с VFS.

Mr_Nobody
()
Ответ на: комментарий от Mr_Nobody

> strace мне кажется здесь не особенно поможет - нужно отслеживать запись/чтение в определённый(st) inode(ы). сделать можно - смотрите в сторону LKM-троянов (их исходный код), иначе придётся модифицировать (включить проверку на отслеживание записи/чтения) код отвечающий за работу с VFS.

да не нужно ничего модифицировать в VFS, достаточно написать простенький модуль, который умеет перехватывать файловые операции для заданного файла и вести соотв. статистику. управлять им можно хоть через chrdev/ioctl, хоть через procfs или еще как - это уже по вкусу.

в принципе, ничего из ряда вон выходящего и будет стабильно и прозрачно работать.

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от klalafuda

To klalafuda:

я так и написал - или перехватывать или модифицировать btw, как бы Вы перехватывали и (самое интересное) посредством чего?

Mr_Nobody
()
Ответ на: комментарий от Mr_Nobody

> я так и написал - или перехватывать или модифицировать btw, как бы Вы перехватывали и (самое интересное) посредством чего?

1. подставляются вектор операций file operations для конкретного суперблока, которому принадлежит интересующий нас файл (разрешаем по пути).
2. в операции смотрим, наш ли это файл. если наш, то обновляем статистику. после форвардим вызов в сохраненную оригинальную операцию.

в реализации все немного сложнее, но лишь немного. весь модуль можно уместить в ~2000 строк на C вместе с управлением и выдачей статистики наружу.

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от Zmacs

> dnotify?

он не даст статистики по операциям с файлом. я так понимаю, человеку хочется узнать, кто, когда и сколько раз вызвал open/close/read/write/etc для некого файла /var/data/foo или набора файлов.

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от klalafuda

> 1. подставляются вектор операций file operations для конкретного суперблока

чтобы подставить новый сначала нужно определить старый - а это самое интересное

Mr_Nobody
()
Ответ на: комментарий от Mr_Nobody

> чтобы подставить новый сначала нужно определить старый - а это самое интересное

а что там собственно определять, если старый вектор лежит в указателе f_op? :) его и запоминаем в списке сохраненных векторов операций и после уже меняем на свой, динамически созданный. в списке сохраняется пара - старый + новый вектора. уже в своей операции ищем по новому вектору указатель на старый и его вызываем. вот и все дела.

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от klalafuda

Кстати я писал перехват системных вызовов для ядра 2.2.4-ac4 :)

выкладывал тут как-то...

Но это тоже падение производительности...

sergej ★★★★★
()
Ответ на: комментарий от sergej

> а что там собственно определять, если старый вектор лежит в указателе f_op? :)

старый вектор лежит в указателе - это верно но по-моемому от этого не легче - если не ошибаюсь это локальный символ (static) и он не виден другим что экспортируется (видно из System.map) - так это например адреса vfs_write() и тд можно было бы определить в модуле адрес кода, переместить его в другое место, а старый затереть jump'ом на нашу ф-цию, которая будет вызываться при любых записях/чтении vfs - как такой вариант? ;-)

Mr_Nobody
()
Ответ на: комментарий от sergej

> Кстати я писал перехват системных вызовов для ядра 2.2.4-ac4 :)

ну как раз системные вызовы перехватываются без особых проблем. например, это хорошо продемонстрировано в Dazuko (http://www.dazuko.org/). но от голово перехвата сисколов не особо много пользы бо в нем приходится делать руками львиную часть работы, которую за нас в любом случае сделает VFS. например, разресолвить конечный путь, найти файл по дескриптору и пр. мелочи жизни. конечно такие дополниьельные нагрузки не могут не сказаться на производительности системы.

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от Mr_Nobody

> старый вектор лежит в указателе - это верно но по-моемому от этого не легче - если не ошибаюсь это локальный символ (static) и он не виден другим что экспортируется (видно из System.map) - так это например адреса vfs_write() и тд можно было бы определить в модуле адрес кода, переместить его в другое место, а старый затереть jump'ом на нашу ф-цию, которая будет вызываться при любых записях/чтении vfs - как такой вариант? ;-)

у каждого объекта VFS, будь то file, inode, super_block, address_space и иже с ними есть свой вектор операций: file_operations, inode_operations, super_operations etc. этот вектор определяет операций, которые можно производить с объектом и представляет собой структуру с набором указателей на элементарные операции типа read, write, open, release etc.

вектор операций назначается конкретной реализацией файловой системы при создании экземпляра объекта. это может быть сделано явно как в случае с супер блоком, когда файловая система сама выставляет поле s_op в операции get_sb файловой системы для каждого суперблока, или же неявно как в случае с файлом (struct file), когда вектор операций берется из иноды на которую этот файл ссылается.

вот собственно именно этот вектор операций для каждого из интересующий нас объектов мы и перехватываем. а интересует нас по условию задачи лишь вектор операций структуры file, i.e. file->f_op, в котором можно отслеживать открытие, закрытие, чтение и пр. операции над файлом или директорией. для этого достаточно выделить свою структуру file_operations и назначить в ней операции read, write, open etc указывающие на наши foo_read, foo_write, foo_open и пр. ненужные нам операции можно или занулить (это плохо) или же лучше установить на значения из оригинального вектора file_operations.

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от klalafuda

да, пожалуй это самый простой способ: передать модулю параметром интересующую директорию или файл, определить затрагиваемые иноды (сделать список), подменить f_op для каждого inode'а

а перехват системных вызовов наверное не самый лёгкий путь

Mr_Nobody
()
Ответ на: комментарий от Mr_Nobody

> да, пожалуй это самый простой способ: передать модулю параметром интересующую директорию или файл, определить затрагиваемые иноды (сделать список), подменить f_op для каждого inode'а

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

> а перехват системных вызовов наверное не самый лёгкий путь

перехватить sys_read или sys_write как раз не сложно и всего кода на пару десятков строк, равно как и отфорвардить вызов в оригинальный обработчик, вопрос в том, что вам даст этот sys_read и как вы определите, что конкретно этот вызов относится именно к вашему файлу а другой уже нет? это конечно же то-же можно придумать как сделать, но IMHO перехват операций на уровне объектов VFS и элегантнее, и проще и не так сильно бъет по производительности всей системы.

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от klalafuda

Прошу меня простить за то ,что но может быть товарищи велосепидисты обратят внимание на register_security()?

по поводу перехвата syscall`s - что вы будете делать если например syscall_table находиться на странице/страницах недоступной(ых) для записи и нет доступа к таблицам трансляции страниц (как вариант эти помечены как глобальные и кешируются в специальном TLB? в этом случае модификация таблиц трансляции ничего не принесет)

anonymous
()
Ответ на: комментарий от anonymous

> Прошу меня простить за то ,что но может быть товарищи велосепидисты обратят внимание на register_security()?

ну это если знать про него. я к примеру не знал :) хотя идея интересная, нужно будет посмотреть что и как.

> по поводу перехвата syscall`s - что вы будете делать если например syscall_table находиться на странице/страницах недоступной(ых) для записи

ну а мы ее временно разрешим на запись, не проблема. change_page_attr()..

> и нет доступа к таблицам трансляции страниц (как вариант эти помечены как глобальные и кешируются в специальном TLB?

global_flush_tlb()..

> в этом случае модификация таблиц трансляции ничего не принесет)

работает перехват сисколов и никакой SELinux & K не спасает, tested :)

ps: anyway мне для своих задач судя по всему простого register_security() недостаточно, бо нужно перехватывать не только и не столько сами вызовы, сколько передаваемые данные с возможностью их фейка на лету. но вообще функция интересная, спору нет.

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от klalafuda

> ps: anyway мне для своих задач судя по всему простого register_security() недостаточно, бо нужно перехватывать не только и не столько сами вызовы, сколько передаваемые данные с возможностью их фейка на лету. но вообще функция интересная, спору нет.

да и судя по коду register_security(), вектор операций можно зарегистрировать лишь один раз, i.e. они не выстраиваются в цепь -> явно не совсем тру метод в случае, если кто-то еще хочет воспользоваться этой фичей :-/

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от klalafuda

> да и судя по коду register_security(), вектор операций можно зарегистрировать лишь один раз, i.e. они не выстраиваются в цепь -> явно не совсем тру метод в случае, если кто-то еще хочет воспользоваться этой фичей :-/

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

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от anonymous

> Прошу меня простить за то ,что но может быть товарищи велосепидисты обратят внимание на register_security()?

да, и собственно самая главная проблема:

EXPORT_SYMBOL_GPL(register_security);
EXPORT_SYMBOL_GPL(unregister_security);
EXPORT_SYMBOL_GPL(mod_reg_security);
EXPORT_SYMBOL_GPL(mod_unreg_security);

после этих строк и суффикса _GPL модуль Security автоматически идет в зад как класс. c'est la vie.

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от klalafuda

согласитесь, что это не проблема для того, кто вот так запросто может патчить syscall_table :)

по поводу tlb flush - это не поможет, если страница глобальная (т.е остается в TLB даже при его flush). Люди сильно удивлялись когда ловили #GP после правильной модификации таблиц трансляции в нужную этим людям сторону и пытались после записать что-то нехорошее в эту страницу.

anonymous
()
Ответ на: комментарий от anonymous

> согласитесь, что это не проблема для того, кто вот так запросто может патчить syscall_table :)

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

> по поводу tlb flush - это не поможет, если страница глобальная (т.е остается в TLB даже при его flush). Люди сильно удивлялись когда ловили #GP после правильной модификации таблиц трансляции в нужную этим людям сторону и пытались после записать что-то нехорошее в эту страницу.

и как тогда это обойти :-? потому что мне то-же приходится патчить таблицу системных вызовов и хотелось бы делать это как можно более надежно.

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от klalafuda

> и как тогда это обойти :-? потому что мне то-же приходится патчить таблицу системных вызовов и хотелось бы делать это как можно более надежно.

необходимость патчить таблицу системных вызовов вытекает из необходимости отслеживания операций монтирования и размонтирования. причем нужно знать не только то, что монтируется, но и куда именно. so перехват file_system_type->get_sb() тут уже не прокатывает (там нет точки назначения, есть лишь исходное устройство). теоретически, security_operations->sb_mount() мне бы более-менее подошел но есть два но:

1. он вызывается до факта монтирования и служит именно как security operation, i.e. предпроверки можно это делать или нельзя. а мне как раз нужен уже постфактум, i.e. "устройство abc было успешно смонтировано туда-то и туда-то".
2. суффикс _GPL полностью исключает использование этой подсистемы. ну если делать все по-честному конечно..

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от klalafuda

> 2. суффикс _GPL полностью исключает использование этой подсистемы. ну если делать все по-честному конечно..

Что, злые адвокаты не дадут отдать под гпл даже один файлик на си в несколько сот строк? Который не делает вообще ничего полезного (логгирование операций монтирования - вещь полезная очень условно) и никак ни от чего не зависит?

Как же они тогда вообще вам позволили прикоснуться к некошерному софту? Почему вы еще не на соляре? ;)

anonymous
()
Ответ на: комментарий от anonymous

> Что, злые адвокаты не дадут отдать под гпл даже один файлик на си в несколько сот строк? Который не делает вообще ничего полезного (логгирование операций монтирования - вещь полезная очень условно) и никак ни от чего не зависит?

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

> Как же они тогда вообще вам позволили прикоснуться к некошерному софту? Почему вы еще не на соляре? ;)

ну почему же не на соряре, мы и на соляре то-же'с. но одно другое ведь не исключает, правда? :) есть и Linux, есть и Solaris, есть и WinNT+...

// wbr

klalafuda ★☆☆
()

inotify тебе поможет

anonymous
()
Ответ на: комментарий от anonymous

Все проще - несколько строк в ядрe пропатчить и все :)

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

sergej ★★★★★
()
Ответ на: комментарий от anonymous

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

Не пробовали смотреть патч GRSecurity? Там есть отслеживание много чего (в том числе и операций монтирования).

Mr_Nobody
()
Ответ на: комментарий от Mr_Nobody

> Не пробовали смотреть патч GRSecurity? Там есть отслеживание много чего (в том числе и операций монтирования).

heh, если бы я мог патчить ядро то такого вопроса даже не стояло :) что хочу то и внес, не проблема. вся сложность как раз в том, что делать это нужно именно из модуля и не имея возможности что-то пропатчить или пересобрать..

// wbr

klalafuda ★☆☆
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.