Move linker config under /linkerconfig

Currently linker config locates under /dev, but this makes some problem
in case of using two system partitions with chroot. To match system
image and configuration, linker config better stays under /linkerconfig

Bug: 144966380
Test: m -j passed && tested from cuttelfish
Change-Id: Iaae5af65721eee8106311c1efb4760a9db13564a
diff --git a/init/Android.mk b/init/Android.mk
index 997b2bc..fc1a182 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -75,7 +75,6 @@
 
 # Set up the same mount points on the ramdisk that system-as-root contains.
 LOCAL_POST_INSTALL_CMD := mkdir -p \
-    $(TARGET_RAMDISK_OUT)/apex \
     $(TARGET_RAMDISK_OUT)/debug_ramdisk \
     $(TARGET_RAMDISK_OUT)/dev \
     $(TARGET_RAMDISK_OUT)/mnt \
diff --git a/init/first_stage_init.cpp b/init/first_stage_init.cpp
index ac44796..bd71cb5 100644
--- a/init/first_stage_init.cpp
+++ b/init/first_stage_init.cpp
@@ -204,10 +204,6 @@
     // part of the product partition, e.g. because they are mounted read-write.
     CHECKCALL(mkdir("/mnt/product", 0755));
 
-    // /apex is used to mount APEXes
-    CHECKCALL(mount("tmpfs", "/apex", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV,
-                    "mode=0755,uid=0,gid=0"));
-
     // /debug_ramdisk is used to preserve additional files from the debug ramdisk
     CHECKCALL(mount("tmpfs", "/debug_ramdisk", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV,
                     "mode=0755,uid=0,gid=0"));
diff --git a/init/init.cpp b/init/init.cpp
index 6ba64ee..5f97e44 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -512,10 +512,24 @@
 
 static void UmountDebugRamdisk() {
     if (umount("/debug_ramdisk") != 0) {
-        LOG(ERROR) << "Failed to umount /debug_ramdisk";
+        PLOG(ERROR) << "Failed to umount /debug_ramdisk";
     }
 }
 
+static void MountExtraFilesystems() {
+#define CHECKCALL(x) \
+    if ((x) != 0) PLOG(FATAL) << #x " failed.";
+
+    // /apex is used to mount APEXes
+    CHECKCALL(mount("tmpfs", "/apex", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV,
+                    "mode=0755,uid=0,gid=0"));
+
+    // /linkerconfig is used to keep generated linker configuration
+    CHECKCALL(mount("tmpfs", "/linkerconfig", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV,
+                    "mode=0755,uid=0,gid=0"));
+#undef CHECKCALL
+}
+
 static void RecordStageBoottimes(const boot_clock::time_point& second_stage_start_time) {
     int64_t first_stage_start_time_ns = -1;
     if (auto first_stage_start_time_str = getenv(kEnvFirstStageStartedAt);
@@ -656,6 +670,9 @@
         UmountDebugRamdisk();
     }
 
+    // Mount extra filesystems required during second stage init
+    MountExtraFilesystems();
+
     // Now set up SELinux for second stage.
     SelinuxSetupKernelLogging();
     SelabelInitialize();
diff --git a/init/mount_namespace.cpp b/init/mount_namespace.cpp
index 940fb6b..c33e0de 100644
--- a/init/mount_namespace.cpp
+++ b/init/mount_namespace.cpp
@@ -172,6 +172,11 @@
     // the bootstrap namespace get APEXes from the read-only partition.
     if (!(MakePrivate("/apex"))) return false;
 
+    // /linkerconfig is a private mountpoint to give a different linker configuration
+    // based on the mount namespace. Subdirectory will be bind-mounted based on current mount
+    // namespace
+    if (!(MakePrivate("/linkerconfig"))) return false;
+
     bootstrap_ns_fd.reset(OpenMountNamespace());
     bootstrap_ns_id = GetMountNamespaceId();
 
diff --git a/init/selinux.cpp b/init/selinux.cpp
index 2fc8f6d..852d6ca 100644
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -531,6 +531,8 @@
     selinux_android_restorecon("/dev/device-mapper", 0);
 
     selinux_android_restorecon("/apex", 0);
+
+    selinux_android_restorecon("/linkerconfig", 0);
 }
 
 int SelinuxKlogCallback(int type, const char* fmt, ...) {
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index 994d9ae..d0baa57 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -72,7 +72,8 @@
 #
 # create some directories (some are mount points) and symlinks
 LOCAL_POST_INSTALL_CMD := mkdir -p $(addprefix $(TARGET_ROOT_OUT)/, \
-    dev proc sys system data odm oem acct config storage mnt apex debug_ramdisk $(BOARD_ROOT_EXTRA_FOLDERS)); \
+    dev proc sys system data odm oem acct config storage mnt apex debug_ramdisk \
+    linkerconfig $(BOARD_ROOT_EXTRA_FOLDERS)); \
     ln -sf /system/bin $(TARGET_ROOT_OUT)/bin; \
     ln -sf /system/etc $(TARGET_ROOT_OUT)/etc; \
     ln -sf /data/user_de/0/com.android.shell/files/bugreports $(TARGET_ROOT_OUT)/bugreports; \
diff --git a/rootdir/init.rc b/rootdir/init.rc
index e2ecad4..afced82 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -38,12 +38,9 @@
     # Allow up to 32K FDs per process
     setrlimit nofile 32768 32768
 
-    # Create directory to keep ld.config.txt
-    mkdir /dev/linkerconfig 0755
-
     # Generate ld.config.txt for early executed processes
-    exec -- /system/bin/linkerconfig --target /dev/linkerconfig/ld.config.txt
-    chmod 444 /dev/linkerconfig/ld.config.txt
+    exec -- /system/bin/linkerconfig --target /linkerconfig/ld.config.txt
+    chmod 444 /linkerconfig/ld.config.txt
 
     start ueventd