Mount selinuxfs on /sys/fs/selinux when possible.

Linux 3.0 introduced /sys/fs/selinux as the preferred mount point
directory for selinuxfs.  Upstream libselinux tries to mount selinuxfs
on /sys/fs/selinux first and falls back to /selinux if it doesn't exist.
Do likewise in Android.

Change-Id: Iec738ff7e2f13f809a271eb03f08ef6cd2582bd4
Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
diff --git a/include/selinux/selinux.h b/include/selinux/selinux.h
index f9a02eb..a8fd639 100644
--- a/include/selinux/selinux.h
+++ b/include/selinux/selinux.h
@@ -284,9 +284,6 @@
    which performs the initial mount of selinuxfs. */
 void set_selinuxmnt(char *mnt);
 
-/* selinuxfs mountpoint */
-#define SELINUXMNT "/selinux"
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/android.c b/src/android.c
index ed505a9..d91aafc 100644
--- a/src/android.c
+++ b/src/android.c
@@ -18,6 +18,7 @@
 #include <selinux/label.h>
 #include <selinux/avc.h>
 #include <private/android_filesystem_config.h>
+#include "policy.h"
 #include "callbacks.h"
 #include "selinux_internal.h"
 
@@ -670,17 +671,27 @@
 
 int selinux_android_load_policy(void)
 {
-	mkdir(SELINUXMNT, 0755);
-	if (mount("selinuxfs", SELINUXMNT, "selinuxfs", 0, NULL)) {
+	char *mnt = SELINUXMNT;
+	int rc;
+	rc = mount(SELINUXFS, mnt, SELINUXFS, 0, NULL);
+	if (rc < 0) {
 		if (errno == ENODEV) {
 			/* SELinux not enabled in kernel */
 			return -1;
 		}
+		if (errno == ENOENT) {
+			/* Fall back to legacy mountpoint. */
+			mnt = OLDSELINUXMNT;
+			mkdir(mnt, 0755);
+			rc = mount(SELINUXFS, mnt, SELINUXFS, 0, NULL);
+		}
+	}
+	if (rc < 0) {
 		selinux_log(SELINUX_ERROR,"SELinux:  Could not mount selinuxfs:  %s\n",
 				strerror(errno));
 		return -1;
 	}
-	set_selinuxmnt(SELINUXMNT);
+	set_selinuxmnt(mnt);
 
 	return selinux_android_reload_policy();
 }
diff --git a/src/policy.h b/src/policy.h
index 47023a0..92a416e 100644
--- a/src/policy.h
+++ b/src/policy.h
@@ -12,11 +12,17 @@
 /* selinuxfs magic number */
 #define SELINUX_MAGIC 0xf97cff8c
 
-/* selinuxfs mount point */
+/* Preferred selinuxfs mount point directory paths. */
+#define SELINUXMNT "/sys/fs/selinux"
+#define OLDSELINUXMNT "/selinux"
+
+/* selinuxfs filesystem type string. */
+#define SELINUXFS "selinuxfs"
+
+/* selinuxfs mount point determined at runtime */
 extern char *selinux_mnt;
 
-#define FILECONTEXTS "/etc/security/selinux/file_contexts"
-
+/* First version of policy supported in mainline Linux. */
 #define DEFAULT_POLICY_VERSION 15
 
 #endif