Ticket #24037: 0001-use-blacklist-rather-than-whitelist-in-syscall-hijac.patch

File 0001-use-blacklist-rather-than-whitelist-in-syscall-hijac.patch, 15.9 KB (added by ertosns, 12 months ago)

implement the first solution

  • src/lib/syscall.c

    From a9b17a085074a7d424fce9ff9ffd0b56580a5af0 Mon Sep 17 00:00:00 2001
    From: ertosns <ertosnsbot@yahoo.com>
    Date: Sun, 19 Nov 2017 14:01:19 +0200
    Subject: [PATCH] use blacklist rather than whitelist in syscall hijacking
    
    ---
     src/lib/syscall.c | 609 +++---------------------------------------------------
     1 file changed, 33 insertions(+), 576 deletions(-)
    
    diff --git a/src/lib/syscall.c b/src/lib/syscall.c
    index 41cba28..5e1d056 100644
    a b  
    2727TSOCKS_LIBC_DECL(syscall, LIBC_SYSCALL_RET_TYPE, LIBC_SYSCALL_SIG)
    2828
    2929/*
    30  * Handle close syscall to be called with tsocks call.
    31  */
    32 static LIBC_CLOSE_RET_TYPE handle_close(va_list args)
    33 {
    34         int fd;
    35 
    36         fd = va_arg(args, int);
    37 
    38         return tsocks_close(fd);
    39 }
    40 
    41 /*
    42  * Handle socket syscall to go through Tor.
    43  */
    44 static LIBC_SOCKET_RET_TYPE handle_socket(va_list args)
    45 {
    46         int domain, type, protocol;
    47 
    48         domain = va_arg(args, int);
    49         type = va_arg(args, int);
    50         protocol = va_arg(args, int);
    51 
    52         return tsocks_socket(domain, type, protocol);
    53 }
    54 
    55 /*
    56  * Handle connect syscall to go through Tor.
    57  */
    58 static LIBC_CONNECT_RET_TYPE handle_connect(va_list args)
    59 {
    60         int sockfd;
    61         const struct sockaddr *addr;
    62         socklen_t addrlen;
    63 
    64         sockfd = va_arg(args, int);
    65         addr = va_arg(args, const struct sockaddr *);
    66         addrlen = va_arg(args, socklen_t);
    67 
    68         return tsocks_connect(sockfd, addr, addrlen);
    69 }
    70 
    71 /*
    72  * Handle accept(2) syscall to go through Tor.
    73  */
    74 static LIBC_ACCEPT_RET_TYPE handle_accept(va_list args)
    75 {
    76         int sockfd;
    77         struct sockaddr *addr;
    78         socklen_t addrlen;
    79 
    80         sockfd = va_arg(args, __typeof__(sockfd));
    81         addr = va_arg(args, __typeof__(addr));
    82         addrlen = va_arg(args, __typeof__(addrlen));
    83 
    84         return tsocks_accept(sockfd, addr, &addrlen);
    85 }
    86 
    87 #if !((defined(__NetBSD__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)) && defined(__x86_64))
    88 /*
    89  * Handle mmap(2) syscall.
    90  */
    91 static LIBC_SYSCALL_RET_TYPE handle_mmap(va_list args)
    92 {
    93         void *addr;
    94         size_t len;
    95         int prot, flags, fd;
    96         off_t offset;
    97 
    98         addr = va_arg(args, __typeof__(addr));
    99         len = va_arg(args, __typeof__(len));
    100         prot = va_arg(args, __typeof__(prot));
    101         flags = va_arg(args, __typeof__(flags));
    102         fd = va_arg(args, __typeof__(fd));
    103         offset = va_arg(args, __typeof__(offset));
    104 
    105         return (LIBC_SYSCALL_RET_TYPE) mmap(addr, len, prot, flags, fd, offset);
    106 }
    107 #endif /* __NetBSD__, __FreeBSD__, __FreeBSD_kernel__, __x86_64 */
    108 
    109 /*
    110  * Handle munmap(2) syscall.
    111  */
    112 static LIBC_SYSCALL_RET_TYPE handle_munmap(va_list args)
    113 {
    114         void *addr;
    115         size_t len;
    116 
    117         addr = va_arg(args, __typeof__(addr));
    118         len = va_arg(args, __typeof__(len));
    119 
    120         return (LIBC_SYSCALL_RET_TYPE) munmap(addr, len);
    121 }
    122 
    123 /*
    124  * Handle getpeername(2) syscall.
    125  */
    126 static LIBC_GETPEERNAME_RET_TYPE handle_getpeername(va_list args)
    127 {
    128         int sockfd;
    129         struct sockaddr *addr;
    130         socklen_t *addrlen;
    131 
    132         sockfd = va_arg(args, __typeof__(sockfd));
    133         addr = va_arg(args, __typeof__(addr));
    134         addrlen = va_arg(args, __typeof__(addrlen));
    135 
    136         return tsocks_getpeername(sockfd, addr, addrlen);
    137 }
    138 
    139 /*
    140  * Handle listen(2) syscall.
    141  */
    142 static LIBC_LISTEN_RET_TYPE handle_listen(va_list args)
    143 {
    144         int sockfd, backlog;
    145 
    146         sockfd = va_arg(args, __typeof__(sockfd));
    147         backlog = va_arg(args, __typeof__(backlog));
    148 
    149         return tsocks_listen(sockfd, backlog);
    150 }
    151 
    152 /*
    153  * Handle recvmsg(2) syscall.
    154  */
    155 static LIBC_RECVMSG_RET_TYPE handle_recvmsg(va_list args)
    156 {
    157         int sockfd, flags;
    158         struct msghdr *msg;
    159 
    160         sockfd = va_arg(args, __typeof__(sockfd));
    161         msg = va_arg(args, __typeof__(msg));
    162         flags = va_arg(args, __typeof__(flags));
    163 
    164         return tsocks_recvmsg(sockfd, msg, flags);
    165 }
    166 
    167 #if defined(__linux__)
    168 
    169 /*
    170  * Handle sched_getaffinity(2) syscall.
    171  * NOTE: ffmpeg is one of the application that needs this one on the
    172  * whitelist.
    173  */
    174 static LIBC_SYSCALL_RET_TYPE handle_sched_getaffinity(va_list args)
    175 {
    176         pid_t pid;
    177         size_t cpusetsize;
    178         cpu_set_t *mask;
    179 
    180         pid = va_arg(args, __typeof__(pid));
    181         cpusetsize = va_arg(args, __typeof__(cpusetsize));
    182         mask = va_arg(args, __typeof__(mask));
    183 
    184         return tsocks_libc_syscall(TSOCKS_NR_SCHED_GETAFFINITY, pid, cpusetsize,
    185                         mask);
    186 }
    187 
    188 /*
    189  * Handle gettid(2) syscall.
    190  */
    191 static LIBC_SYSCALL_RET_TYPE handle_gettid(void)
    192 {
    193         return tsocks_libc_syscall(TSOCKS_NR_GETTID);
    194 }
    195 
    196 /*
    197  * Handle getrandom(2) syscall.
    198  */
    199 static LIBC_SYSCALL_RET_TYPE handle_getrandom(va_list args)
    200 {
    201         void *buf;
    202         size_t buflen;
    203         unsigned int flags;
    204 
    205         buf = va_arg(args, __typeof__(buf));
    206         buflen = va_arg(args, __typeof__(buflen));
    207         flags = va_arg(args, __typeof__(flags));
    208 
    209         return tsocks_libc_syscall(TSOCKS_NR_GETRANDOM, buf, buflen, flags);
    210 }
    211 
    212 /*
    213  * Handle futex(2) syscall.
    214  */
    215 static LIBC_SYSCALL_RET_TYPE handle_futex(va_list args)
    216 {
    217         /* This assumes Linux 2.6.7 or later, as that is when 'val3' was
    218          * added to futex(2).  Kernel versions prior to that are what I
    219          * would consider historic.
    220          */
    221         const struct timespec *timeout;
    222         int *uaddr, *uaddr2;
    223         int op, val, val3;
    224 
    225         uaddr = va_arg(args, __typeof__(uaddr));
    226         op = va_arg(args, __typeof__(op));
    227         val = va_arg(args, __typeof__(val));
    228         timeout = va_arg(args, __typeof__(timeout));
    229         uaddr2 = va_arg(args, __typeof__(uaddr2));
    230         val3 = va_arg(args, __typeof__(val3));
    231 
    232         return tsocks_libc_syscall(TSOCKS_NR_FUTEX, uaddr, op, val, timeout,
    233                         uaddr2, val3);
    234 }
    235 
    236 /*
    237  * Handle accept4(2) syscall.
    238  */
    239 static LIBC_SYSCALL_RET_TYPE handle_accept4(va_list args)
    240 {
    241         int sockfd;
    242         struct sockaddr *addr;
    243         socklen_t addrlen;
    244         int flags;
    245 
    246         sockfd = va_arg(args, __typeof__(sockfd));
    247         addr = va_arg(args, __typeof__(addr));
    248         addrlen = va_arg(args, __typeof__(addrlen));
    249         flags = va_arg(args, __typeof__(flags));
    250 
    251         return tsocks_accept4(sockfd, addr, &addrlen, flags);
    252 }
    253 
    254 /*
    255  * Handle epoll_create1(2) syscall.
    256  */
    257 static LIBC_SYSCALL_RET_TYPE handle_epoll_create1(va_list args)
    258 {
    259         int flags;
    260 
    261         flags = va_arg(args, __typeof__(flags));
    262 
    263         return epoll_create1(flags);
    264 }
    265 
    266 /*
    267  * Handle epoll_wait(2) syscall.
    268  */
    269 static LIBC_SYSCALL_RET_TYPE handle_epoll_wait(va_list args)
    270 {
    271         int epfd;
    272         struct epoll_event *events;
    273         int maxevents;
    274         int timeout;
    275 
    276         epfd = va_arg(args, __typeof__(epfd));
    277         events = va_arg(args, __typeof__(events));
    278         maxevents = va_arg(args, __typeof__(maxevents));
    279         timeout = va_arg(args, __typeof__(maxevents));
    280 
    281         return epoll_wait(epfd, events, maxevents, timeout);
    282 }
    283 
    284 /*
    285  * Handle epoll_pwait(2) syscall.
    286  */
    287 static LIBC_SYSCALL_RET_TYPE handle_epoll_pwait(va_list args)
    288 {
    289         int epfd;
    290         struct epoll_event *events;
    291         int maxevents;
    292         int timeout;
    293         const sigset_t *sigmask;
    294 
    295         epfd = va_arg(args, __typeof__(epfd));
    296         events = va_arg(args, __typeof__(events));
    297         maxevents = va_arg(args, __typeof__(maxevents));
    298         timeout = va_arg(args, __typeof__(maxevents));
    299         sigmask = va_arg(args, __typeof__(sigmask));
    300 
    301         return epoll_pwait(epfd, events, maxevents, timeout, sigmask);
    302 }
    303 
    304 /*
    305  * Handle epoll_ctl(2) syscall.
    306  */
    307 static LIBC_SYSCALL_RET_TYPE handle_epoll_ctl(va_list args)
    308 {
    309         int epfd;
    310         int op;
    311         int fd;
    312         struct epoll_event *event;
    313 
    314         epfd = va_arg(args, __typeof__(epfd));
    315         op = va_arg(args, __typeof__(op));
    316         fd = va_arg(args, __typeof__(fd));
    317         event = va_arg(args, __typeof__(event));
    318 
    319         return epoll_ctl(epfd, op, fd, event);
    320 }
    321 
    322 /*
    323  * Handle eventfd2(2) syscall.
    324  */
    325 static LIBC_SYSCALL_RET_TYPE handle_eventfd2(va_list args)
    326 {
    327         unsigned int initval;
    328         int flags;
    329 
    330         initval = va_arg(args, __typeof__(initval));
    331         flags = va_arg(args, __typeof__(flags));
    332 
    333         return eventfd(initval, flags);
    334 }
    335 
    336 /*
    337  * Handle inotify_init1(2) syscall.
    338  */
    339 static LIBC_SYSCALL_RET_TYPE handle_inotify_init1(va_list args)
    340 {
    341         int flags;
    342         flags = va_arg(args, __typeof__(flags));
    343 
    344         return inotify_init1(flags);
    345 }
    346 
    347 /*
    348  * Handle inotify_add_watch(2) syscall.
    349  */
    350 static LIBC_SYSCALL_RET_TYPE handle_inotify_add_watch(va_list args)
    351 {
    352         int fd;
    353         const char *pathname;
    354         uint32_t mask;
    355 
    356         fd = va_arg(args, __typeof__(fd));
    357         pathname = va_arg(args, __typeof__(pathname));
    358         mask = va_arg(args, __typeof__(mask));
    359 
    360         return inotify_add_watch(fd, pathname, mask);
    361 }
    362 
    363 /*
    364  * Handle inotify_rm_watch(2) syscall.
    365  */
    366 static LIBC_SYSCALL_RET_TYPE handle_inotify_rm_watch(va_list args)
    367 {
    368         int fd, wd;
    369 
    370         fd = va_arg(args, __typeof__(fd));
    371         wd = va_arg(args, __typeof__(wd));
    372 
    373         return inotify_rm_watch(fd, wd);
    374 }
    375 
    376 /*
    377  * Handle seccomp(2) syscall.
    378  */
    379 static LIBC_SYSCALL_RET_TYPE handle_seccomp(va_list args)
    380 {
    381         unsigned int operation, flags;
    382         void *sargs;
    383 
    384         operation = va_arg(args, __typeof__(operation));
    385         flags = va_arg(args, __typeof__(flags));
    386         sargs = va_arg(args, __typeof__(sargs));
    387 
    388         return tsocks_libc_syscall(TSOCKS_NR_SECCOMP, operation, flags, sargs);
    389 }
    390 
    391 /*
    392  * Handle gettimeofday(2) syscall.
    393  */
    394 static LIBC_SYSCALL_RET_TYPE handle_gettimeofday(va_list args)
    395 {
    396         struct timeval *tv;
    397         struct timezone *tz;
    398 
    399         tv = va_arg(args, __typeof__(tv));
    400         tz = va_arg(args, __typeof__(tz));
    401 
    402         return tsocks_libc_syscall(TSOCKS_NR_GETTIMEOFDAY, tv, tz);
    403 }
    404 
    405 /*
    406  * Handle clock_gettime(2) syscall.
    407  */
    408 static LIBC_SYSCALL_RET_TYPE handle_clock_gettime(va_list args)
    409 {
    410         clockid_t clk_id;
    411         struct timespec *tp;
    412 
    413         clk_id = va_arg(args, __typeof__(clk_id));
    414         tp = va_arg(args, __typeof__(tp));
    415 
    416         return tsocks_libc_syscall(TSOCKS_NR_CLOCK_GETTIME, clk_id, tp);
    417 }
    418 
    419 /*
    420  * Handle fork(2) syscall.
    421  */
    422 static LIBC_SYSCALL_RET_TYPE handle_fork(void)
    423 {
    424         return tsocks_libc_syscall(TSOCKS_NR_FORK);
    425 }
    426 #endif /* __linux__ */
    427 
    428 /*
    42930 * Torsocks call for syscall(2)
    43031 */
    43132LIBC_SYSCALL_RET_TYPE tsocks_syscall(long int number, va_list args)
    43233{
    43334        LIBC_SYSCALL_RET_TYPE ret;
    434 
     35        unsigned long a0, a1, a2, a3, a4, a5;
     36        a0 = va_arg(args, __typeof__(a0));
     37        a1 = va_arg(args, __typeof__(a1));
     38        a2 = va_arg(args, __typeof__(a2));
     39        a3 = va_arg(args, __typeof__(a3));
     40        a4 = va_arg(args, __typeof__(a4));
     41        a5 = va_arg(args, __typeof__(a5));
    43542        switch (number) {
    43643        case TSOCKS_NR_SOCKET:
    437                 ret = handle_socket(args);
    438                 break;
     44          //hijacking accept4(2)
     45          ret = tsocks_socket(a0, a1, a2);
     46          break;
    43947        case TSOCKS_NR_CONNECT:
    440                 ret = handle_connect(args);
    441                 break;
     48          //hijacking accept4(2)
     49          ret = tsocks_connect(a0, (const struct sockaddr *)a1, a2);
     50          break;
    44251        case TSOCKS_NR_CLOSE:
    443                 ret = handle_close(args);
    444                 break;
    445         case TSOCKS_NR_MMAP:
    446 #if (defined(__NetBSD__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)) && defined(__x86_64)
    447                 /*
    448                  * On an 64 bit *BSD system, __syscall(2) should be used for mmap().
    449                  * This is NOT suppose to happen but for protection we deny that call.
    450                  */
    451                 ret = -1;
    452                 errno = ENOSYS;
    453 #else
    454                 /*
    455                  * The mmap/munmap syscall are handled here for a very specific case so
    456                  * buckle up here for the explanation :).
    457                  *
    458                  * Considering an application that handles its own memory using a
    459                  * malloc(2) hook for instance *AND* mmap() is called with syscall(),
    460                  * we have to route the call to the libc in order to complete the
    461                  * syscall() symbol lookup.
    462                  *
    463                  * The lookup process of the libdl (using dlsym(3)) calls at some point
    464                  * malloc for a temporary buffer so we end up in this torsocks wrapper
    465                  * when mmap() is called to create a new memory region for the
    466                  * application (remember the malloc hook). When getting here, the libc
    467                  * syscall() symbol is NOT yet populated because we are in the lookup
    468                  * code path. For this, we directly call mmap/munmap using the libc so
    469                  * the lookup can be completed.
    470                  *
    471                  * This crazy situation is present in Mozilla Firefox which handles its
    472                  * own memory using mmap() called by syscall(). Same for munmap().
    473                  */
    474                 ret = handle_mmap(args);
    475 #endif /* __NetBSD__, __FreeBSD__, __FreeBSD_kernel__, __x86_64 */
    476                 break;
    477         case TSOCKS_NR_MUNMAP:
    478                 ret = handle_munmap(args);
    479                 break;
     52          //hijacking accept4(2)
     53          ret = tsocks_close(a0);
     54          break;
    48055        case TSOCKS_NR_ACCEPT:
    481                 ret = handle_accept(args);
    482                 break;
     56          //hijacking accept4(2)
     57          ret = tsocks_accept(a0, (struct sockaddr *)a1, (socklen_t *)a2);
     58          break;
    48359        case TSOCKS_NR_GETPEERNAME:
    484                 ret = handle_getpeername(args);
    485                 break;
     60          //hijacking accept4(2)
     61          ret = tsocks_getpeername(a0, (struct sockaddr *)a1, (socklen_t *)a2);
     62          break;
    48663        case TSOCKS_NR_LISTEN:
    487                 ret = handle_listen(args);
    488                 break;
     64          //hijacking accept4(2)
     65          ret = tsocks_listen(a0, a1);
     66          break;
    48967        case TSOCKS_NR_RECVMSG:
    490                 ret = handle_recvmsg(args);
    491                 break;
     68          //hijacking accept4(2)
     69          ret = tsocks_recvmsg(a0, (struct msghdr *)a1, a2);
     70          break;
    49271#if defined(__linux__)
    493         case TSOCKS_NR_GETTID:
    494                 ret = handle_gettid();
    495                 break;
    496         case TSOCKS_NR_GETRANDOM:
    497                 ret = handle_getrandom(args);
    498                 break;
    499         case TSOCKS_NR_FUTEX:
    500                 ret = handle_futex(args);
    501                 break;
    50272        case TSOCKS_NR_ACCEPT4:
    503                 ret = handle_accept4(args);
    504                 break;
    505         case TSOCKS_NR_EPOLL_CREATE1:
    506                 ret = handle_epoll_create1(args);
    507                 break;
    508         case TSOCKS_NR_EPOLL_WAIT:
    509                 ret = handle_epoll_wait(args);
    510                 break;
    511         case TSOCKS_NR_EPOLL_PWAIT:
    512                 ret = handle_epoll_pwait(args);
    513                 break;
    514         case TSOCKS_NR_EPOLL_CTL:
    515                 ret = handle_epoll_ctl(args);
    516                 break;
    517         case TSOCKS_NR_EVENTFD2:
    518                 ret = handle_eventfd2(args);
    519                 break;
    520         case TSOCKS_NR_INOTIFY_INIT1:
    521                 ret = handle_inotify_init1(args);
    522                 break;
    523         case TSOCKS_NR_INOTIFY_ADD_WATCH:
    524                 ret = handle_inotify_add_watch(args);
    525                 break;
    526         case TSOCKS_NR_INOTIFY_RM_WATCH:
    527                 ret = handle_inotify_rm_watch(args);
    528                 break;
    529         case TSOCKS_NR_SCHED_GETAFFINITY:
    530                 ret = handle_sched_getaffinity(args);
    531                 break;
    532         case TSOCKS_NR_SECCOMP:
    533                 ret = handle_seccomp(args);
    534                 break;
    535         case TSOCKS_NR_GETTIMEOFDAY:
    536                 ret = handle_gettimeofday(args);
    537                 break;
    538         case TSOCKS_NR_CLOCK_GETTIME:
    539                 ret = handle_clock_gettime(args);
    540                 break;
    541         case TSOCKS_NR_FORK:
    542                 ret = handle_fork();
    543                 break;
    544 #endif /* __linux__ */
     73          //hijacking accept4(2)
     74          ret = tsocks_accept4(a0, (struct sockaddr *)a1, (socklen_t *)a2, a3);
     75          break;
     76#endif
    54577        default:
    546                 /*
    547                  * Because of the design of syscall(), we can't pass a va_list to it so
    548                  * we are constraint to use a whitelist scheme and denying the rest.
    549                  */
    550                 WARN("[syscall] Unsupported syscall number %ld. Denying the call",
    551                                 number);
    552                 ret = -1;
    553                 errno = ENOSYS;
    554                 break;
     78          tsocks_libc_syscall(number, a0, a1, a2, a3, a4, a5);
    55579        }
    55680
    55781        return ret;
    LIBC_SYSCALL_DECL 
    577101
    578102        return ret;
    579103}
    580 
    581 /* Only used for *BSD systems. */
    582 #if (defined(__NetBSD__) || defined(__FreeBSD__))
    583 
    584 /* __syscall(2) */
    585 TSOCKS_LIBC_DECL(__syscall, LIBC___SYSCALL_RET_TYPE, LIBC___SYSCALL_SIG)
    586 
    587 /*
    588  * Handle *BSD mmap(2) syscall.
    589  */
    590 static LIBC___SYSCALL_RET_TYPE handle_bsd_mmap(va_list args)
    591 {
    592         void *addr;
    593         size_t len;
    594         int prot, flags, fd;
    595         off_t offset;
    596 
    597         addr = va_arg(args, __typeof__(addr));
    598         len = va_arg(args, __typeof__(len));
    599         prot = va_arg(args, __typeof__(prot));
    600         flags = va_arg(args, __typeof__(flags));
    601         fd = va_arg(args, __typeof__(fd));
    602         offset = va_arg(args, __typeof__(offset));
    603 
    604         return (LIBC___SYSCALL_RET_TYPE) mmap(addr, len, prot, flags, fd, offset);
    605 }
    606 
    607 LIBC___SYSCALL_RET_TYPE tsocks___syscall(quad_t number, va_list args)
    608 {
    609         LIBC_SYSCALL_RET_TYPE ret;
    610 
    611         switch (number) {
    612         case TSOCKS_NR_MMAP:
    613                 /*
    614                  * Please see the mmap comment in the syscall() function to understand
    615                  * why mmap is being hijacked.
    616                  */
    617                 ret = handle_bsd_mmap(args);
    618                 break;
    619         default:
    620                 /*
    621                  * Because of the design of syscall(), we can't pass a va_list to it so
    622                  * we are constraint to use a whitelist scheme and denying the rest.
    623                  */
    624                 WARN("[syscall] Unsupported __syscall number %ld. Denying the call",
    625                                 number);
    626                 ret = -1;
    627                 errno = ENOSYS;
    628                 break;
    629         }
    630 
    631         return ret;
    632 }
    633 
    634 LIBC___SYSCALL_DECL
    635 {
    636         LIBC___SYSCALL_RET_TYPE ret;
    637         va_list args;
    638 
    639         va_start(args, number);
    640         ret = tsocks___syscall(number, args);
    641         va_end(args);
    642 
    643         return ret;
    644 }
    645 
    646 #endif /* __NetBSD__, __FreeBSD__ */