Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

bypass dev/urandom|random for testing

I want to write a functional test case that tests a program with a known value for random numbers. I have already tested it with mocks during the unit testing. But I would like that for functional testing as well (not all of them, of course :)

What is the easiest way to have /dev/urandom overridden for just one process? Is there a way to do something like a chroot for a single file and let all the others 'pass through'?

like image 566
gcb Avatar asked Sep 26 '14 07:09

gcb


1 Answers

If your system is new enough (e.g. RHEL 7) and supports setns syscall it can be done with the help of mount namespaces. Root access is required.

The idea is to create a separate mount namespace for the process, and inside that namespace bind-mount some other file or FIFO over /dev/random so that the processes from this mount namespace would read the data from this bind-mounted file. Other processes will see the regular /dev/random.

Here is how to do that.

Preparation: run the following command to make all this stuff work (as it may not work by default, see this question for details).

# mount --make-rprivate /

Now let's create a shell running inside a new mount namespace.

# unshare -m /bin/bash

You have the new bash started which has its own mount namespace. You can compare the result of the following command from inside this shell and from some other shell:

This shell:

# ls -l /proc/self/ns/mnt
lrwxrwxrwx. 1 root root 0 Sep 26 16:06 /proc/self/ns/mnt -> mnt:[4026532148]

Other shell:

$ ls -l /proc/self/ns/mnt
lrwxrwxrwx. 1 ec2-user ec2-user 0 Sep 26 16:06 /proc/self/ns/mnt -> mnt:[4026531840]

Note that the numbers differ, so the two shells are in the different mount namespaces and the mounts performed from the first shell will not be visible to other processes in the system (except all the children of this shell).

Now in this shell we can bind-mount something over the existing /dev/random.

# echo 'some large text' > /tmp/fakerandom
# mount --bind /tmp/fakerandom /dev/random

Other processes don't see that, for them /dev/random works as usual:

$ ls -l /dev/random
crw-rw-rw-. 1 root root 1, 8 Sep 26 15:45 /dev/random
$ cat /dev/random
�Znp7�v�c��Ω^C

But in our shell it's special:

# ls -l /dev/random
-rw-r--r--. 1 root root 16 Sep 26 16:18 /dev/random
# cat /dev/random
some large text

For the functional testing you may want to substitute /dev/random with some FIFO and write some known data to that FIFO in some other process (see mkfifo(1) for more information on that if needed).

More information about mount namespaces can be found in this excellent article.

like image 69
afenster Avatar answered Sep 21 '22 14:09

afenster