Transplanting Linux Libraries to a Shared Host

The goal is to run Linux binaries on a shared host where we do not have root access, and there are no package managers installed (because it’s shared hosting). The shared libraries need to be copied over manually. Here is how we can do it.

If you’re like me, you might have a (few) shared hosting accounts around town. They’re inexpensive and convenient. When I want to run tools like Xvfb and wkhtmltoimage they need shared libraries (the .so files). Some shared libraries might be helpfully present (e.g. libc.so, libgtk-x11-2.so, libasound.so), but some are not (e.g. libstdc++). Since it is a shared host there are no package managers installed, or else we could just yum-install it.

You can find the Xvfb package online (e.g. from rpmfind.net), but it has dependencies and those dependencies might have more dependencies1. Even if I manually find all the best-match packages and extract the libraries, the gotcha is that there may still be problems like the following.

The shared host in this example is using an older version of GLibc. First, I need to know which one by running /lib64/libc.so.6 or ldd --version.

1

2

3

4

5

6

7

GNUCLibrary stable release version2.12,by Roland McGrath et al.

Copyright(C)2010Free Software Foundation,Inc.

Thisisfree software;see the source forcopying conditions.

There isNO warranty;noteven forMERCHANTABILITY orFITNESS FORA

PARTICULAR PURPOSE.

Compiled by GNU CC version4.4.720120313(Red Hat4.4.7-16).

Compiled onaLinux2.6.32system on2016-03-30.

This means that on this example system I must use libraries that at most link to GLibc 2.12. I’d like to avoid recompiling the binaries I’m trying to use to change the “baked in” path of /lib64/libc.so.6 (but we can), and unfortunately we cannot use LD_PRELOAD (more info) for a local version of libc.so.6:

The CentOS 6.8 virtual machine I’m using here has the target GLibc 2.12 so I can go ahead and install packages, and transfer the shared libraries from the /usr/lib64 folder.

Continuing this example with Xvfb, which is used in a SlimerJS project, we can install it like so:

1

yum install xorg-x11-server-Xvfb.x86_64

Let’s see what non-system dependencies were created in the /usr/lib64 folder:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

# ldd Xvfb | grep '/usr/lib64/' | cut -d '=' -f1

libcrypto.so.10

libGL.so.1

libpixman-1.so.0

libXfont.so.1

libXau.so.6

libxshmfence.so.1

libXdmcp.so.6

libglapi.so.0

libXext.so.6

libXdamage.so.1

libXfixes.so.3

libX11-xcb.so.1

libX11.so.6

libxcb-glx.so.0

libxcb-dri2.so.0

libxcb.so.1

libXxf86vm.so.1

libdrm.so.2

libfreetype.so.6

libfontenc.so.1

libfreebl3.so

These are the shared libraries residing in /usr/lib64 that are being linked against by Xvfb, and are symlinked to the actual libraries. With tar we can get them dereferenced and compressed for transport to the target machine. Using the Xvfb binary example the tarball of the shared libraries can be created.

Assume for this discussion that the following environment variable is set:

1

SRCFILE=/usr/bin/Xvfb

Let’s construct our tar script step by step. First we’ll print out all the libraries we want to transplant.

The tar options are where the magic happens. Importantly, the -h or --dereference switch tells tar to follow any symlinks and include the actual file in the tarball. The --xform='s|.*/||' strips the directory structure from the resulting tarball so all the library files at the base of the archive2.

This is the final command to create our tar’d archive of shared libraries.