MacOSX-FileSystem-Filter icon indicating copy to clipboard operation
MacOSX-FileSystem-Filter copied to clipboard

Hide a file in folder by filtering lookup.

Open Arbaks opened this issue 6 years ago • 4 comments

Здравствуйте, Слава. Мы два студента, пытающиеся выполнить лабораторную по драйверам в Маке. Поскольку в сети, к сожалению, почти нет информации по программированию в ядре для Мака, то ваш проект стал очень полезным подспорьем. Тем не менее, перед нами встала проблема, которую мы не можем решить. Мы нигде не можем найти информацию о том, как сформировать новый vnode для того, чтобы скрыть какой-то конкретный файл. Идея кардинально проста. Хукаем lookup, вытаскиваем из vnod'a имя, проверяем его. Если имя не то, то просто выдаем обратно тот же самый vnode, а вот как модифицировать vnode, чтобы в результате, например, того же ls'а на месте файла ничего не появлялось - непонятно. Простите за такой банальный вопрос и, надеюсь, вы найдете время, чтобы нам помочь. Спасибо.

Arbaks avatar Jan 19 '19 19:01 Arbaks

Чтобы скрыть файл надо убрать его описание из данных возвращенных следующими операциями vnop_reddir_desc (вызывается VNOP_READDIR) vnop_reddir_desc (VNOP_READDIR) vnop_getattrlistbulk_desc (VNOP_GETATTRLISTBULK) эти функции возвращают массив с описанием данных для файлов в директории.

Фильтруя только lookup убрать vnode из списка файлов в директории не всегда возможно. Lookup запрашивает vnode от файловой системы и обычно помещает его в кеш если это не запрещено (создают vnode вызовом vnode_create если он уже не существует - это задача файловой системы следить за тем какие vnode уже созданы и не создавать новых для этого имени а возвратить созданный). Убрать его фильтруя lookup можно только если импленетация vnop_readdir* в файловой системе вызывает lookup (это не делают обычно) или если приложение после readdir вызывает например stat() (но показать в спсике файлов его все равно смогут, например Midnight Commander покажет его красным как недоступный). Тем не менее вам надо запретить открывать vnode и я вам рекомендую вместо перехвата lookup который несколько затруднен из-за кеша vnode (нужно нетривиальную логику сделать для его обхода) в дополнение к перехвату тех трех функций что я описал добавить в свой фильтр KAUTH callback для KAUTH_SCOPE_VNODE вызовом kauth_listen_scope и в этом callback запрещать доступ к vnode который вы скрываете чтобы даже имея имя нельзя было открыть его несмотря на то что в списке директории он не показывается благодаря фильтрации readdir функции которую вы добавите.

Если вам интересно как в lookup в фильтрах создают vnode вам надо посмотреть сюда https://github.com/slavaim/MacOSX-VFS-Isolation-Filter/blob/master/FileSystem-Isolation/VifCoveringVnode.cpp#L202 . Но этот путь как я указал требует обхода кеша vnode иначе иногда ваш хук не будет вызываться так как vnode был помещен в кеш до того как стартовал ваш фильтр. Это можно обойти но это уже слишком много для лабораторной. Вам достаточно KAUTH колбека.

Ну и конечно вам надо в lookup скорее возвращать ошибку EPERM например убрав предварительно референс с возвращенного vnode - vnode_put(*ap->a_vpp) и поставив ее в ноль *ap->a_vpp = NULLVP; . Но того же и даже лучше вы добьетесь вернув ошибку в KAUTH callback , дереференсить vnode при этом не надо.

slavaim avatar Jan 20 '19 02:01 slavaim

Спасибо большое за помощь. Можно небольшое уточнение? То есть, например, если мы можем поместить скрываемый файл в отдельную папку и вернуть результатом этих трех вышеописанных функций для этой папки - NULL, то результатом ls в ней будет пустая папка, так? И можно еще одно уточнение: если мы считаем, что информации об этих файлах в кэше нет, то куда должна подаваться информация на выход о них в лукапе?

Arbaks avatar Jan 20 '19 15:01 Arbaks

NULL возвращать не надо. Даже у пустой директории возвращаются две записи '.' '..' которые вначале массива возвращенного. Чтобы лучше понять посмотрите код файловой системы FAT, там простой код в отличие от HFS, - функция msdosfs_vnop_read в https://opensource.apple.com/source/msdosfs/msdosfs-229.200.3/msdosfs.kextproj/msdosfs.kmodproj/msdosfs_vnops.c

Про lookup я не понял вопрос. Lookup возвращает vnode . Возвращать его или вместо него ошибку - зависит от того что вы хотите. Если вернули vnode то он есть для системы и надо тогда запрещать в KAUTH callback доступ иначе файл будет доступен по полному имени несмотря даже на отсуствие его в списке readdir. Этим будет запрещен доступ к файлу для всех юзермод приложений и большей части кернел мод кода. Как я сказал - вам lookup вобще не нужен, достаточно в KAUTH callback вернуть ошибку и тем самым запретить возврат vnode . Если уж вам очень хочется в lookup все сделать то надо возвращать не vnode а NULL в ap->a_vpp и ошибку из lookup.

slavaim avatar Jan 20 '19 19:01 slavaim

Если у вас задача иметь доступ к файлу но не показывать его в списке файлов директории то вам вобще не надо ничего делать с lookup - она вернет vnode любому у кого есть имя файла.

Если надо фильтровать доступ к этому "секретному" файлу по какому то признаку то фильтруйте в KAUTH callback - делать это в lookup можно но неудобно.

slavaim avatar Jan 20 '19 19:01 slavaim