Re-derive permissions after package changes.

When packages change, existing package-specific directories may have
gained/lost a UID mapping, so we need to update the permissions for
any in-memory nodes.

This allows an app to deliver data for another package before that
package is installed, which is the typical pattern of how OBB files
are delivered.

Also fix bug by re-deriving permissions when files are moved.

Bug: 25399427
Change-Id: I06f38a24ad7dee5f5099ba81429aef03208e5683
(cherry picked from commit f7aad11c1cc133e352333f83e3abbf323cd41ead)
(cherry picked from commit a44febd19b4efd17fe31d75c964ec47f85832a2a)
diff --git a/sdcard/sdcard.c b/sdcard/sdcard.c
index a79e2dd..06452aa 100644
--- a/sdcard/sdcard.c
+++ b/sdcard/sdcard.c
@@ -507,6 +507,16 @@
     }
 }
 
+static void derive_permissions_recursive_locked(struct fuse* fuse, struct node *parent) {
+    struct node *node;
+    for (node = parent->child; node; node = node->next) {
+        derive_permissions_locked(fuse, parent, node);
+        if (node->child) {
+            derive_permissions_recursive_locked(fuse, node);
+        }
+    }
+}
+
 /* Kernel has already enforced everything we returned through
  * derive_permissions_locked(), so this is used to lock down access
  * even further, such as enforcing that apps hold sdcard_rw. */
@@ -1145,6 +1155,8 @@
     res = rename_node_locked(child_node, new_name, new_actual_name);
     if (!res) {
         remove_node_from_parent_locked(child_node);
+        derive_permissions_locked(fuse, new_parent_node, child_node);
+        derive_permissions_recursive_locked(fuse, child_node);
         add_node_to_parent_locked(child_node, new_parent_node);
     }
     goto done;
@@ -1663,6 +1675,10 @@
     TRACE("read_package_list: found %zu packages\n",
             hashmapSize(global->package_to_appid));
     fclose(file);
+
+    /* Regenerate ownership details using newly loaded mapping */
+    derive_permissions_recursive_locked(global->fuse_default, &global->root);
+
     pthread_mutex_unlock(&global->lock);
     return 0;
 }