安全研究

安全漏洞
FreeBSD semconfig()系统调用本地拒绝服务漏洞

发布日期:2000-05-29
更新日期:2000-05-29

受影响系统:
所有版本FreeBSD系统
不受影响系统:
OpenBSD 2.7以及更高版本
NetBSD
描述:

FreeBSD 中的一个系统调用semconfig()可被用来执行本地的拒绝服务攻击。
System V IPC 是进程间通信的一系列接口,包括共享内存,消息队列和信号量等。
在用户空间内,这些内容由ipcs(1)及其相关的工具管理。存在一个未见诸任何文
档的系统调用semconfig() ,它没有进行正确的访问控制检查。这个系统调用正常
只是被ipcs(1)用来对系统中当前System V IPC资源情况进行自动采样,例如确保采
样进程自身的资源不被释放或者分配。 由于没有进行正常的访问控制检查,普通用
户也可以执行这个系统调用,这将导致系统中所有进程在执行exit()函数退出时挂起
,直到另一个相应的系统调用来取消挂起状态或者系统重新启动。这将导致严重的本
地拒绝服务攻击。

<* 来源:Peter Wemm <peter@FreeBSD.org>
        FreeBSD-SA-00:19   
*>


建议:
1. 更新到2000-5-1号以后到的FreeBSD 2.1.7.1-STABLE, 2.2.8-STABLE, 3.4-STABLE,
4.0-STABLE 或者 5.0-CURRENT 版本。

2. 打下列补丁,并重建内核和src/usr.bin/ipcs工具
下列补丁可以在3.4-RELEASE,3.4-STABLE, 4.0-RELEASE 和4.0-STABLE 系统使用。

1) 保存下面的内容到一个advisory文件,以root身份执行下列命令:
# cd /usr/src
# patch -p < /path/to/advisory
# cd usr.bin/ipcs
# make all install

2) 按照FreeBSD手册中的方法重建并重新安装内核和内核模块

3) 重新启动系统

