aboutsummaryrefslogtreecommitdiffstats
path: root/arch
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 /arch
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>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/kernel/ptrace.c25
1 files changed, 21 insertions, 4 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: