forked from Qortal/Brooklyn
2a709f28fa
* 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.
245 lines
5.9 KiB
C
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;
|
|
}
|