net: Add snapshot of sockev module

This is a snapshot of the sockev module taken as of msm-4.4
commit 33193859886dd87 ("net: core: Send only BIND and LISTEN events.").

Added module which subscribes to socket notifier events. Notifier events
are then converted to a multicast netlink message for user space
applications to consume.

net: core: null pointer derefernce in sockev_client_cb

sockev_client_cb creates a netlink message and populates
the nlmsg_data using the socket->sock information.
If socket is closed, while the nlmsg_data is being
populated, a null pointer dereference occurs.

BUG: KASAN: null-ptr-deref in sockev_client_cb+0x1e4/0x310 net/core/sockev_nlmcast.c:98
Read of size 2 at addr 0000000000000010 by task syz-executor/9398
CPU: 6 PID: 9398 Comm: syz-executor Tainted: G W O 4.9.92+ #1

Call trace:
[<ffffff94e2bebec4>] sockev_client_cb+0x1e4/0x310 net/core/sockev_nlmcast.c:98
[<ffffff94e14fb20c>] notifier_call_chain+0x94/0xe0 kernel/notifier.c:93
[<ffffff94e14fb894>] __blocking_notifier_call_chain+0x6c/0xb8 kernel/notifier.c:317
[<ffffff94e14fb920>] blocking_notifier_call_chain+0x40/0x50 kernel/notifier.c:328
[<ffffff94e2b727f8>] sockev_notify net/socket.c:180 [inline]
[<ffffff94e2b727f8>] SYSC_listen net/socket.c:1446 [inline]
[<ffffff94e2b727f8>] SyS_listen+0x1e0/0x1f8 net/socket.c:1428
[<ffffff94e1483f70>] el0_svc_naked+0x24/0x28

net: sockev: fix uninitialized data leak into userspace

Socket event string, notifying userspace of socket event, can leak
data into userspace. Memset it before filling it using strlcpy.

net: memset smsg to avoid the padding data

memset smsg to avoid the padding data of kernel to be shared
with user space. Fix is to set fields event to all "0", but there is
actually 6 bytes padding between "sktype" and "skflags", so memset was
done to set all the padding bits to 0.

CRs-Fixed: 1078373
Change-Id: I435486b80ad19c5fa54b098680623e7a4f080198
Acked-by: Manoj Basapathi <manojbm@qti.qualcomm.com>
Signed-off-by: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
Signed-off-by: Tejaswi Tanikella <tejaswit@codeaurora.org>
Signed-off-by: Sauvik Saha <ssaha@codeaurora.org>
This commit is contained in:
Sauvik Saha 2017-02-13 12:21:01 -07:00
parent 8c640de57d
commit c76c5f058f
6 changed files with 181 additions and 1 deletions

View File

@ -18,3 +18,4 @@ ifneq ($(VSERVICES_SUPPORT), "")
include include/linux/Kbuild.vservices
endif
header-y += okl4-link-shbuf.h
header-y += sockev.h

View File

@ -29,7 +29,7 @@
#define NETLINK_RDMA 20
#define NETLINK_CRYPTO 21 /* Crypto layer */
#define NETLINK_SMC 22 /* SMC monitoring */
#define NETLINK_SOCKEV 23 /* Socket Administrative Events */
#define NETLINK_INET_DIAG NETLINK_SOCK_DIAG
#define MAX_LINKS 32

View File

@ -0,0 +1,33 @@
/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
#ifndef _SOCKEV_H_
#define _SOCKEV_H_
#include <linux/types.h>
#include <linux/netlink.h>
#include <linux/socket.h>
enum sknetlink_groups {
SKNLGRP_UNICAST,
SKNLGRP_SOCKEV,
__SKNLGRP_MAX
};
#define SOCKEV_STR_MAX 32
/********************************************************************
* Socket operation messages
****/
struct sknlsockevmsg {
__u8 event[SOCKEV_STR_MAX];
__u32 pid; /* (struct task_struct*)->pid */
__u16 skfamily; /* (struct socket*)->sk->sk_family */
__u8 skstate; /* (struct socket*)->sk->sk_state */
__u8 skprotocol; /* (struct socket*)->sk->sk_protocol */
__u16 sktype; /* (struct socket*)->sk->sk_type */
__u64 skflags; /* (struct socket*)->sk->sk_flags */
};
#endif /* _SOCKEV_H_ */

View File

@ -329,6 +329,15 @@ config NET_FLOW_LIMIT
with many clients some protection against DoS by a single (spoofed)
flow that greatly exceeds average workload.
config SOCKEV_NLMCAST
bool "Enable SOCKEV Netlink Multicast"
default n
help
Default client for SOCKEV notifier events. Sends multicast netlink
messages whenever the socket event notifier is invoked. Enable if
user space entities need to be notified of socket events without
having to poll /proc
menu "Network testing"
config NET_PKTGEN

