Embedded Linux and Qt Free Cached Memory with setuid Program

Embedded Linux and Qt Free Cached Memory with setuid Program


On an embedded Linux system RAM ( especially FREE memory ) can be easily and quickly consumed. Imagine that you have a file server running on the board that needs to serve up a 500 Mb file via an HTTP response but you only have 256 Mb of RAM!

Of course you can read back the data in chunks and flush it to the socket as you read, but Linux has a very aggressive caching system ( which is usually a great thing - and snappy! ) and may cache your available RAM down to a very low level by default. If you subsequently stress the system further during that long operation, you may begin to page swap like crazy and get a Kernel panic for lack of free RAM!

One way to free memory that is cached during a large file operation would be to use procfs like so:

sync; echo 3 > /proc/sys/vm/drop_caches

Or, programmatically ( in C++ ) like so:

sync();

std::ofstream ofs("/proc/sys/vm/drop_caches");

ofs << "3" << std::endl;

However, you must be the root user to do this. If you try to echo to those files as a non-root user, you will see something like:

# cd /proc/sys/vm/

# ls -lrt drop_caches

-rw-r--r-- 1 root root 0 Feb 13 19:50 drop_caches

# chmod 777 drop_caches

chmod: drop_caches: Operation not permitted

# chown user:user drop_caches

chown: drop_caches: Operation not permitted

What if you wanted to do this programmatically as a non-root user? Well you could use setuid ( http://en.wikipedia.org/wiki/Setuid ). Using this method sets the setuid and setgid bits using chmod as root which in turn allows non-root users to execute a program with root priviledges. BE VERY CAREFUL about using this as it could be a major security issue ( think denial of service attacks ).

In order to do this in our scenario, create a secondary executable that programmatically clears the cache and run the following command on that file as root:

# chmod 6711 clear_cache_program

This sets the setuid and setgid bits on the file. Now you can call this program from a secondary app that is run as some user that is non-root and it will successfully clear the cache!

By the way, a better way of setting the minimal free cache level in order to circumvent the original problem is to change the value of the procfs entry for this control on boot. You can do this with:

# cd /proc/sys/vm/

# echo 32768 > min_free_kbytes

# cat min_free_kbytes

32768

Happy Coding! :)



ClassyBits 2016