aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarkus Metzger <markus.t.metzger@intel.com>2008-01-30 07:32:03 -0500
committerIngo Molnar <mingo@elte.hu>2008-01-30 07:32:03 -0500
commitcba4b65d359268c40679ca75ac92c0b93cecf6de (patch)
tree95352d42a1a51338b08b88603cd4678297d56917
parente6ae5d9540727b0e2e5e2fbeb683c84671ed0a31 (diff)
x86, ptrace: add buffer size checks
Pass the buffer size for (most) ptrace commands that pass user-allocated buffers and check that size before accessing the buffer. Unfortunately, PTRACE_BTS_GET already uses all 4 parameters. Commands that access user buffers return the number of bytes or records read or written. Signed-off-by: Markus Metzger <markus.t.metzger@intel.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r--arch/x86/kernel/ptrace.c25
-rw-r--r--include/asm-x86/ptrace-abi.h14
2 files changed, 29 insertions, 10 deletions
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
index 236528bec6eb..e19a91db9b35 100644
--- a/arch/x86/kernel/ptrace.c
+++ b/arch/x86/kernel/ptrace.c
@@ -591,6 +591,7 @@ static int ptrace_bts_clear(struct task_struct *child)
591} 591}
592 592
593static int ptrace_bts_drain(struct task_struct *child, 593static int ptrace_bts_drain(struct task_struct *child,
594 long size,
594 struct bts_struct __user *out) 595 struct bts_struct __user *out)
595{ 596{
596 int end, i; 597 int end, i;
@@ -603,6 +604,9 @@ static int ptrace_bts_drain(struct task_struct *child,
603 if (end <= 0) 604 if (end <= 0)
604 return end; 605 return end;
605 606
607 if (size < (end * sizeof(struct bts_struct)))
608 return -EIO;
609
606 for (i = 0; i < end; i++, out++) { 610 for (i = 0; i < end; i++, out++) {
607 struct bts_struct ret; 611 struct bts_struct ret;
608 int retval; 612 int retval;
@@ -617,7 +621,7 @@ static int ptrace_bts_drain(struct task_struct *child,
617 621
618 ds_clear(ds); 622 ds_clear(ds);
619 623
620 return i; 624 return end;
621} 625}
622 626
623static int ptrace_bts_realloc(struct task_struct *child, 627static int ptrace_bts_realloc(struct task_struct *child,
@@ -690,15 +694,22 @@ out:
690} 694}
691 695
692static int ptrace_bts_config(struct task_struct *child, 696static int ptrace_bts_config(struct task_struct *child,
697 long cfg_size,
693 const struct ptrace_bts_config __user *ucfg) 698 const struct ptrace_bts_config __user *ucfg)
694{ 699{
695 struct ptrace_bts_config cfg; 700 struct ptrace_bts_config cfg;
696 int bts_size, ret = 0; 701 int bts_size, ret = 0;
697 void *ds; 702 void *ds;
698 703
704 if (cfg_size < sizeof(cfg))
705 return -EIO;
706
699 if (copy_from_user(&cfg, ucfg, sizeof(cfg))) 707 if (copy_from_user(&cfg, ucfg, sizeof(cfg)))
700 return -EFAULT; 708 return -EFAULT;
701 709
710 if ((int)cfg.size < 0)
711 return -EINVAL;
712
702 bts_size = 0; 713 bts_size = 0;
703 ds = (void *)child->thread.ds_area_msr; 714 ds = (void *)child->thread.ds_area_msr;
704 if (ds) { 715 if (ds) {
@@ -734,6 +745,8 @@ static int ptrace_bts_config(struct task_struct *child,
734 else 745 else
735 clear_tsk_thread_flag(child, TIF_BTS_TRACE_TS); 746 clear_tsk_thread_flag(child, TIF_BTS_TRACE_TS);
736 747
748 ret = sizeof(cfg);
749
737out: 750out:
738 if (child->thread.debugctlmsr) 751 if (child->thread.debugctlmsr)
739 set_tsk_thread_flag(child, TIF_DEBUGCTLMSR); 752 set_tsk_thread_flag(child, TIF_DEBUGCTLMSR);
@@ -749,11 +762,15 @@ errout:
749} 762}
750 763
751static int ptrace_bts_status(struct task_struct *child, 764static int ptrace_bts_status(struct task_struct *child,
765 long cfg_size,
752 struct ptrace_bts_config __user *ucfg) 766 struct ptrace_bts_config __user *ucfg)
753{ 767{
754 void *ds = (void *)child->thread.ds_area_msr; 768 void *ds = (void *)child->thread.ds_area_msr;
755 struct ptrace_bts_config cfg; 769 struct ptrace_bts_config cfg;
756 770
771 if (cfg_size < sizeof(cfg))
772 return -EIO;
773
757 memset(&cfg, 0, sizeof(cfg)); 774 memset(&cfg, 0, sizeof(cfg));
758 775
759 if (ds) { 776 if (ds) {
@@ -923,12 +940,12 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
923 940
924 case PTRACE_BTS_CONFIG: 941 case PTRACE_BTS_CONFIG:
925 ret = ptrace_bts_config 942 ret = ptrace_bts_config
926 (child, (struct ptrace_bts_config __user *)addr); 943 (child, data, (struct ptrace_bts_config __user *)addr);
927 break; 944 break;
928 945
929 case PTRACE_BTS_STATUS: 946 case PTRACE_BTS_STATUS:
930 ret = ptrace_bts_status 947 ret = ptrace_bts_status
931 (child, (struct ptrace_bts_config __user *)addr); 948 (child, data, (struct ptrace_bts_config __user *)addr);
932 break; 949 break;
933 950
934 case PTRACE_BTS_SIZE: 951 case PTRACE_BTS_SIZE:
@@ -946,7 +963,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
946 963
947 case PTRACE_BTS_DRAIN: 964 case PTRACE_BTS_DRAIN:
948 ret = ptrace_bts_drain 965 ret = ptrace_bts_drain
949 (child, (struct bts_struct __user *) addr); 966 (child, data, (struct bts_struct __user *) addr);
950 break; 967 break;
951 968
952 default: 969 default:
diff --git a/include/asm-x86/ptrace-abi.h b/include/asm-x86/ptrace-abi.h
index 32fe137822bf..bcf67044754c 100644
--- a/include/asm-x86/ptrace-abi.h
+++ b/include/asm-x86/ptrace-abi.h
@@ -99,13 +99,15 @@ struct ptrace_bts_config {
99 99
100#define PTRACE_BTS_CONFIG 40 100#define PTRACE_BTS_CONFIG 40
101/* Configure branch trace recording. 101/* Configure branch trace recording.
102 DATA is ignored, ADDR points to a struct ptrace_bts_config. 102 ADDR points to a struct ptrace_bts_config.
103 DATA gives the size of that buffer.
103 A new buffer is allocated, iff the size changes. 104 A new buffer is allocated, iff the size changes.
105 Returns the number of bytes read.
104*/ 106*/
105#define PTRACE_BTS_STATUS 41 107#define PTRACE_BTS_STATUS 41
106/* Return the current configuration. 108/* Return the current configuration in a struct ptrace_bts_config
107 DATA is ignored, ADDR points to a struct ptrace_bts_config 109 pointed to by ADDR; DATA gives the size of that buffer.
108 that will contain the result. 110 Returns the number of bytes written.
109*/ 111*/
110#define PTRACE_BTS_SIZE 42 112#define PTRACE_BTS_SIZE 42
111/* Return the number of available BTS records. 113/* Return the number of available BTS records.
@@ -123,8 +125,8 @@ struct ptrace_bts_config {
123*/ 125*/
124#define PTRACE_BTS_DRAIN 45 126#define PTRACE_BTS_DRAIN 45
125/* Read all available BTS records and clear the buffer. 127/* Read all available BTS records and clear the buffer.
126 DATA is ignored. ADDR points to an array of struct bts_struct of 128 ADDR points to an array of struct bts_struct.
127 suitable size. 129 DATA gives the size of that buffer.
128 BTS records are read from oldest to newest. 130 BTS records are read from oldest to newest.
129 Returns number of BTS records drained. 131 Returns number of BTS records drained.
130*/ 132*/