diff options
-rw-r--r-- | CleanSpec.mk | 1 | ||||
-rw-r--r-- | include/cutils/uevent.h | 1 | ||||
-rw-r--r-- | include/sysutils/NetlinkEvent.h | 1 | ||||
-rw-r--r-- | include/sysutils/NetlinkListener.h | 1 | ||||
-rw-r--r-- | libcutils/uevent.c | 26 | ||||
-rw-r--r-- | libsysutils/Android.mk | 7 | ||||
-rw-r--r-- | libsysutils/src/NetlinkEvent.cpp | 59 | ||||
-rw-r--r-- | libsysutils/src/NetlinkListener.cpp | 9 |
8 files changed, 86 insertions, 19 deletions
diff --git a/CleanSpec.mk b/CleanSpec.mk index e78fc88..7f9536e 100644 --- a/CleanSpec.mk +++ b/CleanSpec.mk @@ -54,3 +54,4 @@ $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/bin/reboot) $(call add-clean-step, rm -rf $(PRODUCT_OUT)/root/default.prop) $(call add-clean-step, rm -rf $(PRODUCT_OUT)/recovery/root/default.prop) $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/lmkd_intermediates/import_includes) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libsysutils_intermediates/import_includes) diff --git a/include/cutils/uevent.h b/include/cutils/uevent.h index 4cca7e5..da1c2aa 100644 --- a/include/cutils/uevent.h +++ b/include/cutils/uevent.h @@ -27,6 +27,7 @@ extern "C" { int uevent_open_socket(int buf_sz, bool passcred); ssize_t uevent_kernel_multicast_recv(int socket, void *buffer, size_t length); ssize_t uevent_kernel_multicast_uid_recv(int socket, void *buffer, size_t length, uid_t *uid); +ssize_t uevent_kernel_recv(int socket, void *buffer, size_t length, bool require_group, uid_t *uid); #ifdef __cplusplus } diff --git a/include/sysutils/NetlinkEvent.h b/include/sysutils/NetlinkEvent.h index c345cdb..4fa49c5 100644 --- a/include/sysutils/NetlinkEvent.h +++ b/include/sysutils/NetlinkEvent.h @@ -57,6 +57,7 @@ public: bool parseIfInfoMessage(const struct nlmsghdr *nh); bool parseIfAddrMessage(const struct nlmsghdr *nh); bool parseUlogPacketMessage(const struct nlmsghdr *nh); + bool parseNfPacketMessage(struct nlmsghdr *nh); bool parseRtMessage(const struct nlmsghdr *nh); bool parseNdUserOptMessage(const struct nlmsghdr *nh); }; diff --git a/include/sysutils/NetlinkListener.h b/include/sysutils/NetlinkListener.h index 6e52c3b..82465d6 100644 --- a/include/sysutils/NetlinkListener.h +++ b/include/sysutils/NetlinkListener.h @@ -27,6 +27,7 @@ class NetlinkListener : public SocketListener { public: static const int NETLINK_FORMAT_ASCII = 0; static const int NETLINK_FORMAT_BINARY = 1; + static const int NETLINK_FORMAT_BINARY_UNICAST = 2; #if 1 /* temporary version until we can get Motorola to update their diff --git a/libcutils/uevent.c b/libcutils/uevent.c index 97a81e3..827170a 100644 --- a/libcutils/uevent.c +++ b/libcutils/uevent.c @@ -31,12 +31,12 @@ */ ssize_t uevent_kernel_multicast_recv(int socket, void *buffer, size_t length) { - uid_t user = -1; - return uevent_kernel_multicast_uid_recv(socket, buffer, length, &user); + uid_t uid = -1; + return uevent_kernel_multicast_uid_recv(socket, buffer, length, &uid); } /** - * Like the above, but passes a uid_t in by reference. In the event that this + * Like the above, but passes a uid_t in by pointer. In the event that this * fails due to a bad uid check, the uid_t will be set to the uid of the * socket's peer. * @@ -44,8 +44,12 @@ ssize_t uevent_kernel_multicast_recv(int socket, void *buffer, size_t length) * returns -1, sets errno to EIO, and sets "user" to the UID associated with the * message. If the peer UID cannot be determined, "user" is set to -1." */ -ssize_t uevent_kernel_multicast_uid_recv(int socket, void *buffer, - size_t length, uid_t *user) +ssize_t uevent_kernel_multicast_uid_recv(int socket, void *buffer, size_t length, uid_t *uid) +{ + return uevent_kernel_recv(socket, buffer, length, true, uid); +} + +ssize_t uevent_kernel_recv(int socket, void *buffer, size_t length, bool require_group, uid_t *uid) { struct iovec iov = { buffer, length }; struct sockaddr_nl addr; @@ -60,7 +64,7 @@ ssize_t uevent_kernel_multicast_uid_recv(int socket, void *buffer, 0, }; - *user = -1; + *uid = -1; ssize_t n = recvmsg(socket, &hdr, 0); if (n <= 0) { return n; @@ -73,14 +77,18 @@ ssize_t uevent_kernel_multicast_uid_recv(int socket, void *buffer, } struct ucred *cred = (struct ucred *)CMSG_DATA(cmsg); - *user = cred->uid; + *uid = cred->uid; if (cred->uid != 0) { /* ignoring netlink message from non-root user */ goto out; } - if (addr.nl_groups == 0 || addr.nl_pid != 0) { - /* ignoring non-kernel or unicast netlink message */ + if (addr.nl_pid != 0) { + /* ignore non-kernel */ + goto out; + } + if (require_group && addr.nl_groups == 0) { + /* ignore unicast messages when requested */ goto out; } diff --git a/libsysutils/Android.mk b/libsysutils/Android.mk index 246f954..b902a81 100644 --- a/libsysutils/Android.mk +++ b/libsysutils/Android.mk @@ -16,11 +16,12 @@ LOCAL_SRC_FILES:= \ LOCAL_MODULE:= libsysutils -LOCAL_C_INCLUDES := - LOCAL_CFLAGS := -Werror -LOCAL_SHARED_LIBRARIES := libcutils liblog +LOCAL_SHARED_LIBRARIES := \ + libcutils \ + liblog \ + libnl include $(BUILD_SHARED_LIBRARY) diff --git a/libsysutils/src/NetlinkEvent.cpp b/libsysutils/src/NetlinkEvent.cpp index 9d596ef..909df86 100644 --- a/libsysutils/src/NetlinkEvent.cpp +++ b/libsysutils/src/NetlinkEvent.cpp @@ -32,13 +32,21 @@ #include <linux/if_addr.h> #include <linux/if_link.h> #include <linux/netfilter/nfnetlink.h> +#include <linux/netfilter/nfnetlink_log.h> #include <linux/netfilter_ipv4/ipt_ULOG.h> + /* From kernel's net/netfilter/xt_quota2.c */ -const int QLOG_NL_EVENT = 112; +const int LOCAL_QLOG_NL_EVENT = 112; +const int LOCAL_NFLOG_PACKET = NFNL_SUBSYS_ULOG << 8 | NFULNL_MSG_PACKET; #include <linux/netlink.h> #include <linux/rtnetlink.h> +#include <netlink/attr.h> +#include <netlink/genl/genl.h> +#include <netlink/handlers.h> +#include <netlink/msg.h> + const int NetlinkEvent::NlActionUnknown = 0; const int NetlinkEvent::NlActionAdd = 1; const int NetlinkEvent::NlActionRemove = 2; @@ -95,7 +103,8 @@ static const char *rtMessageName(int type) { NL_EVENT_RTM_NAME(RTM_NEWROUTE); NL_EVENT_RTM_NAME(RTM_DELROUTE); NL_EVENT_RTM_NAME(RTM_NEWNDUSEROPT); - NL_EVENT_RTM_NAME(QLOG_NL_EVENT); + NL_EVENT_RTM_NAME(LOCAL_QLOG_NL_EVENT); + NL_EVENT_RTM_NAME(LOCAL_NFLOG_PACKET); default: return NULL; } @@ -272,6 +281,41 @@ bool NetlinkEvent::parseUlogPacketMessage(const struct nlmsghdr *nh) { } /* + * Parse a LOCAL_NFLOG_PACKET message. + */ +bool NetlinkEvent::parseNfPacketMessage(struct nlmsghdr *nh) { + int uid = -1; + int len = 0; + char* raw = NULL; + + struct nlattr *uid_attr = nlmsg_find_attr(nh, sizeof(struct genlmsghdr), NFULA_UID); + if (uid_attr) { + uid = ntohl(nla_get_u32(uid_attr)); + } + + struct nlattr *payload = nlmsg_find_attr(nh, sizeof(struct genlmsghdr), NFULA_PAYLOAD); + if (payload) { + /* First 256 bytes is plenty */ + len = nla_len(payload); + if (len > 256) len = 256; + raw = (char*) nla_data(payload); + } + + char* hex = (char*) calloc(1, 5 + (len * 2)); + strcpy(hex, "HEX="); + for (int i = 0; i < len; i++) { + hex[4 + (i * 2)] = "0123456789abcdef"[(raw[i] >> 4) & 0xf]; + hex[5 + (i * 2)] = "0123456789abcdef"[raw[i] & 0xf]; + } + + asprintf(&mParams[0], "UID=%d", uid); + mParams[1] = hex; + mSubsystem = strdup("strict"); + mAction = NlActionChange; + return true; +} + +/* * Parse a RTM_NEWROUTE or RTM_DELROUTE message. */ bool NetlinkEvent::parseRtMessage(const struct nlmsghdr *nh) { @@ -478,7 +522,7 @@ bool NetlinkEvent::parseNdUserOptMessage(const struct nlmsghdr *nh) { * TODO: consider only ever looking at the first message. */ bool NetlinkEvent::parseBinaryNetlinkMessage(char *buffer, int size) { - const struct nlmsghdr *nh; + struct nlmsghdr *nh; for (nh = (struct nlmsghdr *) buffer; NLMSG_OK(nh, (unsigned) size) && (nh->nlmsg_type != NLMSG_DONE); @@ -493,7 +537,7 @@ bool NetlinkEvent::parseBinaryNetlinkMessage(char *buffer, int size) { if (parseIfInfoMessage(nh)) return true; - } else if (nh->nlmsg_type == QLOG_NL_EVENT) { + } else if (nh->nlmsg_type == LOCAL_QLOG_NL_EVENT) { if (parseUlogPacketMessage(nh)) return true; @@ -511,6 +555,10 @@ bool NetlinkEvent::parseBinaryNetlinkMessage(char *buffer, int size) { if (parseNdUserOptMessage(nh)) return true; + } else if (nh->nlmsg_type == LOCAL_NFLOG_PACKET) { + if (parseNfPacketMessage(nh)) + return true; + } } @@ -588,7 +636,8 @@ bool NetlinkEvent::parseAsciiNetlinkMessage(char *buffer, int size) { } bool NetlinkEvent::decode(char *buffer, int size, int format) { - if (format == NetlinkListener::NETLINK_FORMAT_BINARY) { + if (format == NetlinkListener::NETLINK_FORMAT_BINARY + || format == NetlinkListener::NETLINK_FORMAT_BINARY_UNICAST) { return parseBinaryNetlinkMessage(buffer, size); } else { return parseAsciiNetlinkMessage(buffer, size); diff --git a/libsysutils/src/NetlinkListener.cpp b/libsysutils/src/NetlinkListener.cpp index 81c5cc2..637aa1e 100644 --- a/libsysutils/src/NetlinkListener.cpp +++ b/libsysutils/src/NetlinkListener.cpp @@ -47,8 +47,13 @@ bool NetlinkListener::onDataAvailable(SocketClient *cli) ssize_t count; uid_t uid = -1; - count = TEMP_FAILURE_RETRY(uevent_kernel_multicast_uid_recv( - socket, mBuffer, sizeof(mBuffer), &uid)); + bool require_group = true; + if (mFormat == NETLINK_FORMAT_BINARY_UNICAST) { + require_group = false; + } + + count = TEMP_FAILURE_RETRY(uevent_kernel_recv(socket, + mBuffer, sizeof(mBuffer), require_group, &uid)); if (count < 0) { if (uid > 0) LOG_EVENT_INT(65537, uid); |