LCOV - code coverage report
Current view: top level - strace_git - ioctl.c (source / functions) Hit Total Coverage
Test: strace-4.16.0.69.f1ea-dirty Code Coverage Lines: 129 159 81.1 %
Date: 2017-03-18 00:38:52 Functions: 9 9 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 79 110 71.8 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
       3                 :            :  * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
       4                 :            :  * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
       5                 :            :  * Copyright (c) 1996-2001 Wichert Akkerman <wichert@cistron.nl>
       6                 :            :  * All rights reserved.
       7                 :            :  *
       8                 :            :  * Redistribution and use in source and binary forms, with or without
       9                 :            :  * modification, are permitted provided that the following conditions
      10                 :            :  * are met:
      11                 :            :  * 1. Redistributions of source code must retain the above copyright
      12                 :            :  *    notice, this list of conditions and the following disclaimer.
      13                 :            :  * 2. Redistributions in binary form must reproduce the above copyright
      14                 :            :  *    notice, this list of conditions and the following disclaimer in the
      15                 :            :  *    documentation and/or other materials provided with the distribution.
      16                 :            :  * 3. The name of the author may not be used to endorse or promote products
      17                 :            :  *    derived from this software without specific prior written permission.
      18                 :            :  *
      19                 :            :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
      20                 :            :  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
      21                 :            :  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
      22                 :            :  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
      23                 :            :  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      24                 :            :  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      25                 :            :  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      26                 :            :  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      27                 :            :  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
      28                 :            :  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      29                 :            :  */
      30                 :            : 
      31                 :            : #include "defs.h"
      32                 :            : #include <linux/ioctl.h>
      33                 :            : #include "xlat/ioctl_dirs.h"
      34                 :            : 
      35                 :            : #ifdef HAVE_LINUX_INPUT_H
      36                 :            : # include <linux/input.h>
      37                 :            : #endif
      38                 :            : 
      39                 :            : #include "xlat/evdev_abs.h"
      40                 :            : #include "xlat/evdev_ev.h"
      41                 :            : 
      42                 :            : static int
      43                 :      42657 : compare(const void *a, const void *b)
      44                 :            : {
      45                 :      42657 :         const unsigned int code1 = (const uintptr_t) a;
      46                 :      42657 :         const unsigned int code2 = ((struct_ioctlent *) b)->code;
      47 [ +  + ][ +  + ]:      42657 :         return (code1 > code2) ? 1 : (code1 < code2) ? -1 : 0;
      48                 :            : }
      49                 :            : 
      50                 :            : static const struct_ioctlent *
      51                 :       4025 : ioctl_lookup(const unsigned int code)
      52                 :            : {
      53                 :            :         struct_ioctlent *iop;
      54                 :            : 
      55                 :       4025 :         iop = bsearch((const void *) (const uintptr_t) code, ioctlent,
      56                 :            :                         nioctlents, sizeof(ioctlent[0]), compare);
      57         [ +  + ]:       4050 :         while (iop > ioctlent) {
      58                 :       3655 :                 iop--;
      59         [ +  + ]:       3655 :                 if (iop->code != code) {
      60                 :       3630 :                         iop++;
      61                 :       3630 :                         break;
      62                 :            :                 }
      63                 :            :         }
      64                 :       4025 :         return iop;
      65                 :            : }
      66                 :            : 
      67                 :            : static const struct_ioctlent *
      68                 :       3706 : ioctl_next_match(const struct_ioctlent *iop)
      69                 :            : {
      70                 :       3706 :         const unsigned int code = iop->code;
      71                 :       3706 :         iop++;
      72 [ +  - ][ +  + ]:       3706 :         if (iop < ioctlent + nioctlents && iop->code == code)
      73                 :         76 :                 return iop;
      74                 :       3630 :         return NULL;
      75                 :            : }
      76                 :            : 
      77                 :            : static void
      78                 :        145 : ioctl_print_code(const unsigned int code)
      79                 :            : {
      80                 :        145 :         tprints("_IOC(");
      81                 :        145 :         printflags(ioctl_dirs, _IOC_DIR(code), "_IOC_???");
      82                 :        145 :         tprintf(", %#x, %#x, %#x)",
      83                 :        290 :                 _IOC_TYPE(code), _IOC_NR(code), _IOC_SIZE(code));
      84                 :        145 : }
      85                 :            : 
      86                 :            : static int
      87                 :        485 : evdev_decode_number(const unsigned int code)
      88                 :            : {
      89                 :        485 :         const unsigned int nr = _IOC_NR(code);
      90                 :            : 
      91         [ +  + ]:        485 :         if (_IOC_DIR(code) == _IOC_WRITE) {
      92 [ +  + ][ +  - ]:        160 :                 if (nr >= 0xc0 && nr <= 0xc0 + 0x3f) {
      93                 :         10 :                         tprints("EVIOCSABS(");
      94                 :         10 :                         printxval(evdev_abs, nr - 0xc0, "ABS_???");
      95                 :         10 :                         tprints(")");
      96                 :         10 :                         return 1;
      97                 :            :                 }
      98                 :            :         }
      99                 :            : 
     100         [ +  + ]:        475 :         if (_IOC_DIR(code) != _IOC_READ)
     101                 :        170 :                 return 0;
     102                 :            : 
     103 [ +  + ][ +  + ]:        305 :         if (nr >= 0x20 && nr <= 0x20 + 0x1f) {
     104                 :        135 :                 tprints("EVIOCGBIT(");
     105                 :        135 :                 printxval(evdev_ev, nr - 0x20, "EV_???");
     106                 :        135 :                 tprintf(", %u)", _IOC_SIZE(code));
     107                 :        135 :                 return 1;
     108 [ +  + ][ +  + ]:        170 :         } else if (nr >= 0x40 && nr <= 0x40 + 0x3f) {
     109                 :         10 :                 tprints("EVIOCGABS(");
     110                 :         10 :                 printxval(evdev_abs, nr - 0x40, "ABS_???");
     111                 :         10 :                 tprints(")");
     112                 :         10 :                 return 1;
     113                 :            :         }
     114                 :            : 
     115   [ +  +  +  +  :        160 :         switch (_IOC_NR(nr)) {
          +  +  +  +  +  
                      + ]
     116                 :            :                 case 0x06:
     117                 :         10 :                         tprintf("EVIOCGNAME(%u)", _IOC_SIZE(code));
     118                 :         10 :                         return 1;
     119                 :            :                 case 0x07:
     120                 :         10 :                         tprintf("EVIOCGPHYS(%u)", _IOC_SIZE(code));
     121                 :         10 :                         return 1;
     122                 :            :                 case 0x08:
     123                 :         10 :                         tprintf("EVIOCGUNIQ(%u)", _IOC_SIZE(code));
     124                 :         10 :                         return 1;
     125                 :            :                 case 0x09:
     126                 :         10 :                         tprintf("EVIOCGPROP(%u)", _IOC_SIZE(code));
     127                 :         10 :                         return 1;
     128                 :            :                 case 0x0a:
     129                 :         10 :                         tprintf("EVIOCGMTSLOTS(%u)", _IOC_SIZE(code));
     130                 :         10 :                         return 1;
     131                 :            :                 case 0x18:
     132                 :         10 :                         tprintf("EVIOCGKEY(%u)", _IOC_SIZE(code));
     133                 :         10 :                         return 1;
     134                 :            :                 case 0x19:
     135                 :         10 :                         tprintf("EVIOCGLED(%u)", _IOC_SIZE(code));
     136                 :         10 :                         return 1;
     137                 :            :                 case 0x1a:
     138                 :         10 :                         tprintf("EVIOCGSND(%u)", _IOC_SIZE(code));
     139                 :         10 :                         return 1;
     140                 :            :                 case 0x1b:
     141                 :         10 :                         tprintf("EVIOCGSW(%u)", _IOC_SIZE(code));
     142                 :         10 :                         return 1;
     143                 :            :                 default:
     144                 :         70 :                         return 0;
     145                 :            :         }
     146                 :            : }
     147                 :            : 
     148                 :            : static int
     149                 :         10 : hiddev_decode_number(const unsigned int code)
     150                 :            : {
     151         [ +  - ]:         10 :         if (_IOC_DIR(code) == _IOC_READ) {
     152   [ -  -  -  +  :         10 :                 switch (_IOC_NR(code)) {
                      + ]
     153                 :            :                         case 0x04:
     154                 :          0 :                                 tprintf("HIDIOCGRAWNAME(%u)", _IOC_SIZE(code));
     155                 :          0 :                                 return 1;
     156                 :            :                         case 0x05:
     157                 :          0 :                                 tprintf("HIDIOCGRAWPHYS(%u)", _IOC_SIZE(code));
     158                 :          0 :                                 return 1;
     159                 :            :                         case 0x06:
     160                 :          0 :                                 tprintf("HIDIOCSFEATURE(%u)", _IOC_SIZE(code));
     161                 :          0 :                                 return 1;
     162                 :            :                         case 0x12:
     163                 :          5 :                                 tprintf("HIDIOCGPHYS(%u)", _IOC_SIZE(code));
     164                 :          5 :                                 return 1;
     165                 :            :                         default:
     166                 :          5 :                                 return 0;
     167                 :            :                 }
     168         [ #  # ]:          0 :         } else if (_IOC_DIR(code) == (_IOC_READ | _IOC_WRITE)) {
     169      [ #  #  # ]:          0 :                 switch (_IOC_NR(code)) {
     170                 :            :                         case 0x06:
     171                 :          0 :                                 tprintf("HIDIOCSFEATURE(%u)", _IOC_SIZE(code));
     172                 :          0 :                                 return 1;
     173                 :            :                         case 0x07:
     174                 :          0 :                                 tprintf("HIDIOCGFEATURE(%u)", _IOC_SIZE(code));
     175                 :          0 :                                 return 1;
     176                 :            :                         default:
     177                 :          0 :                                 return 0;
     178                 :            :                 }
     179                 :            :         }
     180                 :            : 
     181                 :          0 :         return 0;
     182                 :            : }
     183                 :            : 
     184                 :            : static int
     185                 :       4025 : ioctl_decode_command_number(struct tcb *tcp)
     186                 :            : {
     187                 :       4025 :         const unsigned int code = tcp->u_arg[1];
     188                 :            : 
     189   [ +  +  +  -  :       4025 :         switch (_IOC_TYPE(code)) {
                -  -  + ]
     190                 :            :                 case 'E':
     191                 :        485 :                         return evdev_decode_number(code);
     192                 :            :                 case 'H':
     193                 :         10 :                         return hiddev_decode_number(code);
     194                 :            :                 case 'M':
     195         [ +  + ]:        195 :                         if (_IOC_DIR(code) == _IOC_WRITE) {
     196                 :         70 :                                 tprintf("MIXER_WRITE(%u)", _IOC_NR(code));
     197                 :         70 :                                 return 1;
     198         [ +  + ]:        125 :                         } else if (_IOC_DIR(code) == _IOC_READ) {
     199                 :         60 :                                 tprintf("MIXER_READ(%u)", _IOC_NR(code));
     200                 :         60 :                                 return 1;
     201                 :            :                         }
     202                 :         65 :                         return 0;
     203                 :            :                 case 'U':
     204 [ #  # ][ #  # ]:          0 :                         if (_IOC_DIR(code) == _IOC_READ && _IOC_NR(code) == 0x2c) {
     205                 :          0 :                                 tprintf("UI_GET_SYSNAME(%u)", _IOC_SIZE(code));
     206                 :          0 :                                 return 1;
     207                 :            :                         }
     208                 :          0 :                         return 0;
     209                 :            :                 case 'j':
     210 [ #  # ][ #  # ]:          0 :                         if (_IOC_DIR(code) == _IOC_READ && _IOC_NR(code) == 0x13) {
     211                 :          0 :                                 tprintf("JSIOCGNAME(%u)", _IOC_SIZE(code));
     212                 :          0 :                                 return 1;
     213                 :            :                         }
     214                 :          0 :                         return 0;
     215                 :            :                 case 'k':
     216 [ #  # ][ #  # ]:          0 :                         if (_IOC_DIR(code) == _IOC_WRITE && _IOC_NR(code) == 0) {
     217                 :          0 :                                 tprintf("SPI_IOC_MESSAGE(%u)", _IOC_SIZE(code));
     218                 :          0 :                                 return 1;
     219                 :            :                         }
     220                 :          0 :                         return 0;
     221                 :            :                 default:
     222                 :       3335 :                         return 0;
     223                 :            :         }
     224                 :            : }
     225                 :            : 
     226                 :            : static int
     227                 :       5935 : ioctl_decode(struct tcb *tcp)
     228                 :            : {
     229                 :       5935 :         const unsigned int code = tcp->u_arg[1];
     230                 :       5935 :         const kernel_ulong_t arg = tcp->u_arg[2];
     231                 :            : 
     232   [ +  +  +  +  :       5935 :         switch (_IOC_TYPE(code)) {
          -  +  -  +  +  
          +  -  +  -  +  
             +  +  +  +  
                      + ]
     233                 :            : #if defined(ALPHA) || defined(POWERPC)
     234                 :            :         case 'f': {
     235                 :            :                 int ret = file_ioctl(tcp, code, arg);
     236                 :            :                 if (ret != RVAL_DECODED)
     237                 :            :                         return ret;
     238                 :            :         }
     239                 :            :         case 't':
     240                 :            :         case 'T':
     241                 :            :                 return term_ioctl(tcp, code, arg);
     242                 :            : #else /* !ALPHA */
     243                 :            :         case 'f':
     244                 :         10 :                 return file_ioctl(tcp, code, arg);
     245                 :            :         case 0x54:
     246                 :            : #endif /* !ALPHA */
     247                 :         10 :                 return term_ioctl(tcp, code, arg);
     248                 :            :         case 0x89:
     249                 :         80 :                 return sock_ioctl(tcp, code, arg);
     250                 :            :         case 'p':
     251                 :        480 :                 return rtc_ioctl(tcp, code, arg);
     252                 :            :         case 0x03:
     253                 :          0 :                 return hdio_ioctl(tcp, code, arg);
     254                 :            :         case 0x12:
     255                 :        270 :                 return block_ioctl(tcp, code, arg);
     256                 :            :         case 'X':
     257                 :          0 :                 return fs_x_ioctl(tcp, code, arg);
     258                 :            :         case 0x22:
     259                 :        500 :                 return scsi_ioctl(tcp, code, arg);
     260                 :            :         case 'L':
     261                 :        405 :                 return loop_ioctl(tcp, code, arg);
     262                 :            :         case 'M':
     263                 :        235 :                 return mtd_ioctl(tcp, code, arg);
     264                 :            :         case 'o':
     265                 :            :         case 'O':
     266                 :          0 :                 return ubi_ioctl(tcp, code, arg);
     267                 :            :         case 'V':
     268                 :        520 :                 return v4l2_ioctl(tcp, code, arg);
     269                 :            :         case '=':
     270                 :          0 :                 return ptp_ioctl(tcp, code, arg);
     271                 :            : #ifdef HAVE_LINUX_INPUT_H
     272                 :            :         case 'E':
     273                 :        790 :                 return evdev_ioctl(tcp, code, arg);
     274                 :            : #endif
     275                 :            : #ifdef HAVE_LINUX_USERFAULTFD_H
     276                 :            :         case 0xaa:
     277                 :        130 :                 return uffdio_ioctl(tcp, code, arg);
     278                 :            : #endif
     279                 :            : #ifdef HAVE_LINUX_BTRFS_H
     280                 :            :         case 0x94:
     281                 :       1540 :                 return btrfs_ioctl(tcp, code, arg);
     282                 :            : #endif
     283                 :            : #ifdef HAVE_LINUX_NSFS_H
     284                 :            :         case 0xb7:
     285                 :         55 :                 return nsfs_ioctl(tcp, code, arg);
     286                 :            : #endif
     287                 :            : #ifdef HAVE_LINUX_DM_IOCTL_H
     288                 :            :         case 0xfd:
     289                 :        860 :                 return dm_ioctl(tcp, code, arg);
     290                 :            : #endif
     291                 :            :         default:
     292                 :         50 :                 break;
     293                 :            :         }
     294                 :         50 :         return 0;
     295                 :            : }
     296                 :            : 
     297                 :       5935 : SYS_FUNC(ioctl)
     298                 :            : {
     299                 :            :         const struct_ioctlent *iop;
     300                 :            :         int ret;
     301                 :            : 
     302         [ +  + ]:       5935 :         if (entering(tcp)) {
     303                 :       4025 :                 printfd(tcp, tcp->u_arg[0]);
     304                 :       4025 :                 tprints(", ");
     305                 :       4025 :                 ret = ioctl_decode_command_number(tcp);
     306         [ +  - ]:       4025 :                 if (!(ret & IOCTL_NUMBER_STOP_LOOKUP)) {
     307                 :       4025 :                         iop = ioctl_lookup(tcp->u_arg[1]);
     308         [ +  + ]:       4025 :                         if (iop) {
     309         [ +  + ]:       3630 :                                 if (ret)
     310                 :        130 :                                         tprints(" or ");
     311                 :       3630 :                                 tprints(iop->symbol);
     312         [ +  + ]:       3706 :                                 while ((iop = ioctl_next_match(iop)))
     313                 :         76 :                                         tprintf(" or %s", iop->symbol);
     314         [ +  + ]:        395 :                         } else if (!ret) {
     315                 :        145 :                                 ioctl_print_code(tcp->u_arg[1]);
     316                 :            :                         }
     317                 :            :                 }
     318                 :       4025 :                 ret = ioctl_decode(tcp);
     319                 :            :         } else {
     320                 :       1910 :                 ret = ioctl_decode(tcp) | RVAL_DECODED;
     321                 :            :         }
     322                 :            : 
     323         [ +  + ]:       5935 :         if (ret & RVAL_DECODED) {
     324                 :       4025 :                 ret &= ~RVAL_DECODED;
     325         [ +  + ]:       4025 :                 if (ret)
     326                 :       3820 :                         --ret;
     327                 :            :                 else
     328                 :        205 :                         tprintf(", %#" PRI_klx, tcp->u_arg[2]);
     329                 :       4025 :                 ret |= RVAL_DECODED;
     330                 :            :         } else {
     331         [ +  + ]:       1910 :                 if (ret)
     332                 :        565 :                         --ret;
     333                 :            :         }
     334                 :            : 
     335                 :       5935 :         return ret;
     336                 :            : }

Generated by: LCOV version 1.12