linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Prasanna S Panchamukhi <prasanna@in.ibm.com>
To: linux-kernel@vger.kernel.org, systemtap@sources.redhat.com
Cc: akpm@osdl.org, Andi Kleen <ak@suse.de>,
	davem@davemloft.net, suparna@in.ibm.com,
	richardj_moore@uk.ibm.com
Subject: Re: [RFC] [PATCH 6/6] Kprobes: Remove breakpoints from the copied pages
Date: Tue, 9 May 2006 12:45:23 +0530	[thread overview]
Message-ID: <20060509071523.GF22493@in.ibm.com> (raw)
In-Reply-To: <20060509071204.GE22493@in.ibm.com>

This patch removes the breakpoints if the pages read from the page
cache contains breakpoints. If the pages containing the breakpoints
is copied from the page cache, the copied image would also contain
breakpoints in them. This could be a major problem for tools like
tripwire etc and cause security concerns, hence must be prevented.
This patch hooks up the actor routine, checks if the executable was
a probed executable using the file inode and then replaces the
breakpoints with the original opcodes in the copied image.

Signed-off-by: Prasanna S Panchamukhi <prasanna@in.ibm.com>


 fs/nfsd/vfs.c              |    4 +++-
 include/asm-i386/kprobes.h |    1 +
 include/linux/fs.h         |    9 ++++++---
 include/linux/kprobes.h    |   17 ++++++++++++++++-
 kernel/uprobes.c           |   39 +++++++++++++++++++++++++++++++++++++++
 mm/filemap.c               |   17 ++++++++++++++---
 mm/shmem.c                 |    2 +-
 7 files changed, 80 insertions(+), 9 deletions(-)

diff -puN kernel/uprobes.c~kprobes_userspace_probes-remove-breakpoints-on-copy kernel/uprobes.c
--- linux-2.6.17-rc3-mm1/kernel/uprobes.c~kprobes_userspace_probes-remove-breakpoints-on-copy	2006-05-09 12:43:21.000000000 +0530
+++ linux-2.6.17-rc3-mm1-prasanna/kernel/uprobes.c	2006-05-09 12:43:21.000000000 +0530
@@ -300,6 +300,45 @@ struct uprobe_module __kprobes *get_modu
 	return NULL;
 }
 
