summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Harold <nharold@google.com>2017-04-19 11:09:11 -0700
committerNathan Harold <nharold@google.com>2017-04-21 10:08:11 -0700
commit2fb1b127764e23bd14cd74471a4358f2b4c5b3eb (patch)
treeeca7bdf301e5dfb2f5f864e2879e131e737ef27a
parent2dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0 (diff)
downloadnetd-2fb1b127764e23bd14cd74471a4358f2b4c5b3eb.tar.gz
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 Merged-In: Ic08a75d543f92f7fa5e0cf8b4277de12464fd406 Change-Id: Ic08a75d543f92f7fa5e0cf8b4277de12464fd406
-rw-r--r--server/Android.mk8
-rw-r--r--server/XfrmController.cpp2
-rw-r--r--server/XfrmController.h40
3 files changed, 48 insertions, 2 deletions
diff --git a/server/Android.mk b/server/Android.mk
index 0785c23d..10006940 100644
--- a/server/Android.mk
+++ b/server/Android.mk
@@ -52,7 +52,13 @@ LOCAL_SANITIZE := unsigned-integer-overflow
LOCAL_MODULE := netd
# Bug: http://b/29823425 Disable -Wvarargs for Clang update to r271374
-LOCAL_CPPFLAGS += -Wno-varargs
+LOCAL_CPPFLAGS += -Wno-varargs \
+
+ifeq ($(TARGET_ARCH), x86)
+ifneq ($(TARGET_PRODUCT), gce_x86_phone)
+ LOCAL_CPPFLAGS += -D NETLINK_COMPAT32
+endif
+endif
LOCAL_INIT_RC := netd.rc
diff --git a/server/XfrmController.cpp b/server/XfrmController.cpp
index e2cef003..f1e0e239 100644
--- a/server/XfrmController.cpp
+++ b/server/XfrmController.cpp
@@ -209,7 +209,7 @@ public:
};
iov[0].iov_base = &nlMsg;
- iov[0].iov_len = sizeof(nlMsg);
+ iov[0].iov_len = NLMSG_HDRLEN;
for (int i = 0; i < iovLen; ++i) {
nlMsg.nlmsg_len += iov[i].iov_len;
}
diff --git a/server/XfrmController.h b/server/XfrmController.h
index 6e75830d..0f2c95aa 100644
--- a/server/XfrmController.h
+++ b/server/XfrmController.h
@@ -121,6 +121,46 @@ private:
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;