diff options
Diffstat (limited to 'net/socket.c')
-rw-r--r-- | net/socket.c | 56 |
1 files changed, 55 insertions, 1 deletions
diff --git a/net/socket.c b/net/socket.c index 263b334ec5e4..5211c40daecc 100644 --- a/net/socket.c +++ b/net/socket.c @@ -89,6 +89,8 @@ #include <linux/magic.h> #include <linux/slab.h> #include <linux/xattr.h> +#include <linux/seemp_api.h> +#include <linux/seemp_instrumentation.h> #include <asm/uaccess.h> #include <asm/unistd.h> @@ -115,6 +117,9 @@ unsigned int sysctl_net_busy_poll __read_mostly; static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to); static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from); + +static BLOCKING_NOTIFIER_HEAD(sockev_notifier_list); + static int sock_mmap(struct file *file, struct vm_area_struct *vma); static int sock_close(struct inode *inode, struct file *file); @@ -169,6 +174,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. @@ -1234,6 +1247,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; @@ -1378,6 +1394,13 @@ SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen) (struct sockaddr *) &address, addrlen); } + if (!err) { + if (sock->sk) + sock_hold(sock->sk); + sockev_notify(SOCKEV_BIND, sock); + if (sock->sk) + sock_put(sock->sk); + } fput_light(sock->file, fput_needed); } return err; @@ -1405,6 +1428,13 @@ SYSCALL_DEFINE2(listen, int, fd, int, backlog) if (!err) err = sock->ops->listen(sock, backlog); + if (!err) { + if (sock->sk) + sock_hold(sock->sk); + sockev_notify(SOCKEV_LISTEN, sock); + if (sock->sk) + sock_put(sock->sk); + } fput_light(sock->file, fput_needed); } return err; @@ -1492,7 +1522,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: @@ -1542,6 +1573,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: @@ -1627,6 +1660,11 @@ SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len, struct iovec iov; int fput_needed; + seemp_logk_sendto(fd, buff, len, flags, addr, addr_len); + + if (len > INT_MAX) + len = INT_MAX; + err = import_single_range(WRITE, buff, len, &iov, &msg.msg_iter); if (unlikely(err)) return err; @@ -1683,9 +1721,12 @@ SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size, int err, err2; int fput_needed; + if (size > INT_MAX) + size = INT_MAX; err = import_single_range(READ, ubuf, size, &iov, &msg.msg_iter); if (unlikely(err)) return err; + sock = sockfd_lookup_light(fd, &err, &fput_needed); if (!sock) goto out; @@ -1799,6 +1840,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); @@ -3294,3 +3336,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); |