Merge "Keep /sdcard working for shell process when isolated storage is enabled."
diff --git a/VoldNativeService.cpp b/VoldNativeService.cpp
index b034707..8445cd8 100644
--- a/VoldNativeService.cpp
+++ b/VoldNativeService.cpp
@@ -146,6 +146,69 @@
     return ok();
 }
 
+binder::Status checkArgumentPackageName(const std::string& packageName) {
+    // This logic is borrowed from PackageParser.java
+    bool hasSep = false;
+    bool front = true;
+
+    for (size_t i = 0; i < packageName.length(); ++i) {
+        char c = packageName[i];
+        if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
+            front = false;
+            continue;
+        }
+        if (!front) {
+            if ((c >= '0' && c <= '9') || c == '_') {
+                continue;
+            }
+        }
+        if (c == '.') {
+            hasSep = true;
+            front = true;
+            continue;
+        }
+        return exception(binder::Status::EX_ILLEGAL_ARGUMENT,
+                StringPrintf("Bad package character %c in %s", c, packageName.c_str()));
+    }
+
+    if (front) {
+        return exception(binder::Status::EX_ILLEGAL_ARGUMENT,
+                StringPrintf("Missing separator in %s", packageName.c_str()));
+    }
+
+    return ok();
+}
+
+binder::Status checkArgumentPackageNames(const std::vector<std::string>& packageNames) {
+    for (size_t i = 0; i < packageNames.size(); ++i) {
+        binder::Status status = checkArgumentPackageName(packageNames[i]);
+        if (!status.isOk()) {
+            return status;
+        }
+    }
+    return ok();
+}
+
+binder::Status checkArgumentSandboxId(const std::string& sandboxId) {
+    // sandboxId will be in either the format shared:<shared-user-id> or <package-name>
+    // and <shared-user-id> name has same requirements as <package-name>.
+    std::size_t nameStartIndex = 0;
+    if (android::base::StartsWith(sandboxId, "shared:")) {
+        nameStartIndex = 7;  // len("shared:")
+    }
+    return checkArgumentPackageName(sandboxId.substr(nameStartIndex));
+}
+
+binder::Status checkArgumentSandboxIds(const std::vector<std::string>& sandboxIds) {
+    for (size_t i = 0; i < sandboxIds.size(); ++i) {
+        binder::Status status = checkArgumentSandboxId(sandboxIds[i]);
+        if (!status.isOk()) {
+            return status;
+        }
+    }
+    return ok();
+}
+
 #define ENFORCE_UID(uid) {                                  \
     binder::Status status = checkUid((uid));                \
     if (!status.isOk()) {                                   \
@@ -174,6 +237,20 @@
     }                                                       \
 }
 
+#define CHECK_ARGUMENT_PACKAGE_NAMES(packageNames) {                        \
+    binder::Status status = checkArgumentPackageNames((packageNames));      \
+    if (!status.isOk()) {                                                   \
+        return status;                                                      \
+    }                                                                       \
+}
+
+#define CHECK_ARGUMENT_SANDBOX_IDS(sandboxIds) {                            \
+    binder::Status status = checkArgumentSandboxIds((sandboxIds));          \
+    if (!status.isOk()) {                                                   \
+        return status;                                                      \
+    }                                                                       \
+}
+
 #define ACQUIRE_LOCK \
     std::lock_guard<std::mutex> lock(VolumeManager::Instance()->getLock()); \
     ATRACE_CALL();
@@ -247,7 +324,6 @@
     return translate(VolumeManager::Instance()->shutdown());
 }
 
-// TODO: sanity-check these string arguments
 binder::Status VoldNativeService::onUserAdded(int32_t userId, int32_t userSerial) {
     ENFORCE_UID(AID_SYSTEM);
     ACQUIRE_LOCK;
@@ -265,6 +341,7 @@
 binder::Status VoldNativeService::onUserStarted(int32_t userId,
         const std::vector<std::string>& packageNames) {
     ENFORCE_UID(AID_SYSTEM);
+    CHECK_ARGUMENT_PACKAGE_NAMES(packageNames);
     ACQUIRE_LOCK;
 
     return translate(VolumeManager::Instance()->onUserStarted(userId, packageNames));
@@ -277,19 +354,19 @@
     return translate(VolumeManager::Instance()->onUserStopped(userId));
 }
 
-// TODO: sanity-check these string arguments
 binder::Status VoldNativeService::addAppIds(const std::vector<std::string>& packageNames,
         const std::vector<int32_t>& appIds) {
     ENFORCE_UID(AID_SYSTEM);
+    CHECK_ARGUMENT_PACKAGE_NAMES(packageNames);
     ACQUIRE_LOCK;
 
     return translate(VolumeManager::Instance()->addAppIds(packageNames, appIds));
 }
 
-// TODO: sanity-check these string arguments
 binder::Status VoldNativeService::addSandboxIds(const std::vector<int32_t>& appIds,
         const std::vector<std::string>& sandboxIds) {
     ENFORCE_UID(AID_SYSTEM);
+    CHECK_ARGUMENT_SANDBOX_IDS(sandboxIds);
     ACQUIRE_LOCK;
 
     return translate(VolumeManager::Instance()->addSandboxIds(appIds, sandboxIds));
diff --git a/secdiscard.cpp b/secdiscard.cpp
index f9532ea..60834e8 100644
--- a/secdiscard.cpp
+++ b/secdiscard.cpp
@@ -57,7 +57,33 @@
         usage(argv[0]);
         return -1;
     }
+
     for (auto const &target: options.targets) {
+// F2FS-specific ioctl
+// It requires the below kernel commit merged in v4.16-rc1.
+//   1ad71a27124c ("f2fs: add an ioctl to disable GC for specific file")
+// In android-4.4,
+//   56ee1e817908 ("f2fs: updates on v4.16-rc1")
+// In android-4.9,
+//   2f17e34672a8 ("f2fs: updates on v4.16-rc1")
+// In android-4.14,
+//   ce767d9a55bc ("f2fs: updates on v4.16-rc1")
+#ifndef F2FS_IOC_SET_PIN_FILE
+#ifndef F2FS_IOCTL_MAGIC
+#define F2FS_IOCTL_MAGIC		0xf5
+#endif
+#define F2FS_IOC_SET_PIN_FILE	_IOW(F2FS_IOCTL_MAGIC, 13, __u32)
+#define F2FS_IOC_GET_PIN_FILE	_IOW(F2FS_IOCTL_MAGIC, 14, __u32)
+#endif
+        android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(
+            target.c_str(), O_WRONLY, 0)));
+        if (fd == -1) {
+            LOG(ERROR) << "Secure discard open failed for: " << target;
+            return 0;
+        }
+        __u32 set = 1;
+        ioctl(fd, F2FS_IOC_SET_PIN_FILE, &set);
+
         LOG(DEBUG) << "Securely discarding '" << target << "' unlink=" << options.unlink;
         if (!secdiscard_path(target)) {
             LOG(ERROR) << "Secure discard failed for: " << target;
@@ -67,6 +93,8 @@
                 PLOG(ERROR) << "Unable to unlink: " << target;
             }
         }
+        set = 0;
+        ioctl(fd, F2FS_IOC_SET_PIN_FILE, &set);
         LOG(DEBUG) << "Discarded: " << target;
     }
     return 0;