Redis is a key-value store. Environment variables - resemble the same. And what if it somehow combine?
For fans of Friday's posts, easy hacking and strange desires - I ask under the cat
There is an impressive list of client libraries for Redis in almost all programming languages. But what if:
In my case, the task arose after the creation of the next CGI-like service, which needed to save state. In this case, the execution of this script can occur on different machines.
Since it was about 2 o'clock in the morning and it was already Friday for me, it was decided to relax and do something simple and interesting.
Is it possible to intercept system calls so that when writing to environment variables ( setenv
), the data
recorded in Redis, and when reading ( getenv
) on the contrary got it from a cache?
Schematically looks like this:
Application <-- [syscall]--> [Wrapper] <-- [GET/DEL/...] --> [Redis]
Yes, there is a good article that describes how to make system call interceptors.
There is an unpopular opportunity to specify the functions of initialization (constructor) and finalization (destructor) in the shared library. In them we will connect.
It was necessary to study the POSIX'a and Linux'a specification on this topic.
Functions that needed to be intercepted:
putenv
setenv
getenv
secure_getenv
clearenv
unsetenv
No dirty tricks - typical CMake from Github
Dependencies
sudo apt install libhiredis-dev cmake build-essential
Assembly
git clone https://github.com/reddec/envredis.git cd envredis mkdir build && cd build cmake -DCMAKE_BUILD_TYPE=Release ../ && make
Important point: some applications do not change the environment variables, but only the internal array. In such applications, the data from Redis will be received, but will not be displayed back.
A good option is python. According to the documentation , the change in os.environ
displayed in the environment variables.
Let's say Redis is already raised on the local machine.
XYZ
variable output. $ python -c 'import os; print("XYZ=" + os.environ.get("XYZ", ""))' # : # XYZ=
$ redis-cli SET XYZ "Hello world" # : # OK
LD_PRELOAD=/path/to/libenvredis.so python -c 'import os; print("XYZ=" + os.environ.get("XYZ", ""))' # # XYZ=Hello world
LD_PRELOAD=/path/to/libenvredis.so python -c 'import os; os.environ["SAY"] = "Bye!"'
redis-cli GET SAY # # "Bye!"
The task took about two hours, taking into account the study of the subject area. Made more for fun than for real purposes.
Nevertheless, someone may come in handy.
Source: https://habr.com/ru/post/344766/
All Articles