Re: restorecon and symbolic links

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

 



On 31/08/09 21:27, Stephen Smalley wrote:
> On Mon, 2009-08-31 at 14:21 +0100, Martin Orr wrote:
>> On 31/08/09 13:17, Stephen Smalley wrote:
>>> On Sat, 2009-08-29 at 18:19 -0500, Manoj Srivastava wrote:
>>>> On Sat, Aug 29 2009, Martin Orr wrote:
>>>>
>>>>> With policycoreutils 2.0.71, "restorecon /dev/stdin" fails if stdin is a pipe:
>>>>> martin@caligula:~$ echo hi | sudo restorecon /dev/stdin
>>>>> realpath(/dev/stdin) failed No such file or directory
>>>>>
>>>>> The intention here (and what happened with policycoreutils 2.0.69) is to
>>>>> relabel the symbolic link.  But the recent realpath patch changed this, and
>>>>> I don't think there is a way now to ask restorecon to relabel an individual
>>>>> symlink.
>>>
>>> The particular commit was:
>>>
>>> commit 37c5c30998b73d9c6efe53fd0534256463991c5e
>>> Author: Stephen Smalley <sds@xxxxxxxxxxxxx>
>>> Date:   Mon Aug 3 09:34:52 2009 -0400
>>>
>>>     setfiles: only call realpath() on user-supplied pathnames
>>>     
>>>     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>
>>>
>>> What behavior would you like instead?  I'd still like to have restorecon
>>> -R /etc/init.d to do what the user expects, which isn't just relabel the
>>> symlink.
>> True, but I would expect restorecon -R /etc/init.d to relabel the symlink as
>> well as descend into the directory.  On the whole I would expect it not to
>> relabel the target of the symlink itself but I don't have a strong opinion
>> on that, as long as it doesn't fail if the symlink is broken.
> 
> How about this for a compromise?
> 
> Add a -h option to restorecon so that the user can explicitly ask to
> relabel a symlink (as with chcon), but also fall back to proceeding with
> the original path if realpath() fails, in which case we will relabel the
> symlink if the path was a broken symlink.

I think that this is pretty complicated and the fallback behaviour is
potentially confusing.  I still think that restorecon -R /etc/init.d should
by default change the context on the symlink as well as descending into the
directory.

Also, I think it is necessary to restore the code to compute the real path
of all but the last component of a symlink when relabelling the link itself.

The following patch shows approximately the behaviour I would like, except
that it doesn't work, because apply_spec needs an FTSENT:

diff --git a/policycoreutils/setfiles/setfiles.c b/policycoreutils/setfiles/setfiles.c
index 4c47f21..4fd5583 100644
--- a/policycoreutils/setfiles/setfiles.c
+++ b/policycoreutils/setfiles/setfiles.c
@@ -545,6 +545,60 @@ int canoncon(char **contextp)
 	return rc;
 }
 
+static int process_symlink(char *name)
+{
+	int rc = 0;
+	char path[PATH_MAX + 1];
+
+	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, "symlink 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;
+
+	/*rc = apply_spec(name);*/ /* FIXME: Need a FTSENT for apply_spec */
+	fprintf(stderr, "Would restore symlink context: %s\n", name);
+	if (rc == ERR)
+		return -1;
+	return 0;
+}
+
 static int process_one(char *name)
 {
 	int rc = 0;
@@ -555,13 +609,35 @@ static int process_one(char *name)
 
 	if (expand_realpath) {
 		char *p;
-		p = realpath(name, NULL);
-		if (!p) {
-			fprintf(stderr, "realpath(%s) failed %s\n", name,
-				strerror(errno));
+		struct stat sb;
+
+		rc = lstat(name, &sb);
+		if (rc < 0) {
+			fprintf(stderr, "%s:  lstat(%s) failed:  %s\n",
+				progname, name,	strerror(errno));
 			return -1;
 		}
-		name = p;
+		if (S_ISLNK(sb.st_mode)) {
+			rc = process_symlink(name);
+			if (rc < 0)
+				return rc;
+
+			p = realpath(name, NULL);
+			if (!p) {
+				fprintf(stderr, "Warning: %s: Broken symlink: %s\n",
+					name, strerror(errno));
+				return 0;
+			}
+			name = p;
+		} else {
+			p = realpath(name, NULL);
+			if (!p) {
+				fprintf(stderr, "realpath(%s) failed %s\n", name,
+					strerror(errno));
+				return -1;
+			}
+			name = p;
+		}
 	}
 
 

-- 
Martin Orr

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