This is the mail archive of the libc-help@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

runtime loader replaces argv[0]


Hi,

My colleagues and I are using the runtime loader in preservation
software for scientific applications. To be specific, we preserve the
runtime loader implicitly used by the software so that it can be run
again in the future, possibly on a completely different platform (but
using the same or newer kernel). In this context, we are using Linux
but the problems exists for all kernels.

The problem we see is that the glibc loader unconditionally replaces
argv[0]. So if I want to run an application on a different platform
that uses a different loader, I would do this instead:

execve("./preserved/ld-linux.so", ["argv[0]" /* from original
experiment */, "./preserved/application.exe" /* physical exe */,
"argv[1]", ...], [...]);

I would expect the loader to simply strip off its argv[1] and leave
the rest alone. Unfortunately, it sets argv[0] to argv[1], as if we
ran:

execve("./preserved/application.exe", ["./preserved/application.exe",
"argv[1]", ...], [...]);

This prevents us from passing the original argv[0] to the application.
I have attached two C programs that exhibit the problem.

Ironically enough, the software that is most affected by this is the
loader itself. If argv[0] is not a real path (i.e. beginning with ./
or /), then it will readlink("/proc/self/exe") to determine the
physical path. In the original experiment with an argv[0] of "foo",
that's exactly what it does. In the rerun experiment with the
preserved loader, argv[0] is "./preserved/application.exe". So the
loader uses this path incorrectly in subsequent library lookups,
ultimately causing the application to fail.

So as for my question, is there a viable workaround for this or does
anyone have some other suggestion?

-- 
Patrick Donnelly
#include <glob.h>
#include <unistd.h>

#include <stdlib.h>

int main (int argc, char *argv[])
{
    glob_t g;
    if (glob("/usr/lib/ld-[0-9]*so", GLOB_ERR|GLOB_NOSORT, NULL, &g) != 0) {
        perror("glob");
        exit(EXIT_FAILURE);
    }

    char *bargv[] = {
        "b", /* as if it was run as "$ b 1 2" */
        "./b", /* the program ld-[0-9]*.so should load */
        "1", /* first arg */
        "2", /* second arg */
        NULL
    };
    if (execv(g.gl_pathv[0], bargv) == -1) {
        perror("execl");
        exit(EXIT_FAILURE);
    }

    globfree(&g);
    return 0;
}
#include <stdio.h>

int main (int argc, char *argv[])
{
    int i;
    for (i = 0; i < argc; i++)
        printf("[%d] '%s'\n", i, argv[i]);
    return 0;
}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]