FreeBSD I386_Set_LDT()多个本地拒绝服务漏洞

漏洞信息详情

FreeBSD I386_Set_LDT()多个本地拒绝服务漏洞

漏洞简介

FreeBSD就是一种运行在Intel平台上、可以自由使用的开放源码Unix类系统。

FreeBSD中的i386_set_ldt()调用允许用户系统的程序动态管理每个进程的本地描述符表。由于使用了有符号的整数且缺少输入验证,内核中bzero可能会被要求处理很大的参数,漏洞代码如下:

415 int error = 0, i;

416 int largest_ld;

..

449 largest_ld = uap->start + uap->num;

450 if (largest_ld > pldt->ldt_len)

451 largest_ld = pldt->ldt_len;

452 i = largest_ld – uap->start;

453 bzero( &((union descriptor *)(pldt->ldt_base))[uap->start],

454 sizeof(union descriptor) * i);

在415和416行,\”i\”和\”largest_ld\”变量都是有符的整数。在449行,同时添加了uap->start和uap->num,这两个变量都是用户控制的且没有经过正确的检查。在452行,可以将\”i\”设置为很大的负值,导致在453行以很大的长度参数调用bzero。无效的内存访问会导致内核忙碌。

i386_set_ldt()系统调用会在LDT中设置当前进程的i386描述符列表。该调用接受一个开始选择器数(start)、包含有将要设置描述符的内存数组(descs),以及将要设置的条目数(num)。用户在通过sysarch()调用i386_set_ldt()时,如果将start参数设置为很低的整数值、将descs设置为非空的值,并将num设置为很高的无符整数值,就会触发largest_ld和descs_size(533和540行)中的整数溢出,导致耗尽所有可用的系统资源(541行)。此外还可以将start参数设置为低整数值、descs设置为空、num设置为很高的无符整数值触发largest_ld(515行)中的整数溢出,导致删除系统中的敏感数据(519和520行)。有漏洞的函数如下:

476 static int

477 i386_set_ldt(td, args)

478 struct thread *td;

479 char *args;

480 {

481 int error = 0, i;

482 int largest_ld;

483 struct mdproc *mdp = &td->td_proc->p_md;

484 struct proc_ldt *pldt = 0;

485 struct i386_ldt_args ua, *uap = &ua;

486 union descriptor *descs, *dp;

487 int descs_size;

488

489 if ((error = copyin(args, uap, sizeof(struct

i386_ldt_args))) < 0)

490 return(error);

491

492 #ifdef DEBUG

493 printf(\”i386_set_ldt: start=\\%d num=\\%d descs=\\%p\n\”,

494 uap->start, uap->num, (void *)uap->descs);

495 #endif

496

497 if (uap->descs == NULL) {

498 /* Free descriptors */

499 if (uap->start == 0 & & uap->num == 0) {

500 /*

501 * Treat this as a special case, so userland

needn\’\’t

502 * know magic number NLDT.

503 */

504 uap->start = NLDT;

505 uap->num = MAX_LD – NLDT;

506 }

507 if (uap->start <= LUDATA_SEL || uap->num <= 0)508 return (EINVAL);

509 mtx_lock_spin( &sched_lock);

510 pldt = mdp->md_ldt;

511 if (pldt == NULL || uap->start >= pldt->ldt_len) {

512 mtx_unlock_spin( &sched_lock);

513 return (0);

514 }

515 largest_ld = uap->start + uap->num;

516 if (largest_ld > pldt->ldt_len)

517 largest_ld = pldt->ldt_len;

518 i = largest_ld – uap->start;

519 bzero( &((union descriptor

*)(pldt->ldt_base))[uap->start],

520 sizeof(union descriptor) * i);

521 mtx_unlock_spin( &sched_lock);

522 return (0);

523 }

524

525 if (!(uap->start == LDT_AUTO_ALLOC & & uap->num == 1)) {

526 /* complain a for a while if using old methods */

527 if (ldt_warnings++ < NUM_LDT_WARNINGS) {

528 printf(\”Warning: pid \\%d used static ldt

allocation.\n\”,

529 td->td_proc->p_pid);

530 printf(\”See the i386_set_ldt man page for

more info\n\”);

531 }

532 /* verify range of descriptors to modify */

533 largest_ld = uap->start + uap->num;

534 if (uap->start >= MAX_LD ||

535 uap->num < 0 || largest_ld > MAX_LD) {

536 return (EINVAL);

537 }

538 }

539

540 descs_size = uap->num * sizeof(union descriptor);

541 descs = (union descriptor *)kmem_alloc(kernel_map, descs_size);

542 if (descs == NULL)

543 return (ENOMEM);

544 error = copyin(uap->descs

漏洞公告

目前厂商已经发布了升级补丁以修复这个安全问题,补丁下载链接:

http://www.freebsd.org/security/index.html

参考网址

来源: IDEFENSE

名称: 20060923 FreeBSD i386_set_ldt Integer Signedness Vulnerability

链接:http://www.idefense.com/intelligence/vulnerabilities/display.php?id=415

来源: BID

名称: 20158

链接:http://www.securityfocus.com/bid/20158

来源: BUGTRAQ

名称: 20060925 iDefense Security Advisory 09.23.06: FreeBSD i386_set_ldt Integer Signedness Vulnerability

链接:http://www.securityfocus.com/archive/1/archive/1/446946/100/0/threaded

来源: SECTRACK

名称: 1016927

链接:http://securitytracker.com/id?1016927

来源: SECUNIA

名称: 22064

链接:http://secunia.com/advisories/22064

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享