Index: modules/user/user.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/user/user.module,v
retrieving revision 1.1191
diff -u -p -r1.1191 user.module
--- modules/user/user.module	9 Aug 2010 19:49:40 -0000	1.1191
+++ modules/user/user.module	9 Aug 2010 20:18:48 -0000
@@ -3605,9 +3605,34 @@ function user_modules_installed($modules
  * Implements hook_modules_uninstalled().
  */
 function user_modules_uninstalled($modules) {
-   db_delete('role_permission')
-     ->condition('module', $modules, 'IN')
-     ->execute();
+  // Do not remove permissions that are defined by multiple modules.
+  $delete = array();
+  foreach ($modules as $module) {
+    // hook_modules_uninstalled() is not supposed to be invoked via
+    // module_invoke() in uninstalled modules.
+    $function = $module . '_permission';
+    if (function_exists($function)) {
+      $delete += $function();
+    }
+  }
+  // If we have any permissions to delete, iterate over all other modules to
+  // identify uniquely defined permissions; the same permission can be defined
+  // by multiple modules.
+  if (!empty($delete)) {
+    foreach (array_diff(module_implements('permission'), $modules) as $module) {
+      if ($module_permissions = module_invoke($module, 'permission')) {
+        $delete = array_diff_key($delete, $module_permissions);
+      }
+    }
+  }
+  // If any unique permissions are left, delete them.
+  if ($delete) {
+    db_delete('role_permission')
+      ->condition('permission', array_keys($delete))
+      // Extra safety.
+      ->condition('module', $modules)
+      ->execute();
+  }
 }
 
 /**
