1 |
commit: 03c8c49c168246e6941d1344bcb4605955de0a26 |
2 |
Author: Anthony G. Basile <blueness <AT> gentoo <DOT> org> |
3 |
AuthorDate: Sun Jun 8 20:15:06 2014 +0000 |
4 |
Commit: Anthony G. Basile <blueness <AT> gentoo <DOT> org> |
5 |
CommitDate: Sun Jun 8 20:15:06 2014 +0000 |
6 |
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/elfix.git;a=commit;h=03c8c49c |
7 |
|
8 |
misc/install: refine the behavior of which() |
9 |
|
10 |
The wrapper must avoid invoking itself in its attempt to find the |
11 |
system `install` path. The old behavior was to avoid looking in |
12 |
the same directory as the wrapper, but this is too crude since we |
13 |
might have the wrapper in /usr/bin (say), and the system `install` |
14 |
in the same directory, in which case we'll wind up skipping it. |
15 |
The new behavior of which() is to accept argv[0], find its canonical |
16 |
path and skip if it is equal to the canditate system `install` we |
17 |
are checking. |
18 |
|
19 |
We also add PORTAGE_BIN_PATH which will be used in a future commit |
20 |
to avoid this wrapper from finding portage's wrapper. We can then |
21 |
get into a situation where the portage wrapper, usually at |
22 |
${PORTAGE_BIN_PATH}/ebuild-helpers/xattr/install calls this wrapper, |
23 |
usually at /usr/bin/install-xattr, which in turn calls the portage |
24 |
wrapper in an infinite self-invocation (fork bomb). |
25 |
|
26 |
--- |
27 |
misc/install-xattr/install-xattr.c | 42 ++++++++++++++++++++++---------------- |
28 |
1 file changed, 24 insertions(+), 18 deletions(-) |
29 |
|
30 |
diff --git a/misc/install-xattr/install-xattr.c b/misc/install-xattr/install-xattr.c |
31 |
index c0c68f9..7dc248b 100644 |
32 |
--- a/misc/install-xattr/install-xattr.c |
33 |
+++ b/misc/install-xattr/install-xattr.c |
34 |
@@ -162,10 +162,11 @@ copyxattr(const char *source, const char *target) |
35 |
|
36 |
|
37 |
static char * |
38 |
-which(const char *mydir) |
39 |
+which(const char *myfile) |
40 |
{ |
41 |
- char *mycandir = realpath(mydir, NULL); /* canonical value of argv[0]'s dirname */ |
42 |
- char *path, *env_path = getenv("PATH"); /* full $PATH string */ |
43 |
+ char *mypath = realpath(myfile, NULL); /* argv[0]'s canonical path */ |
44 |
+ char *path, *env_path = getenv("PATH"); /* full $PATH string */ |
45 |
+ char *portage_bin_path = getenv("PORTAGE_BIN_PATH"); /* PORTAGE BIN $PATHs to skip */ |
46 |
|
47 |
/* If we don't have $PATH in our environment, then pick a sane path. */ |
48 |
if (env_path == NULL) { |
49 |
@@ -175,39 +176,44 @@ which(const char *mydir) |
50 |
} else |
51 |
path = xstrdup(env_path); |
52 |
|
53 |
- char *dir; /* one directory in the $PATH string */ |
54 |
- char *candir; /* canonical value of that directory */ |
55 |
- char *file; /* file name = path + "/install" */ |
56 |
- char *savedptr; /* reentrant context for strtok_r() */ |
57 |
+ char *dir; /* one directory in the colon delimited $PATH string */ |
58 |
+ char *canfile; /* candidate install's path = dir + "/install" */ |
59 |
+ char *canpath; /* candidate install's canonical path */ |
60 |
+ char *sdir; /* one directory in the $INSTALL_EXCLUDE_PATH string */ |
61 |
+ char *savedptr; /* reentrant context for strtok_r() */ |
62 |
|
63 |
struct stat s; |
64 |
|
65 |
dir = strtok_r(path, ":", &savedptr); |
66 |
|
67 |
while (dir) { |
68 |
- candir = realpath(dir, NULL); |
69 |
+ canfile = path_join(dir, "install"); |
70 |
+ canpath = realpath(canfile, NULL); |
71 |
+ free(canfile); |
72 |
|
73 |
/* ignore invalid paths that cannot be canonicalized */ |
74 |
- if (!candir) |
75 |
+ if (!canpath) |
76 |
goto skip; |
77 |
|
78 |
- file = path_join(candir, "install"); |
79 |
+ /* If argv[0]'s canonical path == candidates install's canonical path, |
80 |
+ * then we skip this path otheriwise we get into an infinite self-invocation. |
81 |
+ */ |
82 |
+ if (!strcmp(mypath, canpath)) |
83 |
+ goto skip; |
84 |
|
85 |
- /* If the file exists and is either a regular file or sym link, |
86 |
+ /* If the canpath exists and is either a regular file or sym link, |
87 |
* assume we found the system's install. |
88 |
*/ |
89 |
- if (stat(file, &s) == 0) |
90 |
+ if (stat(canpath, &s) == 0) |
91 |
if (S_ISREG(s.st_mode)) { |
92 |
- free(candir); |
93 |
- free(mycandir); |
94 |
+ free(mypath); |
95 |
free(path); |
96 |
- return file; |
97 |
+ return canpath; |
98 |
} |
99 |
|
100 |
- free(file); |
101 |
|
102 |
skip: |
103 |
- free(candir); |
104 |
+ free(canpath); |
105 |
dir = strtok_r(NULL, ":", &savedptr); |
106 |
} |
107 |
|
108 |
@@ -310,7 +316,7 @@ main(int argc, char* argv[]) |
109 |
err(1, "fork() failed"); |
110 |
|
111 |
case 0: |
112 |
- install = which(dirname(argv[0])); |
113 |
+ install = which(argv[0]); |
114 |
argv[0] = install; /* so coreutils' lib/program.c behaves */ |
115 |
execv(install, argv); /* The kernel will free(install). */ |
116 |
err(1, "execv() failed"); |