View File

@ -27,6 +27,7 @@ obj-$(CONFIG_CGROUP_NET_PRIO) += netprio_cgroup.o
obj-$(CONFIG_CGROUP_NET_CLASSID) += netclassid_cgroup.o
obj-$(CONFIG_LWTUNNEL) += lwtunnel.o
obj-$(CONFIG_LWTUNNEL_BPF) += lwt_bpf.o
obj-$(CONFIG_SOCKEV_NLMCAST) += sockev_nlmcast.o
obj-$(CONFIG_DST_CACHE) += dst_cache.o
obj-$(CONFIG_HWBM) += hwbm.o
obj-$(CONFIG_NET_DEVLINK) += devlink.o

136
net/core/sockev_nlmcast.c Normal file
View File

@ -0,0 +1,136 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2014-2015, 2017-2019, The Linux Foundation. All rights reserved. */
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/export.h>
#include <linux/netlink.h>
#include <linux/sockev.h>
#include <net/sock.h>
static int registration_status;
static struct sock *socknlmsgsk;
static void sockev_skmsg_recv(struct sk_buff *skb)
{
pr_debug("%s(): Got unsolicited request\n", __func__);
}
static struct netlink_kernel_cfg nlcfg = {
.input = sockev_skmsg_recv
};
static void _sockev_event(unsigned long event, __u8 *evstr, int buflen)
{
switch (event) {
case SOCKEV_SOCKET:
strlcpy(evstr, "SOCKEV_SOCKET", buflen);
break;
case SOCKEV_BIND:
strlcpy(evstr, "SOCKEV_BIND", buflen);
break;
case SOCKEV_LISTEN:
strlcpy(evstr, "SOCKEV_LISTEN", buflen);
break;
case SOCKEV_ACCEPT:
strlcpy(evstr, "SOCKEV_ACCEPT", buflen);
break;
case SOCKEV_CONNECT:
strlcpy(evstr, "SOCKEV_CONNECT", buflen);
break;
case SOCKEV_SHUTDOWN:
strlcpy(evstr, "SOCKEV_SHUTDOWN", buflen);
break;
default:
strlcpy(evstr, "UNKNOWN", buflen);
}
}
static int sockev_client_cb(struct notifier_block *nb,
unsigned long event, void *data)
{
struct sk_buff *skb;
struct nlmsghdr *nlh;
struct sknlsockevmsg *smsg;
struct socket *sock;
struct sock *sk;
sock = (struct socket *)data;
if (!socknlmsgsk || !sock)
goto done;
sk = sock->sk;
if (!sk)
goto done;
if (sk->sk_family != AF_INET && sk->sk_family != AF_INET6)
goto done;
if (event != SOCKEV_BIND && event != SOCKEV_LISTEN)
goto done;
skb = nlmsg_new(sizeof(struct sknlsockevmsg), GFP_KERNEL);
if (!skb)
goto done;
nlh = nlmsg_put(skb, 0, 0, event, sizeof(struct sknlsockevmsg), 0);
if (!nlh) {
kfree_skb(skb);
goto done;
}
NETLINK_CB(skb).dst_group = SKNLGRP_SOCKEV;
smsg = nlmsg_data(nlh);
memset(smsg, 0, sizeof(struct sknlsockevmsg));
smsg->pid = current->pid;
_sockev_event(event, smsg->event, sizeof(smsg->event));
smsg->skfamily = sk->sk_family;
smsg->skstate = sk->sk_state;
smsg->skprotocol = sk->sk_protocol;
smsg->sktype = sk->sk_type;
smsg->skflags = sk->sk_flags;
nlmsg_notify(socknlmsgsk, skb, 0, SKNLGRP_SOCKEV, 0, GFP_KERNEL);
done:
return 0;
}
static struct notifier_block sockev_notifier_client = {
.notifier_call = sockev_client_cb,
.next = 0,
.priority = 0
};
/* ***************** Startup/Shutdown *************************************** */
static int __init sockev_client_init(void)
{
int rc;
registration_status = 1;
rc = sockev_register_notify(&sockev_notifier_client);
if (rc != 0) {
registration_status = 0;
pr_err("%s(): Failed to register cb (%d)\n", __func__, rc);
}
socknlmsgsk = netlink_kernel_create(&init_net, NETLINK_SOCKEV, &nlcfg);
if (!socknlmsgsk) {
pr_err("%s(): Failed to initialize netlink socket\n", __func__);
if (registration_status)
sockev_unregister_notify(&sockev_notifier_client);
registration_status = 0;
}
return rc;
}
static void __exit sockev_client_exit(void)
{
if (registration_status)
sockev_unregister_notify(&sockev_notifier_client);
}
module_init(sockev_client_init)
module_exit(sockev_client_exit)
MODULE_LICENSE("GPL v2");