Run a Dynamically Linked Executable
Introduction
Most applications are dynamically linked. This means that the application uses shared libraries that are loaded at runtime. This is in contrast to statically linked applications, which include all the necessary libraries in the executable itself. In this guide, we will show you how to run a dynamically linked executable on a Ginger OS virtual machine (VM).
This How To guide will use nginx as an example. Nginx is a popular web server that
is dynamically linked. The steps in this guide can be applied to other dynamically linked
executables.
The code for this guide can be found at https://github.com/gingercybersecurity/ginger-nginx.
Chroot
Building a Ginger VM and testing it is an acceptable path to take. However, building and
starting virtual machines takes more time compared to starting a process. For this reason, you
may want to consider using chroot to decrease the amount of time spent trying to
identify all the required resources of a program.
A chroot environment is a way to isolate a process from the rest of the system by changing its root directory. This means that the process cannot access files outside the specified directory, effectively creating a sandboxed environment. The chroot command is used to set up and enter a chroot environment. See the man page for chroot for more information.
Identify Dependent Libraries
Before running a dynamically linked executable, you must identify the shared libraries that
the executable depends on. You can use the ldd command to list the shared libraries
that an executable depends on. For example, to list the shared libraries that the
nginx executable depends on, you can run the following command:
ubuntu@ubuntu:~$ ldd /usr/sbin/nginx
linux-vdso.so.1 (0x00007fff407a1000)
libcrypt.so.1 => /lib/x86_64-linux-gnu/libcrypt.so.1 (0x0000714ec7c88000)
libpcre2-8.so.0 => /lib/x86_64-linux-gnu/libpcre2-8.so.0 (0x0000714ec7bee000)
libssl.so.3 => /lib/x86_64-linux-gnu/libssl.so.3 (0x0000714ec7b44000)
libcrypto.so.3 => /lib/x86_64-linux-gnu/libcrypto.so.3 (0x0000714ec7600000)
libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x0000714ec7b28000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x0000714ec7200000)
/lib64/ld-linux-x86-64.so.2 (0x0000714ec7e2e000)
Please note that the shared libraries that an executable depends on may vary depending on the OS and executable version.
In the output above, you can see the shared libraries that the nginx executable
depends on. You must ensure that these shared libraries are available inside your Ginger
OS VM. Edit the image version configuration file (typically image.yaml) to include the shared
libraries that the executable depends on. The dirs and files sections
should have the following entries:
dirs:
- path: '/lib'
uid: 10
permissions: 0o700
label: 'nginx_lib'
- path: '/lib/x86_64-linux-gnu'
uid: 10
permissions: 0o700
label: 'nginx_lib'
- path: '/lib64'
uid: 10
permissions: 0o700
label: 'nginx_lib'
files:
- source: '/usr/sbin/nginx'
destination: '/sbin/nginx'
uid: 10
permissions: 0o500
label: 'nginx_exec'
- source: '/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2'
destination: '/lib64/ld-linux-x86-64.so.2'
uid: 10
permissions: 0o500
label: 'nginx_lib'
- source: '/lib/x86_64-linux-gnu/libc.so.6'
destination: '/lib/x86_64-linux-gnu/libc.so.6'
uid: 10
permissions: 0o500
label: 'nginx_lib'
- source: '/lib/x86_64-linux-gnu/libcrypt.so.1.1.0'
destination: '/lib/x86_64-linux-gnu/libcrypt.so.1'
uid: 10
permissions: 0o500
label: 'nginx_lib'
- source: '/lib/x86_64-linux-gnu/libcrypto.so.3'
destination: '/lib/x86_64-linux-gnu/libcrypto.so.3'
uid: 10
permissions: 0o500
label: 'nginx_lib'
- source: '/lib/x86_64-linux-gnu/libpcre2-8.so.0.11.2'
destination: '/lib/x86_64-linux-gnu/libpcre2-8.so.0'
uid: 10
permissions: 0o500
label: 'nginx_lib'
- source: '/lib/x86_64-linux-gnu/libssl.so.3'
destination: '/lib/x86_64-linux-gnu/libssl.so.3'
uid: 10
permissions: 0o500
label: 'nginx_lib'
- source: '/lib/x86_64-linux-gnu/libz.so.1.3'
destination: '/lib/x86_64-linux-gnu/libz.so.1'
uid: 10
permissions: 0o500
label: 'nginx_lib'
Please note that the source and destination names may differ. This is because many of the
dependent libraries use symbolic links. You can use the ls -l command to find the
actual files that are linked into the executable. The source will be the actual file linked
into the executable while the destination will be the dependent name as identified by the
ldd command.
The linux-vdso dependent library is automatically provided by the kernel. You do not need to include this library in the image.yaml file.
Identify Dependent Resources
A program may depend upon more than just shared libraries. It may also depend on other files.
All the dependent files must be identified and copied into the VM via the gingervm
configuration files for the image version, server deployment, and data disk.
This is the same requirement for all programs executed in a Ginger OS VM. The sections below
are specific to nginx, but the process will be the same for other programs.
Passwd and Group
The nginx program will try to look up and switch the uid and gid for the process. The default
user and group are nobody and nogroup. The values can be specified in
the configuration file main section using the user directive.
The nginx program will try to query the user and group using getpwent.
This function will open and parse /etc/passwd and /etc/group. Both of these files must be
provided with an entry for the user to use.
nobody:x:10:10:nobody:/nonexistent:/usr/sbin/nologin
nogroup:x:10:
Make sure the UID and GID in the files match what is expected in the Ginger OS init.yaml file.
Logging and Data Storage
The /var/log/nginx directory must be created so nginx will store the
log files there. The /var/lib/nginx directory must be created so
nginx can write data there.
Configuration File
An nginx.conf configuration file must be provided. See the Nginx documentation for
details on how to configure nginx.
Web Files
The nginx.conf file will specify the files to distribute. Create the appropriate
directories and copy the files to those directories.
Build and Deploy
The final step is to build and deploy the disk images and the VM. The steps are the same as for any other program. See the Run a Rust Application guide for more information.
The code for this guide can be found at https://github.com/gingercybersecurity/ginger-nginx.