Se tudo mais falhar, escreva uma biblioteca de wrapper que você vai injetar usando LD_PRELOAD
para que a chamada para open("/home/you/my-program/config.interactive")
seja interceptada, mas qualquer outra será transmitida. Isso funciona para qualquer tipo de programa, até mesmo scripts de shell, já que ele filtrará as chamadas do sistema.
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;
}
}
Observação: eu não testei este código e não tenho 100% de certeza de que a parte errno
funciona.
Veja como fakeroot
o faz para chamadas como getuid(2)
e stat(2)
.
Basicamente, o vinculador vinculará esse aplicativo à sua biblioteca, que substituirá o símbolo open
. Como você não pode usar duas funções diferentes denominadas open
em sua própria biblioteca, é necessário separá-las em uma segunda parte (por exemplo, get_real_open
), que por sua vez vinculará à chamada open
original.
Original: ./Application
Application -----> libc.so
open()
Interceptado: LD_PRELOAD=yourlib_wrap.so ./Application
Application -----> yourlib_wrap.so --------------> yourlib_impl.so -----> libc.so
open() get_real_open() open()
Editar: Aparentemente existe um ld
flag que você pode ativar ( --wrap <symbol>
) que permite escrever wrappers sem ter que recorrer a links duplos:
/* 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;
}
}