[PATCH] setfiles: only call realpath() on user-supplied pathnames

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Change setfiles/restorecon to only call realpath() on the user-supplied
pathnames prior to invoking fts_open().  This ensures that commands such
as restorecon -R /etc/init.d and (cd /etc && restorecon shadow gshadow)
will work as expected while avoiding the overhead of calling realpath()
on each file during a file tree walk.

Since we are now only acting on user-supplied pathnames, drop the
special case handling of symlinks (when a user invokes restorecon
-R /etc/init.d he truly wants it to descend /etc/rc.d/init.d).  We can
also defer allocation of the pathname buffer to libc by passing NULL
(freeing on the out path) and we can drop the redundant exclude() check
as it will now get handled on the normal path.

Signed-off-by: Stephen Smalley <sds@xxxxxxxxxxxxx>

diff --git a/policycoreutils/setfiles/setfiles.c b/policycoreutils/setfiles/setfiles.c
index 5e5d957..d219225 100644
--- a/policycoreutils/setfiles/setfiles.c
+++ b/policycoreutils/setfiles/setfiles.c
@@ -309,65 +309,6 @@ static int exclude(const char *file)
 
 int match(const char *name, struct stat *sb, char **con)
 {
-	char path[PATH_MAX + 1];
-
-	if (expand_realpath) {
-		if (S_ISLNK(sb->st_mode)) {
-			if (verbose > 1)
-				fprintf(stderr,
-					"Warning! %s refers to a symbolic link, not following last component.\n",
-					name);
-			char *p = NULL, *file_sep;
-			char *tmp_path = strdupa(name);
-			size_t len = 0;
-			if (!tmp_path) {
-				fprintf(stderr, "strdupa on %s failed:  %s\n", name,
-					strerror(errno));
-				return -1;
-			}
-			file_sep = strrchr(tmp_path, '/');
-			if (file_sep == tmp_path) {
-				file_sep++;
-				p = strcpy(path, "");
-			} else if (file_sep) {
-				*file_sep = 0;
-				file_sep++;
-				p = realpath(tmp_path, path);
-			} else {
-				file_sep = tmp_path;
-				p = realpath("./", path);
-			}
-			if (p)
-				len = strlen(p);
-			if (!p || len + strlen(file_sep) + 2 > PATH_MAX) {
-				fprintf(stderr, "realpath(%s) failed %s\n", name,
-					strerror(errno));
-				return -1;
-			}
-			p += len;
-			/* ensure trailing slash of directory name */
-			if (len == 0 || *(p - 1) != '/') {
-				*p = '/';
-				p++;
-			}
-			strcpy(p, file_sep);
-			name = path;
-			if (excludeCtr > 0 && exclude(name))
-				return -1;
-		} else {
-			char *p;
-			p = realpath(name, path);
-			if (!p) {
-				fprintf(stderr, "realpath(%s) failed %s\n", name,
-					strerror(errno));
-				return -1;
-			}
-			name = p;
-			if (excludeCtr > 0 && exclude(name))
-				return -1;
-		}
-	}
-
 	if (NULL != rootpath) {
 		if (0 != strncmp(rootpath, name, rootpathlen)) {
 			fprintf(stderr, "%s:  %s is not located in %s\n",
@@ -619,14 +560,28 @@ int canoncon(char **contextp)
 static int process_one(char *name)
 {
 	int rc = 0;
-	const char *namelist[2] = {name, NULL};
+	const char *namelist[2];
 	dev_t dev_num = 0;
 	FTS *fts_handle;
 	FTSENT *ftsent;
 
+	if (expand_realpath) {
+		char *p;
+		p = realpath(name, NULL);
+		if (!p) {
+			fprintf(stderr, "realpath(%s) failed %s\n", name,
+				strerror(errno));
+			return -1;
+		}
+		name = p;
+	}
+
+
 	if (!strcmp(name, "/"))
 		mass_relabel = 1;
 
+	namelist[0] = name;
+	namelist[1] = NULL;
 	fts_handle = fts_open((char **)namelist, fts_flags, NULL);
 	if (fts_handle  == NULL) {
 		fprintf(stderr,
@@ -676,6 +631,8 @@ out:
 	}
 	if (fts_handle)
 		fts_close(fts_handle);
+	if (expand_realpath)
+		free(name);
 	return rc;
 
 err:


-- 
Stephen Smalley
National Security Agency


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@xxxxxxxxxxxxx with
the words "unsubscribe selinux" without quotes as the message.

[Index of Archives]     [Selinux Refpolicy]     [Linux SGX]     [Fedora Users]     [Fedora Desktop]     [Yosemite Photos]     [Yosemite Camping]     [Yosemite Campsites]     [KDE Users]     [Gnome Users]

  Powered by Linux