+/*
+ * This routine checks if the given page contains breakpoints. It first
+ * checks if the file read is a probed executable and later checks
+ * if the page being read contains breakpoints. This routine is
+ * used by file_read_actor();
+ */
+void remove_uprobe_breakpoints(struct address_space *mapping,
+				struct page *page, unsigned long offset,
+				read_descriptor_t *desc, unsigned long size)
+{
+	struct inode *inode = mapping->host;
+	struct page *upage;
+	struct uprobe_module *umodule = NULL;
+	struct uprobe *uprobe = NULL;
+	struct hlist_node *node;
+	unsigned long page_off, ret;
+
+	mutex_lock(&uprobe_mutex);
+	umodule = get_module_by_inode(inode);
+	if (!umodule)
+		goto out;
+	hlist_for_each_entry(uprobe, node, &umodule->ulist_head, ulist) {
+		upage = find_get_page(mapping,
+				uprobe->offset >> PAGE_CACHE_SHIFT);
+		if (upage == page) {
+			page_off = uprobe->offset & ~PAGE_MASK;
+			if ((page_off >= offset) &&
+					(page_off < (offset + PAGE_SIZE)) &&
+					((page_off - offset) <= size))
+				ret = __copy_to_user(desc->arg.buf +
+						(page_off - offset),
+						&(uprobe->kp.opcode),
+						sizeof(kprobe_opcode_t));
+		}
+	}
+out:
+	mutex_unlock(&uprobe_mutex);
+}
+
 static inline void insert_readpage_uprobe(struct page *page,
 	struct address_space *mapping, struct uprobe *uprobe)
 {
diff -puN mm/filemap.c~kprobes_userspace_probes-remove-breakpoints-on-copy mm/filemap.c
--- linux-2.6.17-rc3-mm1/mm/filemap.c~kprobes_userspace_probes-remove-breakpoints-on-copy	2006-05-09 12:43:21.000000000 +0530
+++ linux-2.6.17-rc3-mm1-prasanna/mm/filemap.c	2006-05-09 12:43:21.000000000 +0530
@@ -31,6 +31,7 @@
 #include <linux/security.h>
 #include <linux/syscalls.h>
 #include <linux/cpuset.h>
+#include <linux/kprobes.h>
 #include "filemap.h"
 #include "internal.h"
 
@@ -884,7 +885,7 @@ page_ok:
 		 * "pos" here (the actor routine has to update the user buffer
 		 * pointers and the remaining count).
 		 */
-		ret = actor(desc, page, offset, nr);
+		ret = actor(desc, page, offset, nr, mapping);
 		offset += ret;
 		index += offset >> PAGE_CACHE_SHIFT;
 		offset &= ~PAGE_CACHE_MASK;
@@ -1012,7 +1013,8 @@ out:
 EXPORT_SYMBOL(do_generic_mapping_read);
 
 int file_read_actor(read_descriptor_t *desc, struct page *page,
-			unsigned long offset, unsigned long size)
+			unsigned long offset, unsigned long size,
+			struct address_space *mapping)
 {
 	char *kaddr;
 	unsigned long left, count = desc->count;
@@ -1043,6 +1045,13 @@ int file_read_actor(read_descriptor_t *d
 		desc->error = -EFAULT;
 	}
 success:
+#ifdef CONFIG_KPROBES
+	/*
+	 * Check if the data copied to the buffer contains breakpoint
+	 * and overwrite the breakpoints with appropriate opcodes.
+	 */
+	remove_uprobe_breakpoints(mapping, page, offset, desc, size);
+#endif
 	desc->count = count - size;
 	desc->written += size;
 	desc->arg.buf += size;
@@ -1159,7 +1168,9 @@ generic_file_read(struct file *filp, cha
 
 EXPORT_SYMBOL(generic_file_read);
 
-int file_send_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size)
+int file_send_actor(read_descriptor_t * desc, struct page *page,
+			unsigned long offset, unsigned long size,
+			struct address_space *mapping)
 {
 	ssize_t written;
 	unsigned long count = desc->count;
diff -puN mm/shmem.c~kprobes_userspace_probes-remove-breakpoints-on-copy mm/shmem.c
--- linux-2.6.17-rc3-mm1/mm/shmem.c~kprobes_userspace_probes-remove-breakpoints-on-copy	2006-05-09 12:43:21.000000000 +0530
+++ linux-2.6.17-rc3-mm1-prasanna/mm/shmem.c	2006-05-09 12:43:21.000000000 +0530
@@ -1588,7 +1588,7 @@ static void do_shmem_file_read(struct fi
 		 * "pos" here (the actor routine has to update the user buffer
 		 * pointers and the remaining count).
 		 */
-		ret = actor(desc, page, offset, nr);
+		ret = actor(desc, page, offset, nr, mapping);
 		offset += ret;
 		index += offset >> PAGE_CACHE_SHIFT;
 		offset &= ~PAGE_CACHE_MASK;
diff -puN fs/nfsd/vfs.c~kprobes_userspace_probes-remove-breakpoints-on-copy fs/nfsd/vfs.c
--- linux-2.6.17-rc3-mm1/fs/nfsd/vfs.c~kprobes_userspace_probes-remove-breakpoints-on-copy	2006-05-09 12:43:21.000000000 +0530
+++ linux-2.6.17-rc3-mm1-prasanna/fs/nfsd/vfs.c	2006-05-09 12:43:21.000000000 +0530
@@ -785,7 +785,9 @@ found:
  * directrly. They will be released after the sending has completed.
  */
 static int
-nfsd_read_actor(read_descriptor_t *desc, struct page *page, unsigned long offset , unsigned long size)
+nfsd_read_actor(read_descriptor_t *desc, struct page *page,
+		unsigned long offset, unsigned long size,
+		struct address_space *mapping)
 {
 	unsigned long count = desc->count;
 	struct svc_rqst *rqstp = desc->arg.data;
diff -puN include/linux/kprobes.h~kprobes_userspace_probes-remove-breakpoints-on-copy include/linux/kprobes.h
--- linux-2.6.17-rc3-mm1/include/linux/kprobes.h~kprobes_userspace_probes-remove-breakpoints-on-copy	2006-05-09 12:43:21.000000000 +0530
+++ linux-2.6.17-rc3-mm1-prasanna/include/linux/kprobes.h	2006-05-09 12:43:21.000000000 +0530
@@ -205,13 +205,13 @@ extern void copy_kprobe(struct kprobe *o
 extern int arch_copy_uprobe(struct kprobe *p, kprobe_opcode_t *address);
 extern void arch_arm_uprobe(kprobe_opcode_t *address);
 extern void arch_disarm_uprobe(struct kprobe *p, kprobe_opcode_t *address);
-extern void init_uprobes(void);
 
 /* Get the kprobe at this addr (if any) - called with preemption disabled */
 struct kprobe *get_kprobe(void *addr);
 struct kprobe *get_uprobe(void *addr);
 extern int arch_alloc_insn(struct kprobe *p);
 struct hlist_head * kretprobe_inst_table_head(struct task_struct *tsk);
+struct uprobe_module *get_module_by_inode(struct inode *inode);
 
 /* kprobe_running() will just return the current_kprobe on this CPU */
 static inline struct kprobe *kprobe_running(void)
@@ -239,6 +239,21 @@ static inline void reset_uprobe_instance
 	current_uprobe = NULL;
 }
 
+#ifdef ARCH_SUPPORTS_UPROBES
+extern void init_uprobes(void);
+extern void remove_uprobe_breakpoints(struct address_space *mapping,
+				struct page *page, unsigned long offset,
+				read_descriptor_t *desc, unsigned long size);
+#else
+static inline void init_uprobes(void)
+{
+}
+static inline void remove_uprobe_breakpoints(struct address_space *mapping,
+				struct page *page, unsigned long offset,
+				read_descriptor_t *desc, unsigned long size)
+{
+}
+#endif
 int register_kprobe(struct kprobe *p);
 void unregister_kprobe(struct kprobe *p);
 int setjmp_pre_handler(struct kprobe *, struct pt_regs *);
diff -puN include/asm-i386/kprobes.h~kprobes_userspace_probes-remove-breakpoints-on-copy include/asm-i386/kprobes.h
--- linux-2.6.17-rc3-mm1/include/asm-i386/kprobes.h~kprobes_userspace_probes-remove-breakpoints-on-copy	2006-05-09 12:43:21.000000000 +0530
+++ linux-2.6.17-rc3-mm1-prasanna/include/asm-i386/kprobes.h	2006-05-09 12:43:21.000000000 +0530
@@ -46,6 +46,7 @@ typedef u8 kprobe_opcode_t;
 #define JPROBE_ENTRY(pentry)	(kprobe_opcode_t *)pentry
 #define ARCH_SUPPORTS_KRETPROBES
 #define  ARCH_INACTIVE_KPROBE_COUNT 0
+#define ARCH_SUPPORTS_UPROBES
 
 void arch_remove_kprobe(struct kprobe *p);
 void kretprobe_trampoline(void);
diff -puN include/linux/fs.h~kprobes_userspace_probes-remove-breakpoints-on-copy include/linux/fs.h
--- linux-2.6.17-rc3-mm1/include/linux/fs.h~kprobes_userspace_probes-remove-breakpoints-on-copy	2006-05-09 12:43:21.000000000 +0530
+++ linux-2.6.17-rc3-mm1-prasanna/include/linux/fs.h	2006-05-09 12:43:21.000000000 +0530
@@ -998,7 +998,8 @@ typedef struct {
 	int error;
 } read_descriptor_t;
 
-typedef int (*read_actor_t)(read_descriptor_t *, struct page *, unsigned long, unsigned long);
+typedef int (*read_actor_t)(read_descriptor_t *, struct page *, unsigned long,
+					unsigned long, struct address_space *);
 
 /* These macros are for out of kernel modules to test that
  * the kernel supports the unlocked_ioctl and compat_ioctl
@@ -1595,8 +1596,10 @@ extern int sb_min_blocksize(struct super
 
 extern int generic_file_mmap(struct file *, struct vm_area_struct *);
 extern int generic_file_readonly_mmap(struct file *, struct vm_area_struct *);
-extern int file_read_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size);
-extern int file_send_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size);
+extern int file_read_actor(read_descriptor_t * desc, struct page *page,
+		unsigned long offset, unsigned long size, struct address_space *mapping);
+extern int file_send_actor(read_descriptor_t * desc, struct page *page,
+		unsigned long offset, unsigned long size, struct address_space *mapping);
 extern ssize_t generic_file_read(struct file *, char __user *, size_t, loff_t *);
 int generic_write_checks(struct file *file, loff_t *pos, size_t *count, int isblk);
 extern ssize_t generic_file_write(struct file *, const char __user *, size_t, loff_t *);

_
-- 
Prasanna S Panchamukhi
Linux Technology Center
India Software Labs, IBM Bangalore
Email: prasanna@in.ibm.com
Ph: 91-80-41776329

  reply	other threads:[~2006-05-09  7:15 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-05-09  6:54 [RFC] [PATCH 0/6] Kprobes: User-space probes support for i386 Prasanna S Panchamukhi
2006-05-09  6:59 ` [RFC] [PATCH 1/6] Kprobes: Allow/deny exclusive write access to inodes Prasanna S Panchamukhi
2006-05-09  7:01   ` [RFC] [PATCH 2/6] Kprobes: Get one pagetable entry Prasanna S Panchamukhi
2006-05-09  7:05     ` [RFC] [PATCH 3/6] Kprobes: New interfaces for user-space probes Prasanna S Panchamukhi
2006-05-09  7:09       ` [RFC] [PATCH 4/6] Kprobes: Insert probes on non-memory resident pages Prasanna S Panchamukhi
2006-05-09  7:12         ` [RFC] [PATCH 5/6] Kprobes: Single step the original instruction out-of-line Prasanna S Panchamukhi
2006-05-09  7:15           ` Prasanna S Panchamukhi [this message]
2006-05-09 17:04             ` [RFC] [PATCH 6/6] Kprobes: Remove breakpoints from the copied pages Hugh Dickins
2006-05-10 12:17               ` Prasanna S Panchamukhi
2006-05-10 15:17                 ` Hugh Dickins
2006-05-09  9:38           ` [RFC] [PATCH 5/6] Kprobes: Single step the original instruction out-of-line Christoph Hellwig
2006-05-10  0:47           ` bibo,mao
2006-05-10 14:19             ` Richard J Moore
2006-05-09  9:37         ` [RFC] [PATCH 4/6] Kprobes: Insert probes on non-memory resident pages Christoph Hellwig
2006-05-09  9:36       ` [RFC] [PATCH 3/6] Kprobes: New interfaces for user-space probes Christoph Hellwig
2006-05-09 15:11         ` Richard J Moore
2006-05-09 15:18           ` Christoph Hellwig
2006-05-09 17:41             ` Frank Ch. Eigler
2006-05-09 20:40               ` Adrian Bunk
2006-05-09 20:58                 ` Frank Ch. Eigler
2006-05-09 22:35                   ` Christoph Hellwig
2006-05-09  9:34     ` [RFC] [PATCH 2/6] Kprobes: Get one pagetable entry Christoph Hellwig

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20060509071523.GF22493@in.ibm.com \
    --to=prasanna@in.ibm.com \
    --cc=ak@suse.de \
    --cc=akpm@osdl.org \
    --cc=davem@davemloft.net \
    --cc=linux-kernel@vger.kernel.org \
    --cc=richardj_moore@uk.ibm.com \
    --cc=suparna@in.ibm.com \
    --cc=systemtap@sources.redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).