Messages in this thread Patch in this message | | | Subject | [patch 1/1] /proc/$$/ipaddr and per-task networking bits | From | Lorenzo Hernández García-Hierro <> | Date | Thu, 10 Mar 2005 15:16:42 +0100 |
| |
Ported feature from grSecurity that makes possible to add an ipaddr entry in each /proc/<pid> (/proc/<pid>/ipaddr), where the task originating IP address is stored, and subsequently made available (readable) by the process itself and also the root user with CAP_DAC_OVERRIDE capability (that can be managed by specific security models implementations like SELinux). Available also at http://pearls.tuxedo-es.org/patches/task-curr_ip.patch
Signed-off-by: Lorenzo Hernandez Garcia-Hierro <lorenzo@gnu.org> ---
linux-2.6.11-lorenzo/fs/Kconfig | 16 ++ linux-2.6.11-lorenzo/fs/proc/array.c | 10 + linux-2.6.11-lorenzo/fs/proc/base.c | 12 ++ linux-2.6.11-lorenzo/fs/proc/internal.h | 3 linux-2.6.11-lorenzo/include/linux/sched.h | 8 + linux-2.6.11-lorenzo/kernel/exit.c | 8 + linux-2.6.11-lorenzo/net/Makefile | 4 linux-2.6.11-lorenzo/net/ipv4/tcp_ipv4.c | 14 ++ linux-2.6.11-lorenzo/net/proc_ipaddr.c | 166 +++++++++++++++++++++++++++++ linux-2.6.11-lorenzo/net/socket.c | 2 10 files changed, 243 insertions(+)
diff -puN fs/proc/base.c~task-curr_ip fs/proc/base.c --- linux-2.6.11/fs/proc/base.c~task-curr_ip 2005-03-10 14:56:13.931854168 +0100 +++ linux-2.6.11-lorenzo/fs/proc/base.c 2005-03-10 14:56:14.048836384 +0100 @@ -74,6 +74,9 @@ enum pid_directory_inos { #ifdef CONFIG_AUDITSYSCALL PROC_TGID_LOGINUID, #endif +#ifdef CONFIG_PROC_IPADDR + PROC_TGID_IPADDR, +#endif PROC_TGID_FD_DIR, PROC_TGID_OOM_SCORE, PROC_TGID_OOM_ADJUST, @@ -134,6 +137,9 @@ static struct pid_entry tgid_base_stuff[ E(PROC_TGID_ROOT, "root", S_IFLNK|S_IRWXUGO), E(PROC_TGID_EXE, "exe", S_IFLNK|S_IRWXUGO), E(PROC_TGID_MOUNTS, "mounts", S_IFREG|S_IRUGO), +#ifdef CONFIG_PROC_IPADDR + E(PROC_TGID_IPADDR, "ipaddr", S_IFREG|S_IRUSR), +#endif #ifdef CONFIG_SECURITY E(PROC_TGID_ATTR, "attr", S_IFDIR|S_IRUGO|S_IXUGO), #endif @@ -1416,6 +1422,12 @@ static struct dentry *proc_pident_lookup inode->i_fop = &proc_info_file_operations; ei->op.proc_read = proc_pid_status; break; +#ifdef CONFIG_PROC_IPADDR + case PROC_TGID_IPADDR: + inode->i_fop = &proc_info_file_operations; + ei->op.proc_read = proc_pid_ipaddr; + break; +#endif case PROC_TID_STAT: inode->i_fop = &proc_info_file_operations; ei->op.proc_read = proc_tid_stat; diff -puN fs/proc/internal.h~task-curr_ip fs/proc/internal.h --- linux-2.6.11/fs/proc/internal.h~task-curr_ip 2005-03-10 14:56:13.932854016 +0100 +++ linux-2.6.11-lorenzo/fs/proc/internal.h 2005-03-10 14:56:14.048836384 +0100 @@ -36,6 +36,9 @@ extern int proc_tid_stat(struct task_str extern int proc_tgid_stat(struct task_struct *, char *); extern int proc_pid_status(struct task_struct *, char *); extern int proc_pid_statm(struct task_struct *, char *); +#ifdef CONFIG_PROC_IPADDR +extern int proc_pid_ipaddr(struct task_struct*,char*); +#endif static inline struct task_struct *proc_task(struct inode *inode) { diff -puN fs/proc/array.c~task-curr_ip fs/proc/array.c --- linux-2.6.11/fs/proc/array.c~task-curr_ip 2005-03-10 14:56:13.934853712 +0100 +++ linux-2.6.11-lorenzo/fs/proc/array.c 2005-03-10 14:56:14.048836384 +0100 @@ -473,3 +473,13 @@ int proc_pid_statm(struct task_struct *t return sprintf(buffer,"%d %d %d %d %d %d %d\n", size, resident, shared, text, lib, data, 0); } + +#ifdef CONFIG_PROC_IPADDR +int proc_pid_ipaddr(struct task_struct *task, char * buffer) +{ + int len; + + len = sprintf(buffer, "%u.%u.%u.%u\n", NIPQUAD(task->curr_ip)); + return len; +} +#endif diff -puN fs/Kconfig~task-curr_ip fs/Kconfig --- linux-2.6.11/fs/Kconfig~task-curr_ip 2005-03-10 14:56:13.936853408 +0100 +++ linux-2.6.11-lorenzo/fs/Kconfig 2005-03-10 14:56:14.049836232 +0100 @@ -716,6 +716,22 @@ config PROC_FS config PROC_KCORE bool "/proc/kcore support" if !ARM depends on PROC_FS && MMU + +config PROC_IPADDR + bool "/proc/<pid>/ipaddr support" + depends on PROC_FS && NET && INET + help + If you say Y here, a new entry will be added to each /proc/<pid> + directory that contains the IP address of the person using the task. + The IP is carried across local TCP and AF_UNIX stream sockets. + This information can be useful for IDS/IPSes to perform remote response + to a local attack. The entry is readable by only the owner of the + process (and root if he has CAP_DAC_OVERRIDE, which can be handled in + different manners depending on the used model, ie. RBAC and the engine + implementing it, ie. SELinux), and thus does not create privacy concerns. + + This feature has been ported out of grSecurity from Brad Spengler by + lorenzo@gnu.org. config SYSFS bool "sysfs file system support" if EMBEDDED diff -puN net/socket.c~task-curr_ip net/socket.c --- linux-2.6.11/net/socket.c~task-curr_ip 2005-03-10 14:56:13.938853104 +0100 +++ linux-2.6.11-lorenzo/net/socket.c 2005-03-10 14:56:14.050836080 +0100 @@ -114,6 +114,7 @@ static ssize_t sock_writev(struct file * static ssize_t sock_sendpage(struct file *file, struct page *page, int offset, size_t size, loff_t *ppos, int more); +extern void proc_attach_curr_ip(const struct sock *sk); /* * Socket files have a set of 'special' operations as well as the generic file ones. These don't appear @@ -1386,6 +1387,7 @@ asmlinkage long sys_accept(int fd, struc goto out_release; security_socket_post_accept(sock, newsock); + proc_attach_curr_ip(newsock->sk); out_put: sockfd_put(sock); diff -puN include/linux/sched.h~task-curr_ip include/linux/sched.h --- linux-2.6.11/include/linux/sched.h~task-curr_ip 2005-03-10 14:56:13.963849304 +0100 +++ linux-2.6.11-lorenzo/include/linux/sched.h 2005-03-10 14:56:14.051835928 +0100 @@ -685,6 +685,14 @@ struct task_struct { struct mempolicy *mempolicy; short il_next; #endif +#ifdef CONFIG_PROC_IPADDR + u32 curr_ip; /* per-task originating ip address */ + u8 used_accept:1; + u32 net_saddr; + u32 net_daddr; + u16 net_sport; + u16 net_dport; +#endif }; static inline pid_t process_group(struct task_struct *tsk) diff -puN net/ipv4/tcp_ipv4.c~task-curr_ip net/ipv4/tcp_ipv4.c --- linux-2.6.11/net/ipv4/tcp_ipv4.c~task-curr_ip 2005-03-10 14:56:13.977847176 +0100 +++ linux-2.6.11-lorenzo/net/ipv4/tcp_ipv4.c 2005-03-10 14:56:14.052835776 +0100 @@ -82,6 +82,11 @@ int sysctl_tcp_low_latency; /* Check TCP sequence numbers in ICMP packets. */ #define ICMP_MIN_LENGTH 8 +#ifdef CONFIG_PROC_IPADDR +extern void net_add_to_task_ip_table(struct task_struct *p); +extern void net_del_task_from_ip_table(struct task_struct *p); +#endif + /* Socket used for sending RSTs */ static struct socket *tcp_socket; @@ -717,6 +722,15 @@ ok: __tcp_v4_hash(sk, 0); } spin_unlock(&head->lock); + +#ifdef CONFIG_PROC_IPADDR + net_del_task_from_ip_table(current); + current->net_saddr = inet_sk(sk)->rcv_saddr; + current->net_daddr = inet_sk(sk)->daddr; + current->net_sport = inet_sk(sk)->sport; + current->net_dport = inet_sk(sk)->dport; + net_add_to_task_ip_table(current); +#endif if (tw) { tcp_tw_deschedule(tw); diff -puN kernel/exit.c~task-curr_ip kernel/exit.c --- linux-2.6.11/kernel/exit.c~task-curr_ip 2005-03-10 14:56:13.979846872 +0100 +++ linux-2.6.11-lorenzo/kernel/exit.c 2005-03-10 14:56:14.053835624 +0100 @@ -35,6 +35,10 @@ extern void sem_exit (void); extern struct task_struct *child_reaper; +#ifdef CONFIG_PROC_IPADDR +extern void net_del_task_from_ip_table(struct task_struct *p); +#endif + int getrusage(struct task_struct *, int, struct rusage __user *); static void __unhash_process(struct task_struct *p) @@ -811,6 +815,10 @@ fastcall NORET_TYPE void do_exit(long co group_dead = atomic_dec_and_test(&tsk->signal->live); if (group_dead) acct_process(code); + +#ifdef CONFIG_PROC_IPADDR + net_del_task_from_ip_table(tsk); +#endif exit_mm(tsk); exit_sem(tsk); diff -puN /dev/null net/proc_ipaddr.c --- /dev/null 2005-03-01 21:41:03.335473768 +0100 +++ linux-2.6.11-lorenzo/net/proc_ipaddr.c 2005-03-10 14:56:14.054835472 +0100 @@ -0,0 +1,166 @@ +/* + * Per-task originating IP address & /proc/$$/ipaddr entry support. + * + * Copyright (C) 2005 Lorenzo Hernandez Garcia-Hierro <lorenzo@gnu.org> + * Copyright (C) 2004, 2005 Brad Spengler <spender@grsecurity.net> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#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> + +#ifdef CONFIG_PROC_IPADDR +#define net_conn_table_size 65521 +struct task_struct *net_conn_table[net_conn_table_size]; +struct task_struct *deleted_conn = (struct task_struct *)~0; +spinlock_t net_conn_table_lock = SPIN_LOCK_UNLOCKED; + +static __inline__ int +conn_hash(__u32 saddr, __u32 daddr, __u16 sport, __u16 dport, unsigned int size) +{ + return ((daddr + saddr + (sport << 8) + (dport << 16)) % size); +} + +static __inline__ int +conn_match(const struct task_struct *task, __u32 saddr, __u32 daddr, + __u16 sport, __u16 dport) +{ + if (unlikely(task != deleted_conn && task->net_saddr == saddr && + task->net_daddr == daddr && task->net_sport == sport && + task->net_dport == dport)) + return 1; + else + return 0; +} + +void net_add_to_task_ip_table(struct task_struct *task) +{ + unsigned int index; + + if (unlikely(net_conn_table == NULL)) + return; + + if (!thread_group_leader(task)) + task = task->group_leader; + + index = conn_hash(task->net_saddr, task->net_daddr, + task->net_sport, task->net_dport, + net_conn_table_size); + + spin_lock(&net_conn_table_lock); + + while (net_conn_table[index] && net_conn_table[index] != deleted_conn) { + index = (index + 1) % net_conn_table_size; + } + + net_conn_table[index] = task; + + spin_unlock(&net_conn_table_lock); + + return; +} + +void net_del_task_from_ip_table_nolock(struct task_struct *task) +{ + unsigned int index; + + if (unlikely(net_conn_table == NULL)) + return; + + if (!thread_group_leader(task)) + task = task->group_leader; + + index = conn_hash(task->net_saddr, task->net_daddr, + task->net_sport, task->net_dport, + net_conn_table_size); + + while (net_conn_table[index] && !conn_match(net_conn_table[index], + task->net_saddr, task->net_daddr, task->net_sport, + task->net_dport)) { + index = (index + 1) % net_conn_table_size; + } + + if (net_conn_table[index]) { + if (net_conn_table[(index + 1) % net_conn_table_size]) + net_conn_table[index] = deleted_conn; + else + net_conn_table[index] = NULL; + } + + return; +} + +struct task_struct * net_lookup_task_ip_table(__u32 saddr, __u32 daddr, + __u16 sport, __u16 dport) +{ + unsigned int index; + + if (unlikely(net_conn_table == NULL)) + return NULL; + + index = conn_hash(saddr, daddr, sport, dport, net_conn_table_size); + + while (net_conn_table[index] && !conn_match(net_conn_table[index], + saddr, daddr, sport, dport)) { + index = (index + 1) % net_conn_table_size; + } + + return net_conn_table[index]; +} +#endif + +void net_del_task_from_ip_table(struct task_struct *task) +{ +#ifdef CONFIG_PROC_IPADDR + spin_lock(&net_conn_table_lock); + if (!thread_group_leader(task)) + net_del_task_from_ip_table_nolock(task->group_leader); + else + net_del_task_from_ip_table_nolock(task); + spin_unlock(&net_conn_table_lock); +#endif + return; +} + +void +proc_attach_curr_ip(const struct sock *sk) +{ +#ifdef CONFIG_PROC_IPADDR + struct task_struct *p; + struct task_struct *set; + const struct inet_sock *inet = inet_sk(sk); + + if (unlikely(sk->sk_protocol != IPPROTO_TCP)) + return; + + set = current; + if (!thread_group_leader(set)) + set = set->group_leader; + + spin_lock(&net_conn_table_lock); + p = net_lookup_task_ip_table(inet->daddr, inet->rcv_saddr, + inet->dport, inet->sport); + if (unlikely(p != NULL)) { + set->curr_ip = p->curr_ip; + set->used_accept = 1; + net_del_task_from_ip_table_nolock(p); + spin_unlock(&net_conn_table_lock); + return; + } + spin_unlock(&net_conn_table_lock); + + set->curr_ip = inet->daddr; + set->used_accept = 1; +#endif + return; +} diff -puN net/Makefile~task-curr_ip net/Makefile --- linux-2.6.11/net/Makefile~task-curr_ip 2005-03-10 14:56:13.981846568 +0100 +++ linux-2.6.11-lorenzo/net/Makefile 2005-03-10 14:56:14.054835472 +0100 @@ -46,3 +46,7 @@ obj-$(CONFIG_IP_SCTP) += sctp/ ifeq ($(CONFIG_NET),y) obj-$(CONFIG_SYSCTL) += sysctl_net.o endif + +ifeq ($(CONFIG_NET),y) +obj-$(CONFIG_PROC_IPADDR) += proc_ipaddr.o +endif Cheers, -- Lorenzo Hernández García-Hierro <lorenzo@gnu.org> [1024D/6F2B2DEC] & [2048g/9AE91A22][http://tuxedo-es.org][unhandled content-type:application/pgp-signature] | |