Re: PTRACE_GET_THREAD_AREA

Roland McGrath (roland@redhat.com)
Sun, 12 Jan 2003 19:51:28 -0800


Hi Linus. I didn't get your reply until just recently when someone
forwarded it to me, because I'm not on the mailing list. Please be sure to
include <roland@redhat.com> directly on any replies you make.

> Looks fine, except I'd ask you to split up the get/set logic as separate
> functions, instead of making that case-statement thing horribly big.

No problem. Here is a new version of the patch. Please let me know if
there is any reason this can't go in ASAP.

Thanks,
Roland

--- linux-2.5.54/include/asm-i386/ptrace.h.orig Mon Dec 9 18:45:43 2002
+++ linux-2.5.54/include/asm-i386/ptrace.h Fri Jan 10 16:39:44 2003
@@ -51,6 +51,9 @@ struct pt_regs {

#define PTRACE_OLDSETOPTIONS 21

+#define PTRACE_GET_THREAD_AREA 25
+#define PTRACE_SET_THREAD_AREA 26
+
#ifdef __KERNEL__
#define user_mode(regs) ((VM_MASK & (regs)->eflags) || (3 & (regs)->xcs))
#define instruction_pointer(regs) ((regs)->eip)
[Exit 1]
--- linux-2.5.54/arch/i386/kernel/ptrace.c.orig Fri Jan 10 16:40:18 2003
+++ linux-2.5.54/arch/i386/kernel/ptrace.c Fri Jan 10 12:38:30 2003
@@ -21,6 +21,8 @@
#include <asm/processor.h>
#include <asm/i387.h>
#include <asm/debugreg.h>
+#include <asm/ldt.h>
+#include <asm/desc.h>

/*
* does not yet catch signals sent when the child dies.
@@ -148,6 +150,85 @@ void ptrace_disable(struct task_struct *
put_stack_long(child, EFL_OFFSET, tmp);
}

+/*
+ * Perform get_thread_area on behalf of the traced child.
+ */
+static int
+ptrace_get_thread_area(struct task_struct *child,
+ int idx, struct user_desc *user_desc)
+{
+ struct user_desc info;
+ struct desc_struct *desc;
+
+/*
+ * Get the current Thread-Local Storage area:
+ */
+
+#define GET_BASE(desc) ( \
+ (((desc)->a >> 16) & 0x0000ffff) | \
+ (((desc)->b << 16) & 0x00ff0000) | \
+ ( (desc)->b & 0xff000000) )
+
+#define GET_LIMIT(desc) ( \
+ ((desc)->a & 0x0ffff) | \
+ ((desc)->b & 0xf0000) )
+
+#define GET_32BIT(desc) (((desc)->b >> 23) & 1)
+#define GET_CONTENTS(desc) (((desc)->b >> 10) & 3)
+#define GET_WRITABLE(desc) (((desc)->b >> 9) & 1)
+#define GET_LIMIT_PAGES(desc) (((desc)->b >> 23) & 1)
+#define GET_PRESENT(desc) (((desc)->b >> 15) & 1)
+#define GET_USEABLE(desc) (((desc)->b >> 20) & 1)
+
+ if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
+ return -EINVAL;
+
+ desc = child->thread.tls_array + idx - GDT_ENTRY_TLS_MIN;
+
+ info.entry_number = idx;
+ info.base_addr = GET_BASE(desc);
+ info.limit = GET_LIMIT(desc);
+ info.seg_32bit = GET_32BIT(desc);
+ info.contents = GET_CONTENTS(desc);
+ info.read_exec_only = !GET_WRITABLE(desc);
+ info.limit_in_pages = GET_LIMIT_PAGES(desc);
+ info.seg_not_present = !GET_PRESENT(desc);
+ info.useable = GET_USEABLE(desc);
+
+ if (copy_to_user(user_desc, &info, sizeof(info)))
+ return -EFAULT;
+
+ return 0;
+}
+
+/*
+ * Perform set_thread_area on behalf of the traced child.
+ */
+static int
+ptrace_set_thread_area(struct task_struct *child,
+ int idx, struct user_desc *user_desc)
+{
+ struct user_desc info;
+ struct desc_struct *desc;
+
+ if (copy_from_user(&info, user_desc, sizeof(info)))
+ return -EFAULT;
+
+ if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
+ return -EINVAL;
+
+ desc = child->thread.tls_array + idx - GDT_ENTRY_TLS_MIN;
+ if (LDT_empty(&info)) {
+ desc->a = 0;
+ desc->b = 0;
+ } else {
+ desc->a = LDT_entry_a(&info);
+ desc->b = LDT_entry_b(&info);
+ }
+
+ return 0;
+}
+
asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
{
struct task_struct *child;
@@ -416,6 +497,16 @@ asmlinkage int sys_ptrace(long request,
break;
}

+ case PTRACE_GET_THREAD_AREA:
+ ret = ptrace_get_thread_area(child,
+ addr, (struct user_desc *) data);
+ break;
+
+ case PTRACE_SET_THREAD_AREA:
+ ret = ptrace_set_thread_area(child,
+ addr, (struct user_desc *) data);
+ break;
+
default:
ret = ptrace_request(child, request, addr, data);
break;
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/