Loading libsysutils/src/NetlinkEvent.cpp +24 −97 Original line number Diff line number Diff line Loading @@ -37,108 +37,44 @@ #include <sys/utsname.h> #include <android-base/parseint.h> #include <bpf/KernelUtils.h> #include <log/log.h> #include <sysutils/NetlinkEvent.h> using android::base::ParseInt; using android::bpf::isKernel64Bit; /* From kernel's net/netfilter/xt_quota2.c */ const int LOCAL_QLOG_NL_EVENT = 112; const int LOCAL_NFLOG_PACKET = NFNL_SUBSYS_ULOG << 8 | NFULNL_MSG_PACKET; /****************************************************************************** * WARNING: HERE BE DRAGONS! * * * * This is here to provide for compatibility with both 32 and 64-bit kernels * * from 32-bit userspace. * * * * The kernel definition of this struct uses types (like long) that are not * * the same across 32-bit and 64-bit builds, and there is no compatibility * * layer to fix it up before it reaches userspace. * * As such we need to detect the bit-ness of the kernel and deal with it. * * * ******************************************************************************/ /* * This is the verbatim kernel declaration from net/netfilter/xt_quota2.c, * it is *NOT* of a well defined layout and is included here for compile * time assertions only. * * It got there from deprecated ipt_ULOG.h to parse QLOG_NL_EVENT. */ #define ULOG_MAC_LEN 80 #define ULOG_PREFIX_LEN 32 typedef struct ulog_packet_msg { unsigned long mark; long timestamp_sec; long timestamp_usec; unsigned int hook; char indev_name[IFNAMSIZ]; char outdev_name[IFNAMSIZ]; size_t data_len; char prefix[ULOG_PREFIX_LEN]; unsigned char mac_len; unsigned char mac[ULOG_MAC_LEN]; unsigned char payload[0]; } ulog_packet_msg_t; // On Linux int is always 32 bits, while sizeof(long) == sizeof(void*), // thus long on a 32-bit Linux kernel is 32-bits, like int always is typedef int long32; typedef unsigned int ulong32; static_assert(sizeof(long32) == 4); static_assert(sizeof(ulong32) == 4); // Here's the same structure definition with the assumption the kernel // is compiled for 32-bits. typedef struct { ulong32 mark; long32 timestamp_sec; long32 timestamp_usec; unsigned int hook; char indev_name[IFNAMSIZ]; char outdev_name[IFNAMSIZ]; ulong32 data_len; char prefix[ULOG_PREFIX_LEN]; unsigned char mac_len; unsigned char mac[ULOG_MAC_LEN]; unsigned char payload[0]; } ulog_packet_msg32_t; // long on a 64-bit kernel is 64-bits with 64-bit alignment, // while long long is 64-bit but may have 32-bit aligment. // 'long' on a 32-bit kernel is 32-bits with 32-bit alignment, // and on a 64-bit kernel is 64-bits with 64-bit alignment, // while 'long long' is always 64-bit it may have 32-bit aligment (x86 structs). typedef long long __attribute__((__aligned__(8))) long64; typedef unsigned long long __attribute__((__aligned__(8))) ulong64; static_assert(sizeof(long64) == 8); static_assert(sizeof(ulong64) == 8); // Here's the same structure definition with the assumption the kernel // is compiled for 64-bits. // From kernel's net/netfilter/xt_quota2.c // It got there from deprecated ipt_ULOG.h to parse QLOG_NL_EVENT. constexpr int LOCAL_QLOG_NL_EVENT = 112; constexpr int LOCAL_NFLOG_PACKET = NFNL_SUBSYS_ULOG << 8 | NFULNL_MSG_PACKET; constexpr int ULOG_MAC_LEN = 80; constexpr int ULOG_PREFIX_LEN = 32; // This structure layout assumes we're running on a 64-bit kernel. typedef struct { ulong64 mark; long64 timestamp_sec; long64 timestamp_usec; ulong64 mark; // kernel: unsigned long long64 timestamp_sec; // kernel: long long64 timestamp_usec; // kernel: long unsigned int hook; char indev_name[IFNAMSIZ]; char outdev_name[IFNAMSIZ]; ulong64 data_len; ulong64 data_len; // kernel: size_t, a.k.a. unsigned long char prefix[ULOG_PREFIX_LEN]; unsigned char mac_len; unsigned char mac[ULOG_MAC_LEN]; unsigned char payload[0]; } ulog_packet_msg64_t; // One expects the 32-bit version to be smaller than the 64-bit version. static_assert(sizeof(ulog_packet_msg32_t) < sizeof(ulog_packet_msg64_t)); // And either way the 'native' version should match either the 32 or 64 bit one. static_assert(sizeof(ulog_packet_msg_t) == sizeof(ulog_packet_msg32_t) || sizeof(ulog_packet_msg_t) == sizeof(ulog_packet_msg64_t)); } ulog_packet_msg_t; // In practice these sizes are always simply (for both x86 and arm): static_assert(sizeof(ulog_packet_msg32_t) == 168); static_assert(sizeof(ulog_packet_msg64_t) == 192); // In practice, for both x86 and arm, we have static_assert(sizeof(ulog_packet_msg_t) == 192); /******************************************************************************/ Loading Loading @@ -356,20 +292,11 @@ bool NetlinkEvent::parseIfAddrMessage(const struct nlmsghdr *nh) { * Parse a QLOG_NL_EVENT message. */ bool NetlinkEvent::parseUlogPacketMessage(const struct nlmsghdr *nh) { const char* alert; const char* devname; if (isKernel64Bit()) { ulog_packet_msg64_t* pm64 = (ulog_packet_msg64_t*)NLMSG_DATA(nh); if (!checkRtNetlinkLength(nh, sizeof(*pm64))) return false; alert = pm64->prefix; devname = pm64->indev_name[0] ? pm64->indev_name : pm64->outdev_name; } else { ulog_packet_msg32_t* pm32 = (ulog_packet_msg32_t*)NLMSG_DATA(nh); if (!checkRtNetlinkLength(nh, sizeof(*pm32))) return false; alert = pm32->prefix; devname = pm32->indev_name[0] ? pm32->indev_name : pm32->outdev_name; } ulog_packet_msg_t* pm = (ulog_packet_msg_t*)NLMSG_DATA(nh); if (!checkRtNetlinkLength(nh, sizeof(*pm))) return false; const char* alert = pm->prefix; const char* devname = pm->indev_name[0] ? pm->indev_name : pm->outdev_name; asprintf(&mParams[0], "ALERT_NAME=%s", alert); asprintf(&mParams[1], "INTERFACE=%s", devname); Loading Loading
libsysutils/src/NetlinkEvent.cpp +24 −97 Original line number Diff line number Diff line Loading @@ -37,108 +37,44 @@ #include <sys/utsname.h> #include <android-base/parseint.h> #include <bpf/KernelUtils.h> #include <log/log.h> #include <sysutils/NetlinkEvent.h> using android::base::ParseInt; using android::bpf::isKernel64Bit; /* From kernel's net/netfilter/xt_quota2.c */ const int LOCAL_QLOG_NL_EVENT = 112; const int LOCAL_NFLOG_PACKET = NFNL_SUBSYS_ULOG << 8 | NFULNL_MSG_PACKET; /****************************************************************************** * WARNING: HERE BE DRAGONS! * * * * This is here to provide for compatibility with both 32 and 64-bit kernels * * from 32-bit userspace. * * * * The kernel definition of this struct uses types (like long) that are not * * the same across 32-bit and 64-bit builds, and there is no compatibility * * layer to fix it up before it reaches userspace. * * As such we need to detect the bit-ness of the kernel and deal with it. * * * ******************************************************************************/ /* * This is the verbatim kernel declaration from net/netfilter/xt_quota2.c, * it is *NOT* of a well defined layout and is included here for compile * time assertions only. * * It got there from deprecated ipt_ULOG.h to parse QLOG_NL_EVENT. */ #define ULOG_MAC_LEN 80 #define ULOG_PREFIX_LEN 32 typedef struct ulog_packet_msg { unsigned long mark; long timestamp_sec; long timestamp_usec; unsigned int hook; char indev_name[IFNAMSIZ]; char outdev_name[IFNAMSIZ]; size_t data_len; char prefix[ULOG_PREFIX_LEN]; unsigned char mac_len; unsigned char mac[ULOG_MAC_LEN]; unsigned char payload[0]; } ulog_packet_msg_t; // On Linux int is always 32 bits, while sizeof(long) == sizeof(void*), // thus long on a 32-bit Linux kernel is 32-bits, like int always is typedef int long32; typedef unsigned int ulong32; static_assert(sizeof(long32) == 4); static_assert(sizeof(ulong32) == 4); // Here's the same structure definition with the assumption the kernel // is compiled for 32-bits. typedef struct { ulong32 mark; long32 timestamp_sec; long32 timestamp_usec; unsigned int hook; char indev_name[IFNAMSIZ]; char outdev_name[IFNAMSIZ]; ulong32 data_len; char prefix[ULOG_PREFIX_LEN]; unsigned char mac_len; unsigned char mac[ULOG_MAC_LEN]; unsigned char payload[0]; } ulog_packet_msg32_t; // long on a 64-bit kernel is 64-bits with 64-bit alignment, // while long long is 64-bit but may have 32-bit aligment. // 'long' on a 32-bit kernel is 32-bits with 32-bit alignment, // and on a 64-bit kernel is 64-bits with 64-bit alignment, // while 'long long' is always 64-bit it may have 32-bit aligment (x86 structs). typedef long long __attribute__((__aligned__(8))) long64; typedef unsigned long long __attribute__((__aligned__(8))) ulong64; static_assert(sizeof(long64) == 8); static_assert(sizeof(ulong64) == 8); // Here's the same structure definition with the assumption the kernel // is compiled for 64-bits. // From kernel's net/netfilter/xt_quota2.c // It got there from deprecated ipt_ULOG.h to parse QLOG_NL_EVENT. constexpr int LOCAL_QLOG_NL_EVENT = 112; constexpr int LOCAL_NFLOG_PACKET = NFNL_SUBSYS_ULOG << 8 | NFULNL_MSG_PACKET; constexpr int ULOG_MAC_LEN = 80; constexpr int ULOG_PREFIX_LEN = 32; // This structure layout assumes we're running on a 64-bit kernel. typedef struct { ulong64 mark; long64 timestamp_sec; long64 timestamp_usec; ulong64 mark; // kernel: unsigned long long64 timestamp_sec; // kernel: long long64 timestamp_usec; // kernel: long unsigned int hook; char indev_name[IFNAMSIZ]; char outdev_name[IFNAMSIZ]; ulong64 data_len; ulong64 data_len; // kernel: size_t, a.k.a. unsigned long char prefix[ULOG_PREFIX_LEN]; unsigned char mac_len; unsigned char mac[ULOG_MAC_LEN]; unsigned char payload[0]; } ulog_packet_msg64_t; // One expects the 32-bit version to be smaller than the 64-bit version. static_assert(sizeof(ulog_packet_msg32_t) < sizeof(ulog_packet_msg64_t)); // And either way the 'native' version should match either the 32 or 64 bit one. static_assert(sizeof(ulog_packet_msg_t) == sizeof(ulog_packet_msg32_t) || sizeof(ulog_packet_msg_t) == sizeof(ulog_packet_msg64_t)); } ulog_packet_msg_t; // In practice these sizes are always simply (for both x86 and arm): static_assert(sizeof(ulog_packet_msg32_t) == 168); static_assert(sizeof(ulog_packet_msg64_t) == 192); // In practice, for both x86 and arm, we have static_assert(sizeof(ulog_packet_msg_t) == 192); /******************************************************************************/ Loading Loading @@ -356,20 +292,11 @@ bool NetlinkEvent::parseIfAddrMessage(const struct nlmsghdr *nh) { * Parse a QLOG_NL_EVENT message. */ bool NetlinkEvent::parseUlogPacketMessage(const struct nlmsghdr *nh) { const char* alert; const char* devname; if (isKernel64Bit()) { ulog_packet_msg64_t* pm64 = (ulog_packet_msg64_t*)NLMSG_DATA(nh); if (!checkRtNetlinkLength(nh, sizeof(*pm64))) return false; alert = pm64->prefix; devname = pm64->indev_name[0] ? pm64->indev_name : pm64->outdev_name; } else { ulog_packet_msg32_t* pm32 = (ulog_packet_msg32_t*)NLMSG_DATA(nh); if (!checkRtNetlinkLength(nh, sizeof(*pm32))) return false; alert = pm32->prefix; devname = pm32->indev_name[0] ? pm32->indev_name : pm32->outdev_name; } ulog_packet_msg_t* pm = (ulog_packet_msg_t*)NLMSG_DATA(nh); if (!checkRtNetlinkLength(nh, sizeof(*pm))) return false; const char* alert = pm->prefix; const char* devname = pm->indev_name[0] ? pm->indev_name : pm->outdev_name; asprintf(&mParams[0], "ALERT_NAME=%s", alert); asprintf(&mParams[1], "INTERFACE=%s", devname); Loading