summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnthony G. Basile <blueness@gentoo.org>2014-06-08 16:15:06 -0400
committerAnthony G. Basile <blueness@gentoo.org>2014-06-09 21:49:02 -0400
commitba08589f95e4ec77b5e7f73f97278730dc426bcd (patch)
tree120ef66a52d3286a4fe4ead55bd7fe6b02b8289c
parentChangeLog: updated (diff)
downloadelfix-ba08589f95e4ec77b5e7f73f97278730dc426bcd.tar.gz
elfix-ba08589f95e4ec77b5e7f73f97278730dc426bcd.tar.bz2
elfix-ba08589f95e4ec77b5e7f73f97278730dc426bcd.zip
misc/install-xattr: refine the behavior of which()
The wrapper must avoid invoking itself in its attempt to find the system `install` path. The old behavior was to avoid looking in the same directory as the wrapper, but this is too crude since we might have the wrapper in /usr/bin (say), and the system `install` in the same directory, in which case we'll wind up skipping it. The new behavior of which() is to accept argv[0], find its canonical path and skip if it is equal to the canditate system `install` we are checking. We also add PORTAGE_BIN_PATH which will be used in a future commit to avoid this wrapper from finding portage's wrapper. We can then get into a situation where the portage wrapper, usually at ${PORTAGE_BIN_PATH}/ebuild-helpers/xattr/install calls this wrapper, usually at /usr/bin/install-xattr, which in turn calls the portage wrapper in an infinite self-invocation (fork bomb).
-rw-r--r--misc/install-xattr/install-xattr.c42
1 files changed, 24 insertions, 18 deletions
diff --git a/misc/install-xattr/install-xattr.c b/misc/install-xattr/install-xattr.c
index c0c68f9..7dc248b 100644
--- a/misc/install-xattr/install-xattr.c
+++ b/misc/install-xattr/install-xattr.c
@@ -162,10 +162,11 @@ copyxattr(const char *source, const char *target)
static char *
-which(const char *mydir)
+which(const char *myfile)
{
- char *mycandir = realpath(mydir, NULL); /* canonical value of argv[0]'s dirname */
- char *path, *env_path = getenv("PATH"); /* full $PATH string */
+ char *mypath = realpath(myfile, NULL); /* argv[0]'s canonical path */
+ char *path, *env_path = getenv("PATH"); /* full $PATH string */
+ char *portage_bin_path = getenv("PORTAGE_BIN_PATH"); /* PORTAGE BIN $PATHs to skip */
/* If we don't have $PATH in our environment, then pick a sane path. */
if (env_path == NULL) {
@@ -175,39 +176,44 @@ which(const char *mydir)
} else
path = xstrdup(env_path);
- char *dir; /* one directory in the $PATH string */
- char *candir; /* canonical value of that directory */
- char *file; /* file name = path + "/install" */
- char *savedptr; /* reentrant context for strtok_r() */
+ char *dir; /* one directory in the colon delimited $PATH string */
+ char *canfile; /* candidate install's path = dir + "/install" */
+ char *canpath; /* candidate install's canonical path */
+ char *sdir; /* one directory in the $INSTALL_EXCLUDE_PATH string */
+ char *savedptr; /* reentrant context for strtok_r() */
struct stat s;
dir = strtok_r(path, ":", &savedptr);
while (dir) {
- candir = realpath(dir, NULL);
+ canfile = path_join(dir, "install");
+ canpath = realpath(canfile, NULL);
+ free(canfile);
/* ignore invalid paths that cannot be canonicalized */
- if (!candir)
+ if (!canpath)
goto skip;
- file = path_join(candir, "install");
+ /* If argv[0]'s canonical path == candidates install's canonical path,
+ * then we skip this path otheriwise we get into an infinite self-invocation.
+ */
+ if (!strcmp(mypath, canpath))
+ goto skip;
- /* If the file exists and is either a regular file or sym link,
+ /* If the canpath exists and is either a regular file or sym link,
* assume we found the system's install.
*/
- if (stat(file, &s) == 0)
+ if (stat(canpath, &s) == 0)
if (S_ISREG(s.st_mode)) {
- free(candir);
- free(mycandir);
+ free(mypath);
free(path);
- return file;
+ return canpath;
}
- free(file);
skip:
- free(candir);
+ free(canpath);
dir = strtok_r(NULL, ":", &savedptr);
}
@@ -310,7 +316,7 @@ main(int argc, char* argv[])
err(1, "fork() failed");
case 0:
- install = which(dirname(argv[0]));
+ install = which(argv[0]);
argv[0] = install; /* so coreutils' lib/program.c behaves */
execv(install, argv); /* The kernel will free(install). */
err(1, "execv() failed");