public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [patch 1/1] /proc/$$/ipaddr and per-task networking bits
@ 2005-03-10 14:16 Lorenzo Hernández García-Hierro
  2005-03-10 14:26 ` Arjan van de Ven
  2005-03-10 15:22 ` YOSHIFUJI Hideaki / 吉藤英明
  0 siblings, 2 replies; 10+ messages in thread
From: Lorenzo Hernández García-Hierro @ 2005-03-10 14:16 UTC (permalink / raw)
  To: linux-kernel@vger.kernel.org

[-- Attachment #1: Type: text/plain, Size: 13278 bytes --]

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]

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2005-03-11 12:35 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-03-10 14:16 [patch 1/1] /proc/$$/ipaddr and per-task networking bits Lorenzo Hernández García-Hierro
2005-03-10 14:26 ` Arjan van de Ven
2005-03-10 15:28   ` Lorenzo Hernández García-Hierro
2005-03-10 15:38     ` Arjan van de Ven
2005-03-10 16:00       ` Lorenzo Hernández García-Hierro
2005-03-10 16:08         ` Arjan van de Ven
2005-03-10 16:19           ` Paul P Komkoff Jr
2005-03-10 16:36           ` Joost Remijn
2005-03-11 12:35           ` Coywolf Qi Hunt
2005-03-10 15:22 ` YOSHIFUJI Hideaki / 吉藤英明

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox