3
0
mirror of https://github.com/Qortal/Brooklyn.git synced 2025-01-30 23:02:18 +00:00
Brooklyn/grsecurity/grsec_sock.c
Scare Crowe 2a709f28fa Auto exploit mitigation feature
* 0day explit mitigation
* Memory corruption prevention
* Privilege escalation prevention
* Buffer over flow prevention
* File System corruption defense
* Thread escape prevention

This may very well be the most intensive inclusion to BrooklynR. This will not be part of an x86 suite nor it will be released as tool kit. The security core toolkit will remain part of kernel base.
2021-11-13 09:26:51 +05:00

245 lines
5.9 KiB
C

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/file.h>
#include <linux/net.h>
#include <linux/in.h>
#include <linux/ip.h>
#include <net/sock.h>
#include <net/inet_sock.h>
#include <linux/grsecurity.h>
#include <linux/grinternal.h>
#include <linux/gracl.h>
extern int gr_search_udp_recvmsg(struct sock *sk, const struct sk_buff *skb);
extern int gr_search_udp_sendmsg(struct sock *sk, struct sockaddr_in *addr);
EXPORT_SYMBOL_GPL(gr_search_udp_recvmsg);
EXPORT_SYMBOL_GPL(gr_search_udp_sendmsg);
#ifdef CONFIG_UNIX_MODULE
EXPORT_SYMBOL_GPL(gr_acl_handle_unix);
EXPORT_SYMBOL_GPL(gr_acl_handle_mknod);
EXPORT_SYMBOL_GPL(gr_handle_chroot_unix);
EXPORT_SYMBOL_GPL(gr_handle_create);
#endif
#ifdef CONFIG_GRKERNSEC
#define gr_conn_table_size 32749
struct conn_table_entry {
struct conn_table_entry *next;
struct signal_struct *sig;
};
struct conn_table_entry *gr_conn_table[gr_conn_table_size];
DEFINE_SPINLOCK(gr_conn_table_lock);
extern const char * gr_socktype_to_name(unsigned char type);
extern const char * gr_proto_to_name(unsigned char proto);
extern const char * gr_sockfamily_to_name(unsigned char family);
static int
conn_hash(__u32 saddr, __u32 daddr, __u16 sport, __u16 dport, unsigned int size)
{
return ((daddr + saddr + (sport << 8) + (dport << 16)) % size);
}
static int
conn_match(const struct signal_struct *sig, __u32 saddr, __u32 daddr,
__u16 sport, __u16 dport)
{
if (unlikely(sig->gr_saddr == saddr && sig->gr_daddr == daddr &&
sig->gr_sport == sport && sig->gr_dport == dport))
return 1;
else
return 0;
}
static void gr_add_to_task_ip_table_nolock(struct signal_struct *sig, struct conn_table_entry *newent)
{
struct conn_table_entry **match;
unsigned int index;
index = conn_hash(sig->gr_saddr, sig->gr_daddr,
sig->gr_sport, sig->gr_dport,
gr_conn_table_size);
newent->sig = sig;
match = &gr_conn_table[index];
newent->next = *match;
*match = newent;
return;
}
static void gr_del_task_from_ip_table_nolock(struct signal_struct *sig)
{
struct conn_table_entry *match, *last = NULL;
unsigned int index;
index = conn_hash(sig->gr_saddr, sig->gr_daddr,
sig->gr_sport, sig->gr_dport,
gr_conn_table_size);
match = gr_conn_table[index];
while (match && !conn_match(match->sig,
sig->gr_saddr, sig->gr_daddr, sig->gr_sport,
sig->gr_dport)) {
last = match;
match = match->next;
}
if (match) {
if (last)
last->next = match->next;
else
gr_conn_table[index] = NULL;
kfree(match);
}
return;
}
static struct signal_struct * gr_lookup_task_ip_table(__u32 saddr, __u32 daddr,
__u16 sport, __u16 dport)
{
struct conn_table_entry *match;
unsigned int index;
index = conn_hash(saddr, daddr, sport, dport, gr_conn_table_size);
match = gr_conn_table[index];
while (match && !conn_match(match->sig, saddr, daddr, sport, dport))
match = match->next;
if (match)
return match->sig;
else
return NULL;
}
#endif
void gr_update_task_in_ip_table(const struct inet_sock *inet)
{
#ifdef CONFIG_GRKERNSEC
struct signal_struct *sig = current->signal;
struct conn_table_entry *newent;
newent = kmalloc(sizeof(struct conn_table_entry), GFP_ATOMIC);
if (newent == NULL)
return;
/* no bh lock needed since we are called with bh disabled */
spin_lock(&gr_conn_table_lock);
gr_del_task_from_ip_table_nolock(sig);
sig->gr_saddr = inet->inet_rcv_saddr;
sig->gr_daddr = inet->inet_daddr;
sig->gr_sport = inet->inet_sport;
sig->gr_dport = inet->inet_dport;
gr_add_to_task_ip_table_nolock(sig, newent);
spin_unlock(&gr_conn_table_lock);
#endif
return;
}
void gr_del_task_from_ip_table(struct task_struct *task)
{
#ifdef CONFIG_GRKERNSEC
spin_lock_bh(&gr_conn_table_lock);
gr_del_task_from_ip_table_nolock(task->signal);
spin_unlock_bh(&gr_conn_table_lock);
#endif
return;
}
void
gr_attach_curr_ip(const struct sock *sk)
{
#ifdef CONFIG_GRKERNSEC
struct signal_struct *p, *set;
const struct inet_sock *inet = inet_sk(sk);
if (unlikely(sk->sk_protocol != IPPROTO_TCP))
return;
set = current->signal;
spin_lock_bh(&gr_conn_table_lock);
p = gr_lookup_task_ip_table(inet->inet_daddr, inet->inet_rcv_saddr,
inet->inet_dport, inet->inet_sport);
if (unlikely(p != NULL)) {
set->curr_ip = p->curr_ip;
set->used_accept = 1;
gr_del_task_from_ip_table_nolock(p);
spin_unlock_bh(&gr_conn_table_lock);
return;
}
spin_unlock_bh(&gr_conn_table_lock);
set->curr_ip = inet->inet_daddr;
set->used_accept = 1;
#endif
return;
}
int
gr_handle_sock_all(const int family, const int type, const int protocol)
{
#ifdef CONFIG_GRKERNSEC_SOCKET_ALL
if (grsec_enable_socket_all && in_group_p(grsec_socket_all_gid) &&
(family != AF_UNIX)) {
if (family == AF_INET)
gr_log_str3(GR_DONT_AUDIT, GR_SOCK_MSG, gr_sockfamily_to_name(family), gr_socktype_to_name(type), gr_proto_to_name(protocol));
else
gr_log_str2_int(GR_DONT_AUDIT, GR_SOCK_NOINET_MSG, gr_sockfamily_to_name(family), gr_socktype_to_name(type), protocol);
return -EACCES;
}
#endif
return 0;
}
int
gr_handle_sock_server(const struct sockaddr *sck)
{
#ifdef CONFIG_GRKERNSEC_SOCKET_SERVER
if (grsec_enable_socket_server &&
in_group_p(grsec_socket_server_gid) &&
sck && (sck->sa_family != AF_UNIX) &&
(sck->sa_family != AF_LOCAL)) {
gr_log_noargs(GR_DONT_AUDIT, GR_BIND_MSG);
return -EACCES;
}
#endif
return 0;
}
int
gr_handle_sock_server_other(const struct sock *sck)
{
#ifdef CONFIG_GRKERNSEC_SOCKET_SERVER
if (grsec_enable_socket_server &&
in_group_p(grsec_socket_server_gid) &&
sck && (sck->sk_family != AF_UNIX) &&
(sck->sk_family != AF_LOCAL)) {
gr_log_noargs(GR_DONT_AUDIT, GR_BIND_MSG);
return -EACCES;
}
#endif
return 0;
}
int
gr_handle_sock_client(const struct sockaddr *sck)
{
#ifdef CONFIG_GRKERNSEC_SOCKET_CLIENT
if (grsec_enable_socket_client && in_group_p(grsec_socket_client_gid) &&
sck && (sck->sa_family != AF_UNIX) &&
(sck->sa_family != AF_LOCAL)) {
gr_log_noargs(GR_DONT_AUDIT, GR_CONNECT_MSG);
return -EACCES;
}
#endif
return 0;
}