LCOV - code coverage report
Current view: top level - strace - ioctl.c (source / functions) Hit Total Coverage
Test: strace-4.18.0.129.97bbb Code Coverage Lines: 114 136 83.8 %
Date: 2017-07-31 03:46:08 Functions: 8 8 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 73 103 70.9 %

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

Generated by: LCOV version 1.11