Fix ABI incompatibility for Netlink XFRM on Fugu

Fugu is compiled with an x86 userspace and an x86_64
kernel. This means that there is no guarantee of ABI
compatibility between the kernel and userspace. The
xfrm_usersa_info struct is one such place where the
compatibility happens to not exist due to struct
alignment differences. This CL patches the
xfrm_usersa_info struct to match the kernel's 64-bit
alignment in at least the case of x86 vs x86_64.

Bug: 37252170
Test: CTS - IpSecManagerTest passes
Change-Id: Ic08a75d543f92f7fa5e0cf8b4277de12464fd406
diff --git a/server/XfrmController.h b/server/XfrmController.h
index 6e75830..0f2c95a 100644
--- a/server/XfrmController.h
+++ b/server/XfrmController.h
@@ -121,6 +121,46 @@
 
     static constexpr size_t MAX_ALGO_LENGTH = 128;
 
+/*
+ * Below is a redefinition of the xfrm_usersa_info struct that is part
+ * of the Linux uapi <linux/xfrm.h> to align the structures to a 64-bit
+ * boundary.
+ */
+#ifdef NETLINK_COMPAT32
+    // Shadow the kernel definition of xfrm_usersa_info with a 64-bit aligned version
+    struct xfrm_usersa_info : ::xfrm_usersa_info {
+    } __attribute__((aligned(8)));
+    // Shadow the kernel's version, using the aligned version of xfrm_usersa_info
+    struct xfrm_userspi_info {
+        struct xfrm_usersa_info info;
+        __u32 min;
+        __u32 max;
+    };
+
+    /*
+     * Anyone who encounters a failure when sending netlink messages should look here
+     * first. Hitting the static_assert() below should be a strong hint that Android
+     * IPsec will probably not work with your current settings.
+     *
+     * Again, experimentally determined, the "flags" field should be the first byte in
+     * the final word of the xfrm_usersa_info struct. The check validates the size of
+     * the padding to be 7.
+     *
+     * This padding is verified to be correct on gcc/x86_64 kernel, and clang/x86 userspace.
+     */
+    static_assert(sizeof(::xfrm_usersa_info) % 8 != 0, "struct xfrm_usersa_info has changed "
+                                                       "alignment. Please consider whether this "
+                                                       "patch is needed.");
+    static_assert(sizeof(xfrm_usersa_info) - offsetof(xfrm_usersa_info, flags) == 8,
+                  "struct xfrm_usersa_info probably misaligned with kernel struct.");
+    static_assert(sizeof(xfrm_usersa_info) % 8 == 0, "struct xfrm_usersa_info_t is not 64-bit  "
+                                                     "aligned. Please consider whether this patch "
+                                                     "is needed.");
+    static_assert(sizeof(::xfrm_userspi_info) - sizeof(::xfrm_usersa_info) ==
+                      sizeof(xfrm_userspi_info) - sizeof(xfrm_usersa_info),
+                  "struct xfrm_userspi_info has changed and does not match the kernel struct.");
+#endif
+
     struct nlattr_algo_crypt {
         nlattr hdr;
         xfrm_algo crypt;