summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Cashman <dcashman@google.com>2015-09-10 09:42:15 -0700
committerDan Cashman <dcashman@google.com>2015-09-17 09:23:16 -0700
commit249094fcb1b4d3a37be10e394023bcba75fff2b1 (patch)
tree4c8c5578f36198ed829176ccf7b55295b94d5e7c
parent91b7d911c51f972f127972bc5c529310387fba8b (diff)
downloadlibselinux-249094fcb1b4d3a37be10e394023bcba75fff2b1.tar.gz
Enable restorecon to properly label symlinks.
commit: 06d45512e2df93f65a51877a51549e522b4f2cf5 changed restorecon to only operate on paths which had undergone a realpath transformation. Unfortunately, this made it impossible to directly restorecon a symlink, since the symlink would be followed. Change restorecon to only perform realpath on the directory prefix, so that symlinks can be labeled. Bug: 21732016 Change-Id: I95e18f9a8e9ffda8cf9ab8676052486c68216b00
-rw-r--r--src/android.c44
1 files changed, 34 insertions, 10 deletions
diff --git a/src/android.c b/src/android.c
index 8f66a5a..8949a5d 100644
--- a/src/android.c
+++ b/src/android.c
@@ -31,6 +31,7 @@
#include <limits.h>
#include <sys/vfs.h>
#include <linux/magic.h>
+#include <libgen.h>
/*
* XXX Where should this configuration file be located?
@@ -1231,7 +1232,7 @@ static int selinux_android_restorecon_common(const char* pathname_orig,
struct statfs sfsb;
FTS *fts;
FTSENT *ftsent;
- char *pathname;
+ char *pathname = NULL, *pathdnamer = NULL, *pathdname, *pathbname;
char * paths[2] = { NULL , NULL };
int ftsflags = FTS_NOCHDIR | FTS_XDEV | FTS_PHYSICAL;
int error, sverrno;
@@ -1246,16 +1247,25 @@ static int selinux_android_restorecon_common(const char* pathname_orig,
if (!fc_sehandle)
return 0;
- // convert passed-in pathname to canonical pathname
- pathname = realpath(pathname_orig, NULL);
- if (!pathname) {
- sverrno = errno;
- selinux_log(SELINUX_ERROR, "SELinux: Could not get canonical path %s restorecon: %s.\n",
- pathname_orig, strerror(errno));
- errno = sverrno;
- error = -1;
- goto cleanup;
+ /*
+ * Convert passed-in pathname to canonical pathname by resolving realpath of
+ * containing dir, then appending last component name.
+ */
+ pathbname = basename(pathname_orig);
+ if (!strcmp(pathbname, "/") || !strcmp(pathbname, ".") || !strcmp(pathbname, "..")) {
+ pathname = realpath(pathname_orig, NULL);
+ if (!pathname)
+ goto realpatherr;
+ } else {
+ pathdname = dirname(pathname_orig);
+ pathdnamer = realpath(pathdname, NULL);
+ if (!pathdnamer)
+ goto realpatherr;
+ error = asprintf(&pathname, "%s/%s", pathdnamer, pathbname);
+ if (error < 0)
+ goto oom;
}
+
paths[0] = pathname;
issys = (!strcmp(pathname, SYS_PATH)
|| !strncmp(pathname, SYS_PREFIX, sizeof(SYS_PREFIX)-1)) ? true : false;
@@ -1364,8 +1374,22 @@ out:
(void) fts_close(fts);
errno = sverrno;
cleanup:
+ free(pathdnamer);
free(pathname);
return error;
+oom:
+ sverrno = errno;
+ selinux_log(SELINUX_ERROR, "%s: Out of memory\n", __FUNCTION__);
+ errno = sverrno;
+ error = -1;
+ goto cleanup;
+realpatherr:
+ sverrno = errno;
+ selinux_log(SELINUX_ERROR, "SELinux: Could not get canonical path for %s restorecon: %s.\n",
+ pathname_orig, strerror(errno));
+ errno = sverrno;
+ error = -1;
+ goto cleanup;
}
int selinux_android_restorecon(const char *file, unsigned int flags)