From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <gentoo-commits+bounces-702180-garchives=archives.gentoo.org@lists.gentoo.org>
Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80])
	by finch.gentoo.org (Postfix) with ESMTP id 403FD1387FD
	for <garchives@archives.gentoo.org>; Tue, 10 Jun 2014 01:49:19 +0000 (UTC)
Received: from pigeon.gentoo.org (localhost [127.0.0.1])
	by pigeon.gentoo.org (Postfix) with SMTP id CEF71E08F7;
	Tue, 10 Jun 2014 01:49:16 +0000 (UTC)
Received: from smtp.gentoo.org (smtp.gentoo.org [140.211.166.183])
	(using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits))
	(No client certificate requested)
	by pigeon.gentoo.org (Postfix) with ESMTPS id 42096E08F7
	for <gentoo-commits@lists.gentoo.org>; Tue, 10 Jun 2014 01:49:16 +0000 (UTC)
Received: from spoonbill.gentoo.org (spoonbill.gentoo.org [81.93.255.5])
	(using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits))
	(No client certificate requested)
	by smtp.gentoo.org (Postfix) with ESMTPS id 3452B33FFDD
	for <gentoo-commits@lists.gentoo.org>; Tue, 10 Jun 2014 01:49:15 +0000 (UTC)
Received: from localhost.localdomain (localhost [127.0.0.1])
	by spoonbill.gentoo.org (Postfix) with ESMTP id 1BC1F181A9
	for <gentoo-commits@lists.gentoo.org>; Tue, 10 Jun 2014 01:49:13 +0000 (UTC)
From: "Anthony G. Basile" <blueness@gentoo.org>
To: gentoo-commits@lists.gentoo.org
Content-Transfer-Encoding: 8bit
Content-type: text/plain; charset=UTF-8
Reply-To: gentoo-dev@lists.gentoo.org, "Anthony G. Basile" <blueness@gentoo.org>
Message-ID: <1402364942.ba08589f95e4ec77b5e7f73f97278730dc426bcd.blueness@gentoo>
Subject: [gentoo-commits] proj/elfix:master commit in: misc/install-xattr/
X-VCS-Repository: proj/elfix
X-VCS-Files: misc/install-xattr/install-xattr.c
X-VCS-Directories: misc/install-xattr/
X-VCS-Committer: blueness
X-VCS-Committer-Name: Anthony G. Basile
X-VCS-Revision: ba08589f95e4ec77b5e7f73f97278730dc426bcd
X-VCS-Branch: master
Date: Tue, 10 Jun 2014 01:49:13 +0000 (UTC)
Precedence: bulk
List-Post: <mailto:gentoo-commits@lists.gentoo.org>
List-Help: <mailto:gentoo-commits+help@lists.gentoo.org>
List-Unsubscribe: <mailto:gentoo-commits+unsubscribe@lists.gentoo.org>
List-Subscribe: <mailto:gentoo-commits+subscribe@lists.gentoo.org>
List-Id: Gentoo Linux mail <gentoo-commits.gentoo.org>
X-BeenThere: gentoo-commits@lists.gentoo.org
X-Archives-Salt: f865127f-a05b-489e-a5fc-ffba485cc5e6
X-Archives-Hash: f3865fbf9769acd5962bc14387c8b905

commit:     ba08589f95e4ec77b5e7f73f97278730dc426bcd
Author:     Anthony G. Basile <blueness <AT> gentoo <DOT> org>
AuthorDate: Sun Jun  8 20:15:06 2014 +0000
Commit:     Anthony G. Basile <blueness <AT> gentoo <DOT> org>
CommitDate: Tue Jun 10 01:49:02 2014 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/elfix.git;a=commit;h=ba08589f

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).

---
 misc/install-xattr/install-xattr.c | 42 ++++++++++++++++++++++----------------
 1 file 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");