FirewallController: discover max uid in the current user namespace

This patch gives the capability to FirewallController to discover the
maximum valid uid in the user namespace in which netd is currently
running, and uses that value in the whitelist uid rules.

This is done by parsing the content of /proc/self/uid_map as explained
in the man page of 'user_namespaces'.

On the default root namespace the maximum uid is expected to be
UINT32_MAX - 1, but this assumption is incorrect in other user
namespaces created for instance for container environments.

The uid mapping is de facto constant from within the user namespace and
cannot be modified from inside (more precisely uid_map and gid_map proc
files can only be written once each for a new user namespacE).

netd makes the assumption that the uid mapping stays constant, meaning
it is a bug if the host namespace tries to remap uids after netd starts.

Bug: 110459356
Test: - built,
      - flashed and booted a marlin, 'fw_powersave' rule is as expected
      - flashed and booted ARC++ container, 'fw_powersave' rule is as
        expected
      - new unit tests pass
Change-Id: I44a885c34e174b0067848b860be8d7b8f3e83296
diff --git a/server/FirewallController.h b/server/FirewallController.h
index 9b0c013..c43e94e 100644
--- a/server/FirewallController.h
+++ b/server/FirewallController.h
@@ -17,6 +17,7 @@
 #ifndef _FIREWALL_CONTROLLER_H
 #define _FIREWALL_CONTROLLER_H
 
+#include <sys/types.h>
 #include <mutex>
 #include <set>
 #include <string>
@@ -61,6 +62,7 @@
     int replaceUidChain(const std::string&, bool, const std::vector<int32_t>&);
 
     static std::string makeCriticalCommands(IptablesTarget target, const char* chainName);
+    static uid_t discoverMaximumValidUid(const std::string& fileName);
 
     static const char* TABLE;
 
@@ -83,13 +85,19 @@
     static int (*execIptablesRestore)(IptablesTarget target, const std::string& commands);
 
 private:
-    FirewallType mFirewallType;
-    bool mUseBpfOwnerMatch;
-    std::set<std::string> mIfaceRules;
-    int attachChain(const char*, const char*);
-    int detachChain(const char*, const char*);
-    int createChain(const char*, FirewallType);
-    FirewallType getFirewallType(ChildChain);
+  // Netd supports two cases, in both of which mMaxUid that derives from the uid mapping is const:
+  //  - netd runs in a root namespace which contains all UIDs.
+  //  - netd runs in a user namespace where the uid mapping is written once before netd starts.
+  //    In that case, an attempt to write more than once to a uid_map file in a user namespace
+  //    fails with EPERM. Netd can therefore assumes the max valid uid to be const.
+  const uid_t mMaxUid;
+  FirewallType mFirewallType;
+  bool mUseBpfOwnerMatch;
+  std::set<std::string> mIfaceRules;
+  int attachChain(const char*, const char*);
+  int detachChain(const char*, const char*);
+  int createChain(const char*, FirewallType);
+  FirewallType getFirewallType(ChildChain);
 };
 
 #endif