Gentoo Archives: gentoo-commits

From: "Anthony G. Basile" <blueness@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/elfix:master commit in: misc/install-xattr/
Date: Sun, 08 Jun 2014 20:27:46
Message-Id: 1402258506.03c8c49c168246e6941d1344bcb4605955de0a26.blueness@gentoo
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");