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

Та ошибка была произведена ядром. Вы могли попытаться обновить ядро, чтобы видеть, была ли проблема решена.

31
25.02.2015, 17:19
7 ответов

Эта программа, вероятно, разрешает путь к этому файлу из $HOME/.config/myprogram. Таким образом, вы можете сказать, что ваш домашний каталог находится в другом месте, например:

HOME=/nowhere your-program

Теперь, возможно, вашей программе нужен какой-нибудь другой ресурс в вашем домашнем каталоге. Если вы знаете, какие они, вы можете подготовить фальшивый дом для вашей программы со ссылками на ресурс, который ей там нужен.

mkdir -p ~/myprogram-home/.config
ln -s ~/.Xauthority ~/myprogram-home/
...
HOME=~/myprogram-home myprogram
33
27.01.2020, 19:37

Это должно быть возможно с профсоюзами / aufs. Вы создаете chroot окружение для процесса. Вы используете реальный каталог в качестве слоя только для чтения и ставите поверх него пустой каталог. Затем вы монтируете том unionfs в соответствующий каталог в среде chroot и удаляете файл там. Процесс не увидит его, но все остальные увидят.

.
1
27.01.2020, 19:37

Если все остальное не удастся, напишите библиотеку оберток, которую вы вставите с помощью LD_PRELOAD, чтобы вызов open("/home/you/my-program/config.interactive") был перехвачен, но прошел через любую другую библиотеку. Это работает для любого типа программ, даже скриптов оболочки, так как будет фильтровать системные вызовы.

extern int errno;

int open(const char *pathname, int flags)
{
  char *config_path = get_config_file_path();
  if (!strstr(pathname, config_path))
  {
    return get_real_open(pathname, flags);
  }
  else
  {
    errno = ENOENT;
    return -1;
  }
}

Примечание: Я не тестировал этот код, и я не на 100% уверен, что часть errno работает.

Посмотрите, как fakeroot делает это для вызовов типа getuid(2) и stat(2).

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

Original: ./Application

Application -----> libc.so
            open()

Intercepted: LD_PRELOAD=yourlib_wrap.so . /Application

Application -----> yourlib_wrap.so --------------> yourlib_impl.so -----> libc.so
            open()                 get_real_open()                 open()

Edit: Видимо есть флаг ld, который можно включить (-обертка <символ>), что позволяет писать обертки, не прибегая к двойной линковке:

/* yourlib.c */
#include <stdio.h>

int __real_open(const char *pathname, int flags)

int __wrap_open(const char *pathname, int flags)
{
  char *config_path = get_config_file_path();
  if (!strstr(pathname, config_path))
  {
    /* the undefined reference here will resolve to "open" at linking time */
    return __real_open(pathname, flags);
  }
  else
  {
    errno = ENOENT;
    return -1; 
  }
}
28
27.01.2020, 19:37

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

2
27.01.2020, 19:37

Переименуйте файл конфигурации, например, в config.interactive. Создайте другой пустой файл, например config.script.

Теперь создайте мягкую ссылку под названием config (или что бы приложение ни ожидало в качестве конфигурационного файла) на нужную вам реальную конфигурацию и запустите ваше приложение.

ln -s config.interactive config

После этого не забудьте привести свою ссылку в порядок.

0
27.01.2020, 19:37

Если вы точно охарактеризовали , как ваша программа использует конфигурационный файл, Я пропустил это.  Многие программы (такие как bash и vi) будут проверять на наличие конфигурационного файла сразу же после запуска; если файл существует, прочитайте его и закройте.  Эти программы больше никогда не обращаются к этим инициализационным файлам.  Если ваша программа такая, читайте дальше.

Я знаю, что вы отвергли ответы, которые делают конфигурационный файл по-настоящему несуществующим. (переименовывая его), но у меня есть морщина, которую я не видел ни у кого другого.  Делайте это, когда вызываете программу в пакетном режиме:

DELAY_TIME=1
REALPATH="~/.config/myprogram"
HOLDPATH="${REALPATH}.hold"

mv "$REALPATH" "$HOLDPATH"
(sleep "$DELAY_TIME"; mv "$HOLDPATH" "$REALPATH")&
myprogram

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

Это действительно создаёт условия гонки; если программе потребуется слишком много времени для открытия файла, он может получить настоящий файл.  Если такое случается достаточно часто, чтобы это стало проблемой, просто увеличьте значение DELAY_TIME.

0
27.01.2020, 19:37

Мне нравится ответ Стефана, но это трюк любая программа полагает, что какой-либо файл пустой - (потому что его папка временно указывает на фактически пустой файл) :

cat <./test.txt
###OUTPUT###
notempty

mount --bind /dev/null ./test.txt
cat <./test.txt
###NO OUTPUT###

umount ./test.txt
cat <./test.txt
###OUTPUT###
notempty

Вы также можете:

mount --bind ./someotherconfig.conf ./unwanted.conf

Если хотите.

-1
27.01.2020, 19:37

Теги

Похожие вопросы