下面是相应的补丁程序:
(也可以在这里下载:ftp://ftp.freebsd.org/pub/FreeBSD/CERT/patches/SA-00:19/semconfig.patch)

    --- sys/kern/syscalls.master    2000/01/19 06:01:07    1.72
    +++ sys/kern/syscalls.master    2000/05/01 11:15:10    1.72.2.1
    @@ -342,7 +342,7 @@
     221    STD    BSD    { int semget(key_t key, int nsems, int semflg); }
     222    STD    BSD    { int semop(int semid, struct sembuf *sops, \
                     u_int nsops); }
    -223    STD    BSD    { int semconfig(int flag); }
    +223    UNIMPL    NOHIDE    semconfig
     224    STD    BSD    { int msgctl(int msqid, int cmd, \
                     struct msqid_ds *buf); }
     225    STD    BSD    { int msgget(key_t key, int msgflg); }
    --- sys/kern/init_sysent.c    2000/01/19 06:02:29    1.79
    +++ sys/kern/init_sysent.c    2000/05/01 11:15:56    1.79.2.1
    @@ -243,7 +243,7 @@
         { 4, (sy_call_t *)__semctl },            /* 220 = __semctl */
         { 3, (sy_call_t *)semget },            /* 221 = semget */
         { 3, (sy_call_t *)semop },            /* 222 = semop */
    -    { 1, (sy_call_t *)semconfig },            /* 223 = semconfig */
    +    { 0, (sy_call_t *)nosys },            /* 223 = semconfig */
         { 3, (sy_call_t *)msgctl },            /* 224 = msgctl */
         { 2, (sy_call_t *)msgget },            /* 225 = msgget */
         { 4, (sy_call_t *)msgsnd },            /* 226 = msgsnd */
    --- sys/kern/syscalls.c    2000/01/19 06:02:29    1.71
    +++ sys/kern/syscalls.c    2000/05/01 11:15:56    1.71.2.1
    @@ -230,7 +230,7 @@
         "__semctl",            /* 220 = __semctl */
         "semget",            /* 221 = semget */
         "semop",            /* 222 = semop */
    -    "semconfig",            /* 223 = semconfig */
    +    "#223",            /* 223 = semconfig */
         "msgctl",            /* 224 = msgctl */
         "msgget",            /* 225 = msgget */
         "msgsnd",            /* 226 = msgsnd */
    --- sys/kern/sysv_ipc.c    2000/02/29 22:58:59    1.13
    +++ sys/kern/sysv_ipc.c    2000/05/01 11:15:56    1.13.2.1
    @@ -107,15 +107,6 @@
     semsys(p, uap)
         struct proc *p;
         struct semsys_args *uap;
    -{
    -    sysv_nosys(p, "SYSVSEM");
    -    return nosys(p, (struct nosys_args *)uap);
    -};
    -
    -int
    -semconfig(p, uap)
    -    struct proc *p;
    -    struct semconfig_args *uap;
     {
         sysv_nosys(p, "SYSVSEM");
         return nosys(p, (struct nosys_args *)uap);
    --- sys/kern/sysv_sem.c    2000/04/02 08:47:08    1.24.2.1
    +++ sys/kern/sysv_sem.c    2000/05/01 11:15:56    1.24.2.2
    @@ -26,8 +26,6 @@
     int semget __P((struct proc *p, struct semget_args *uap));
     struct semop_args;
     int semop __P((struct proc *p, struct semop_args *uap));
    -struct semconfig_args;
    -int semconfig __P((struct proc *p, struct semconfig_args *uap));
     #endif

     static struct sem_undo *semu_alloc __P((struct proc *p));
    @@ -38,7 +36,7 @@
     /* XXX casting to (sy_call_t *) is bogus, as usual. */
     static sy_call_t *semcalls[] = {
         (sy_call_t *)__semctl, (sy_call_t *)semget,
    -    (sy_call_t *)semop, (sy_call_t *)semconfig
    +    (sy_call_t *)semop
     };

     static int    semtot = 0;
    @@ -47,8 +45,6 @@
     static struct sem_undo *semu_list;     /* list of active undo structures */
     int    *semu;            /* undo structure pool */

    -static struct proc *semlock_holder = NULL;
    -
     void
     seminit(dummy)
         void *dummy;
    @@ -87,64 +83,12 @@
         } */ *uap;
     {

    -    while (semlock_holder != NULL && semlock_holder != p)
    -        (void) tsleep((caddr_t)&semlock_holder, (PZERO - 4), "semsys", 0);
    -
         if (uap->which >= sizeof(semcalls)/sizeof(semcalls[0]))
             return (EINVAL);
         return ((*semcalls[uap->which])(p, &uap->a2));
     }

     /*
    - * Lock or unlock the entire semaphore facility.
    - *
    - * This will probably eventually evolve into a general purpose semaphore
    - * facility status enquiry mechanism (I don't like the "read /dev/kmem"
    - * approach currently taken by ipcs and the amount of info that we want
    - * to be able to extract for ipcs is probably beyond what the capability
    - * of the getkerninfo facility.
    - *
    - * At the time that the current version of semconfig was written, ipcs is
    - * the only user of the semconfig facility.  It uses it to ensure that the
    - * semaphore facility data structures remain static while it fishes around
    - * in /dev/kmem.
    - */
    -
    -#ifndef _SYS_SYSPROTO_H_
    -struct semconfig_args {
    -    semconfig_ctl_t    flag;
    -};
    -#endif
    -
    -int
    -semconfig(p, uap)
    -    struct proc *p;
    -    struct semconfig_args *uap;
    -{
    -    int eval = 0;
    -
    -    switch (uap->flag) {
    -    case SEM_CONFIG_FREEZE:
    -        semlock_holder = p;
    -        break;
    -
    -    case SEM_CONFIG_THAW:
    -        semlock_holder = NULL;
    -        wakeup((caddr_t)&semlock_holder);
    -        break;
    -
    -    default:
    -        printf("semconfig: unknown flag parameter value (%d) - ignored\n",
    -            uap->flag);
    -        eval = EINVAL;
    -        break;
    -    }
    -
    -    p->p_retval[0] = 0;
    -    return(eval);
    -}
    -
    -/*
      * Allocate a new sem_undo structure for a process
      * (returns ptr to structure or NULL if no more room)
      */
    @@ -873,17 +817,6 @@
         register struct sem_undo **supptr;
         int did_something;

    -    /*
    -     * If somebody else is holding the global semaphore facility lock
    -     * then sleep until it is released.
    -     */
    -    while (semlock_holder != NULL && semlock_holder != p) {
    -#ifdef SEM_DEBUG
    -        printf("semaphore facility locked - sleeping ...\n");
    -#endif
    -        (void) tsleep((caddr_t)&semlock_holder, (PZERO - 4), "semext", 0);
    -    }
    -
         did_something = 0;

         /*
    @@ -898,7 +831,7 @@
         }

         if (suptr == NULL)
    -        goto unlock;
    +        return;

     #ifdef SEM_DEBUG
         printf("proc @%08x has undo structure with %d entries\n", p,
    @@ -955,14 +888,4 @@
     #endif
         suptr->un_proc = NULL;
         *supptr = suptr->un_next;
    -
    -unlock:
    -    /*
    -     * If the exiting process is holding the global semaphore facility
    -     * lock then release it.
    -     */
    -    if (semlock_holder == p) {
    -        semlock_holder = NULL;
    -        wakeup((caddr_t)&semlock_holder);
    -    }
     }

    --- sys/sys/sem.h    1999/12/29 04:24:46    1.20
    +++ sys/sys/sem.h    2000/05/01 11:15:58    1.20.2.1
    @@ -163,13 +163,5 @@
      * Process sem_undo vectors at proc exit.
      */
     void    semexit __P((struct proc *p));
    -
    -/*
    - * Parameters to the semconfig system call
    - */
    -typedef enum {
    -    SEM_CONFIG_FREEZE,    /* Freeze the semaphore facility. */
    -    SEM_CONFIG_THAW        /* Thaw the semaphore facility. */
    -} semconfig_ctl_t;
     #endif /* _KERNEL */

    --- sys/sys/syscall-hide.h    2000/01/19 06:02:31    1.65
    +++ sys/sys/syscall-hide.h    2000/05/01 11:15:58    1.65.2.1
    @@ -191,7 +191,6 @@
     HIDE_BSD(__semctl)
     HIDE_BSD(semget)
     HIDE_BSD(semop)
    -HIDE_BSD(semconfig)
     HIDE_BSD(msgctl)
     HIDE_BSD(msgget)
     HIDE_BSD(msgsnd)
    --- sys/sys/syscall.h    2000/01/19 06:02:31    1.69
    +++ sys/sys/syscall.h    2000/05/01 11:15:59    1.69.2.1
    @@ -196,7 +196,6 @@
     #define    SYS___semctl    220
     #define    SYS_semget    221
     #define    SYS_semop    222
    -#define    SYS_semconfig    223
     #define    SYS_msgctl    224
     #define    SYS_msgget    225
     #define    SYS_msgsnd    226
    --- sys/sys/syscall.mk    2000/01/19 06:07:34    1.23
    +++ sys/sys/syscall.mk    2000/05/01 11:15:59    1.23.2.1
    @@ -148,7 +148,6 @@
         __semctl.o \
         semget.o \
         semop.o \
    -    semconfig.o \
         msgctl.o \
         msgget.o \
         msgsnd.o \
    --- sys/sys/sysproto.h    2000/01/19 06:02:31    1.59
    +++ sys/sys/sysproto.h    2000/05/01 11:16:00    1.59.2.1
    @@ -662,9 +662,6 @@
         struct sembuf *    sops;    char sops_[PAD_(struct sembuf *)];
         u_int    nsops;    char nsops_[PAD_(u_int)];
     };
    -struct    semconfig_args {
    -    int    flag;    char flag_[PAD_(int)];
    -};
     struct    msgctl_args {
         int    msqid;    char msqid_[PAD_(int)];
         int    cmd;    char cmd_[PAD_(int)];
    @@ -1158,7 +1155,6 @@
     int    __semctl __P((struct proc *, struct __semctl_args *));
     int    semget __P((struct proc *, struct semget_args *));
     int    semop __P((struct proc *, struct semop_args *));
    -int    semconfig __P((struct proc *, struct semconfig_args *));
     int    msgctl __P((struct proc *, struct msgctl_args *));
     int    msgget __P((struct proc *, struct msgget_args *));
     int    msgsnd __P((struct proc *, struct msgsnd_args *));
    --- usr.bin/ipcs/ipcs.c    1999/12/29 05:05:32    1.12
    +++ usr.bin/ipcs/ipcs.c    2000/05/01 10:51:37    1.12.2.1
    @@ -56,7 +56,6 @@
     struct shminfo    shminfo;
     struct shmid_ds    *shmsegs;

    -int    semconfig __P((int,...));
     void    usage __P((void));

     static struct nlist symbols[] = {
    @@ -420,11 +419,6 @@
                     seminfo.semaem);
             }
             if (display & SEMINFO) {
    -            if (semconfig(SEM_CONFIG_FREEZE) != 0) {
    -                perror("semconfig");
    -                fprintf(stderr,
    -                    "Can't lock semaphore facility - winging it...\n");
    -            }
                 kvm_read(kd, symbols[X_SEMA].n_value, &sema, sizeof(sema));
                 xsema = malloc(sizeof(struct semid_ds) * seminfo.semmni);
                 kvm_read(kd, (u_long) sema, xsema, sizeof(struct semid_ds) * seminfo.semmni);
    @@ -470,8 +464,6 @@
                         printf("\n");
                     }
                 }
    -
    -            (void) semconfig(SEM_CONFIG_THAW);

                 printf("\n");
             }



浏览次数:6392
严重程度:0(网友投票)
本安全漏洞由绿盟科技翻译整理,版权所有,未经许可,不得转载
绿盟科技给您安全的保障