[636] in linux-security and linux-alert archive
[linux-security] Patch for 1.2.13 modify_ldt hole
daemon@ATHENA.MIT.EDU (Marek Michalkiewicz)
Wed Mar 20 15:25:16 1996
From: Marek Michalkiewicz <marekm@i17linuxb.ists.pwr.wroc.pl>
To: linux-security@tarsier.cv.nrao.edu
Date: Wed, 20 Mar 1996 16:04:27 +0100 (MET)
Since the patch for the modify_ldt hole (see my previous mail) is
small (and important), I think it's OK to post it here. It should
apply cleanly to 1.2.13 as well as 1.3.x (x<72) kernels. It is
already in in 1.3.72 and newer.
Marek
diff -urN linux-1.2.13/arch/i386/kernel/ldt.c linux/arch/i386/kernel/ldt.c
--- linux-1.2.13/arch/i386/kernel/ldt.c Sun Feb 5 23:39:17 1995
+++ linux/arch/i386/kernel/ldt.c Thu Mar 7 16:24:45 1996
@@ -34,11 +34,35 @@
return size;
}
+static inline int limits_ok(struct modify_ldt_ldt_s *ldt_info)
+{
+ unsigned long base, limit;
+ /* linear address of first and last accessible byte */
+ unsigned long first, last;
+
+ base = ldt_info->base_addr;
+ limit = ldt_info->limit;
+ if (ldt_info->limit_in_pages)
+ limit = limit * PAGE_SIZE + PAGE_SIZE - 1;
+
+ first = base;
+ last = limit + base;
+
+ /* segment grows down? */
+ if (ldt_info->contents == 1) {
+ /* data segment grows down */
+ first = base+limit+1;
+ last = base+65535;
+ if (ldt_info->seg_32bit)
+ last = base-1;
+ }
+ return (last >= first && last < TASK_SIZE);
+}
+
static int write_ldt(void * ptr, unsigned long bytecount)
{
struct modify_ldt_ldt_s ldt_info;
unsigned long *lp;
- unsigned long base, limit;
int error, i;
if (bytecount != sizeof(ldt_info))
@@ -52,13 +76,7 @@
if (ldt_info.contents == 3 || ldt_info.entry_number >= LDT_ENTRIES)
return -EINVAL;
- limit = ldt_info.limit;
- base = ldt_info.base_addr;
- if (ldt_info.limit_in_pages)
- limit *= PAGE_SIZE;
-
- limit += base;
- if (limit < base || limit >= 0xC0000000)
+ if (!limits_ok(&ldt_info))
return -EINVAL;
if (!current->ldt) {