]> granicus.if.org Git - strace/blobdiff - dm.c
nlattr: add UID/GID netlink attribute decoders
[strace] / dm.c
diff --git a/dm.c b/dm.c
index 327a5e1abce383836633e1fa4e4203b06bac188a..963852f8b3657aa53e8c36e355917cc7a7acf97e 100644 (file)
--- a/dm.c
+++ b/dm.c
@@ -5,7 +5,7 @@
  * Copyright (c) 2016 Masatake Yamato <yamato@redhat.com>
  * Copyright (c) 2016 Dmitry V. Levin <ldv@altlinux.org>
  * Copyright (c) 2016 Eugene Syromyatnikov <evgsyr@gmail.com>
- * Copyright (c) 2016-2017 The strace developers.
+ * Copyright (c) 2016-2018 The strace developers.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
 /* Definitions for command which have been added later */
 
 #  ifndef DM_LIST_VERSIONS
-#   define DM_LIST_VERSIONS    _IOWR(DM_IOCTL, 0xd, struct dm_ioctl)
+#   define DM_LIST_VERSIONS    _IOWR(DM_IOCTL, 0x0d, struct dm_ioctl)
 #  endif
 #  ifndef DM_TARGET_MSG
-#   define DM_TARGET_MSG       _IOWR(DM_IOCTL, 0xe, struct dm_ioctl)
+#   define DM_TARGET_MSG       _IOWR(DM_IOCTL, 0x0e, struct dm_ioctl)
 #  endif
 #  ifndef DM_DEV_SET_GEOMETRY
-#   define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, 0xf, struct dm_ioctl)
+#   define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, 0x0f, struct dm_ioctl)
+#  endif
+#  ifndef DM_DEV_ARM_POLL
+#   define DM_DEV_ARM_POLL     _IOWR(DM_IOCTL, 0x10, struct dm_ioctl)
 #  endif
 
 
@@ -88,7 +91,7 @@ dm_decode_values(struct tcb *tcp, const unsigned int code,
                case DM_DEV_SUSPEND:
                        if (ioc->flags & DM_SUSPEND_FLAG)
                                break;
-                       /* Fall through */
+                       ATTRIBUTE_FALLTHROUGH;
                case DM_DEV_RENAME:
                case DM_DEV_REMOVE:
                case DM_DEV_WAIT:
@@ -234,7 +237,7 @@ dm_decode_dm_target_deps(struct tcb *const tcp, const kernel_ulong_t addr,
 
        tprints(", deps=");
        print_array(tcp, addr + offset_end, s.count, &dev_buf, sizeof(dev_buf),
-                   umoven_or_printaddr, dm_print_dev, NULL);
+                   tfetch_mem, dm_print_dev, NULL);
 
        tprints("}");
 
@@ -255,6 +258,7 @@ dm_decode_dm_name_list(struct tcb *const tcp, const kernel_ulong_t addr,
        uint32_t offset = ioc->data_start;
        uint32_t offset_end = 0;
        uint32_t count;
+       int rc;
 
        if (ioc->data_start == ioc->data_size)
                return;
@@ -285,8 +289,36 @@ dm_decode_dm_name_list(struct tcb *const tcp, const kernel_ulong_t addr,
 
                PRINT_FIELD_DEV("{", s, dev);
                tprints(", name=");
-               printstr_ex(tcp, addr + offset_end, ioc->data_size - offset_end,
-                           QUOTE_0_TERMINATED);
+               rc = printstr_ex(tcp, addr + offset_end,
+                                ioc->data_size - offset_end,
+                                QUOTE_0_TERMINATED);
+
+               /*
+                * In Linux v4.13-rc1~137^2~13 it has been decided to cram in
+                * one more undocumented field after the device name, as if the
+                * format decoding was not twisted enough already. So, we have
+                * to check "next" now, and if it _looks like_ that there is
+                * a space for one additional integer, let's print it. As if the
+                * perversity with "name string going further than pointer to
+                * the next one" wasn't enough. Moreover, the calculation was
+                * broken for m32 on 64-bit kernels until v4.14-rc4~20^2~3, and
+                * we have no ability to detect kernel bit-ness (on x86, at
+                * least), so refrain from printing it for the DM versions below
+                * 4.37 (the original version was also aligned differently than
+                * now even on 64 bit).
+                */
+
+               if ((rc > 0) && ioc->version[1] >= 37) {
+                       kernel_ulong_t event_addr =
+                               (addr + offset_end + rc + 7) & ~7;
+                       uint32_t event_nr;
+
+                       if ((event_addr + sizeof(event_nr)) <=
+                           (addr + offset + s.next) &&
+                           !umove(tcp, event_addr, &event_nr))
+                               tprintf(", event_nr=%" PRIu32, event_nr);
+               }
+
                tprints("}");
 
                if (!s.next)
@@ -429,6 +461,7 @@ dm_ioctl_has_params(const unsigned int code)
        case DM_DEV_SUSPEND:
        case DM_DEV_STATUS:
        case DM_TABLE_CLEAR:
+       case DM_DEV_ARM_POLL:
                return false;
        }
 
@@ -479,7 +512,7 @@ dm_known_ioctl(struct tcb *const tcp, const unsigned int code,
        }
 
        if (exiting(tcp) && syserror(tcp) && !ioc_changed)
-               return 1;
+               return RVAL_IOCTL_DECODED;
 
        /*
         * device mapper code uses %d in some places and %u in another, but
@@ -553,7 +586,7 @@ dm_known_ioctl(struct tcb *const tcp, const unsigned int code,
 
  skip:
        tprints("}");
-       return 1;
+       return entering(tcp) ? 0 : RVAL_IOCTL_DECODED;
 }
 
 int
@@ -576,6 +609,7 @@ dm_ioctl(struct tcb *const tcp, const unsigned int code, const kernel_ulong_t ar
        case DM_LIST_VERSIONS:
        case DM_TARGET_MSG:
        case DM_DEV_SET_GEOMETRY:
+       case DM_DEV_ARM_POLL:
                return dm_known_ioctl(tcp, code, arg);
        default:
                return RVAL_DECODED;