net: socket: Added notifier chains for socket administrative functions
Allows other areas in the kernel to register notifier callbacks which get invoked whenever something performs an administrative action on a socket. This patch adds hooks in socket(), bind(), listen(), accept(), shutdown(). CRs-Fixed: 626021 Change-Id: I4ae99cb2206d7c4eddba69757335c18d10143045 Signed-off-by: Harout Hedeshian <harouth@codeaurora.org>
This commit is contained in:
parent
f24aee9af1
commit
5886b0b593
|
@ -2261,4 +2261,15 @@ extern int sysctl_optmem_max;
|
|||
extern __u32 sysctl_wmem_default;
|
||||
extern __u32 sysctl_rmem_default;
|
||||
|
||||
/* SOCKEV Notifier Events */
|
||||
#define SOCKEV_SOCKET 0x00
|
||||
#define SOCKEV_BIND 0x01
|
||||
#define SOCKEV_LISTEN 0x02
|
||||
#define SOCKEV_ACCEPT 0x03
|
||||
#define SOCKEV_CONNECT 0x04
|
||||
#define SOCKEV_SHUTDOWN 0x05
|
||||
|
||||
int sockev_register_notify(struct notifier_block *nb);
|
||||
int sockev_unregister_notify(struct notifier_block *nb);
|
||||
|
||||
#endif /* _SOCK_H */
|
||||
|
|
35
net/socket.c
35
net/socket.c
|
@ -105,6 +105,8 @@
|
|||
#include <linux/sockios.h>
|
||||
#include <linux/atalk.h>
|
||||
|
||||
static BLOCKING_NOTIFIER_HEAD(sockev_notifier_list);
|
||||
|
||||
static int sock_no_open(struct inode *irrelevant, struct file *dontcare);
|
||||
static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov,
|
||||
unsigned long nr_segs, loff_t pos);
|
||||
|
@ -165,6 +167,14 @@ static const struct net_proto_family __rcu *net_families[NPROTO] __read_mostly;
|
|||
static DEFINE_PER_CPU(int, sockets_in_use);
|
||||
|
||||
/*
|
||||
* Socket Event framework helpers
|
||||
*/
|
||||
static void sockev_notify(unsigned long event, struct socket *sk)
|
||||
{
|
||||
blocking_notifier_call_chain(&sockev_notifier_list, event, sk);
|
||||
}
|
||||
|
||||
/**
|
||||
* Support routines.
|
||||
* Move socket addresses back and forth across the kernel/user
|
||||
* divide and look after the messy bits.
|
||||
|
@ -1382,6 +1392,9 @@ SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
|
|||
if (retval < 0)
|
||||
goto out;
|
||||
|
||||
if (retval == 0)
|
||||
sockev_notify(SOCKEV_SOCKET, sock);
|
||||
|
||||
retval = sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));
|
||||
if (retval < 0)
|
||||
goto out_release;
|
||||
|
@ -1514,6 +1527,8 @@ SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen)
|
|||
&address, addrlen);
|
||||
}
|
||||
fput_light(sock->file, fput_needed);
|
||||
if (!err)
|
||||
sockev_notify(SOCKEV_BIND, sock);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
@ -1541,6 +1556,8 @@ SYSCALL_DEFINE2(listen, int, fd, int, backlog)
|
|||
err = sock->ops->listen(sock, backlog);
|
||||
|
||||
fput_light(sock->file, fput_needed);
|
||||
if (!err)
|
||||
sockev_notify(SOCKEV_LISTEN, sock);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
@ -1627,7 +1644,8 @@ SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
|
|||
|
||||
fd_install(newfd, newfile);
|
||||
err = newfd;
|
||||
|
||||
if (!err)
|
||||
sockev_notify(SOCKEV_ACCEPT, sock);
|
||||
out_put:
|
||||
fput_light(sock->file, fput_needed);
|
||||
out:
|
||||
|
@ -1677,6 +1695,8 @@ SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr,
|
|||
|
||||
err = sock->ops->connect(sock, (struct sockaddr *)&address, addrlen,
|
||||
sock->file->f_flags);
|
||||
if (!err)
|
||||
sockev_notify(SOCKEV_CONNECT, sock);
|
||||
out_put:
|
||||
fput_light(sock->file, fput_needed);
|
||||
out:
|
||||
|
@ -1939,6 +1959,7 @@ SYSCALL_DEFINE2(shutdown, int, fd, int, how)
|
|||
|
||||
sock = sockfd_lookup_light(fd, &err, &fput_needed);
|
||||
if (sock != NULL) {
|
||||
sockev_notify(SOCKEV_SHUTDOWN, sock);
|
||||
err = security_socket_shutdown(sock, how);
|
||||
if (!err)
|
||||
err = sock->ops->shutdown(sock, how);
|
||||
|
@ -3477,3 +3498,15 @@ int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how)
|
|||
return sock->ops->shutdown(sock, how);
|
||||
}
|
||||
EXPORT_SYMBOL(kernel_sock_shutdown);
|
||||
|
||||
int sockev_register_notify(struct notifier_block *nb)
|
||||
{
|
||||
return blocking_notifier_chain_register(&sockev_notifier_list, nb);
|
||||
}
|
||||
EXPORT_SYMBOL(sockev_register_notify);
|
||||
|
||||
int sockev_unregister_notify(struct notifier_block *nb)
|
||||
{
|
||||
return blocking_notifier_chain_unregister(&sockev_notifier_list, nb);
|
||||
}
|
||||
EXPORT_SYMBOL(sockev_unregister_notify);
|
||||
|
|
Loading…
Reference in New Issue