bool decode_netlink_selinux(struct tcb *const tcp, const struct nlmsghdr *const nlmsghdr, const kernel_ulong_t addr, const unsigned int len) { switch (nlmsghdr->nlmsg_type) { case SELNL_MSG_SETENFORCE: { struct selnl_msg_setenforce msg; if (len < sizeof(msg)) printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX); else if (!umove_or_printaddr(tcp, addr, &msg)) { PRINT_FIELD_D("{", msg, val); tprints("}"); } break; } case SELNL_MSG_POLICYLOAD: { struct selnl_msg_policyload msg; if (len < sizeof(msg)) printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX); else if (!umove_or_printaddr(tcp, addr, &msg)) { PRINT_FIELD_U("{", msg, seqno); tprints("}"); } break; } default: return false; } return true; }
void print_seccomp_filter(struct tcb *tcp, unsigned long addr) { #if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4 if (current_wordsize == 4) { struct { unsigned short len; uint32_t filter; } fprog; if (!umove_or_printaddr(tcp, addr, &fprog)) decode_fprog(tcp, fprog.len, fprog.filter); } else { #endif struct { unsigned short len; unsigned long filter; } fprog; if (!umove_or_printaddr(tcp, addr, &fprog)) decode_fprog(tcp, fprog.len, fprog.filter); #if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4 } #endif }
static void decode_old_sigaction(struct tcb *tcp, long addr) { struct old_sigaction sa; #if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4 if (current_wordsize != sizeof(sa.__sa_handler) && current_wordsize == 4) { struct old_sigaction32 sa32; if (umove_or_printaddr(tcp, addr, &sa32)) return; memset(&sa, 0, sizeof(sa)); sa.__sa_handler = (void*)(uintptr_t)sa32.__sa_handler; sa.sa_flags = sa32.sa_flags; #if HAVE_SA_RESTORER && defined SA_RESTORER sa.sa_restorer = (void*)(uintptr_t)sa32.sa_restorer; #endif sa.sa_mask = sa32.sa_mask; } else #endif if (umove_or_printaddr(tcp, addr, &sa)) return; /* Architectures using function pointers, like * hppa, may need to manipulate the function pointer * to compute the result of a comparison. However, * the __sa_handler function pointer exists only in * the address space of the traced process, and can't * be manipulated by strace. In order to prevent the * compiler from generating code to manipulate * __sa_handler we cast the function pointers to long. */ tprints("{"); if ((long)sa.__sa_handler == (long)SIG_ERR) tprints("SIG_ERR"); else if ((long)sa.__sa_handler == (long)SIG_DFL) tprints("SIG_DFL"); else if ((long)sa.__sa_handler == (long)SIG_IGN) tprints("SIG_IGN"); else printaddr((long) sa.__sa_handler); tprints(", "); #ifdef MIPS tprintsigmask_addr("", sa.sa_mask); #else tprintsigmask_val("", sa.sa_mask); #endif tprints(", "); printflags(sigact_flags, sa.sa_flags, "SA_???"); #if HAVE_SA_RESTORER && defined SA_RESTORER if (sa.sa_flags & SA_RESTORER) tprintf(", %p", sa.sa_restorer); #endif tprints("}"); }
static void decode_new_sigaction(struct tcb *const tcp, const kernel_ulong_t addr) { struct new_sigaction sa; #ifndef current_wordsize if (current_wordsize < sizeof(sa.sa_handler__)) { struct new_sigaction32 sa32; if (umove_or_printaddr(tcp, addr, &sa32)) return; memset(&sa, 0, sizeof(sa)); sa.sa_handler__ = sa32.sa_handler__; sa.sa_flags = sa32.sa_flags; #if HAVE_SA_RESTORER && defined SA_RESTORER sa.sa_restorer = sa32.sa_restorer; #endif /* Kernel treats sa_mask as an array of longs. * For 32-bit process, "long" is uint32_t, thus, for example, * 32th bit in sa_mask will end up as bit 0 in sa_mask[1]. * But for (64-bit) kernel, 32th bit in sa_mask is * 32th bit in 0th (64-bit) long! * For little-endian, it's the same. * For big-endian, we swap 32-bit words. */ sa.sa_mask[0] = ULONG_LONG(sa32.sa_mask[0], sa32.sa_mask[1]); } else #endif if (umove_or_printaddr(tcp, addr, &sa)) return; tprints("{sa_handler="); print_sa_handler(sa.sa_handler__); tprints(", sa_mask="); /* * Sigset size is in tcp->u_arg[4] (SPARC) * or in tcp->u_arg[3] (all other), * but kernel won't handle sys_rt_sigaction * with wrong sigset size (just returns EINVAL instead). * We just fetch the right size, which is NSIG_BYTES. */ tprintsigmask_val("", sa.sa_mask); tprints(", sa_flags="); printflags(sigact_flags, sa.sa_flags, "SA_???"); #if HAVE_SA_RESTORER && defined SA_RESTORER if (sa.sa_flags & SA_RESTORER) { tprints(", sa_restorer="); printaddr(sa.sa_restorer); } #endif tprints("}"); }
MPERS_PRINTER_DECL(bool, fetch_struct_stat, struct tcb *tcp, const unsigned long addr, struct strace_stat *const dst) { #ifdef HAVE_STRUCT_STAT struct_stat buf; if (umove_or_printaddr(tcp, addr, &buf)) return false; dst->dev = zero_extend_signed_to_ull(buf.st_dev); dst->ino = zero_extend_signed_to_ull(buf.st_ino); dst->rdev = zero_extend_signed_to_ull(buf.st_rdev); dst->size = zero_extend_signed_to_ull(buf.st_size); dst->blocks = zero_extend_signed_to_ull(buf.st_blocks); dst->blksize = zero_extend_signed_to_ull(buf.st_blksize); dst->mode = zero_extend_signed_to_ull(buf.st_mode); dst->nlink = zero_extend_signed_to_ull(buf.st_nlink); dst->uid = zero_extend_signed_to_ull(buf.st_uid); dst->gid = zero_extend_signed_to_ull(buf.st_gid); dst->atime = sign_extend_unsigned_to_ll(buf.st_atime); dst->ctime = sign_extend_unsigned_to_ll(buf.st_ctime); dst->mtime = sign_extend_unsigned_to_ll(buf.st_mtime); dst->atime_nsec = TIME_NSEC(buf.st_atime_nsec); dst->ctime_nsec = TIME_NSEC(buf.st_ctime_nsec); dst->mtime_nsec = TIME_NSEC(buf.st_mtime_nsec); return true; #else /* !HAVE_STRUCT_STAT */ printaddr(addr); return false; #endif }
static void decode_termios(struct tcb *const tcp, const kernel_ulong_t addr) { struct termios tios; tprints(", "); if (umove_or_printaddr(tcp, addr, &tios)) return; if (abbrev(tcp)) { tprints("{"); printxval(baud_options, tios.c_cflag & CBAUD, "B???"); tprintf(" %sopost %sisig %sicanon %secho ...}", (tios.c_oflag & OPOST) ? "" : "-", (tios.c_lflag & ISIG) ? "" : "-", (tios.c_lflag & ICANON) ? "" : "-", (tios.c_lflag & ECHO) ? "" : "-"); return; } tprintf("{c_iflags=%#lx, c_oflags=%#lx, ", (long) tios.c_iflag, (long) tios.c_oflag); tprintf("c_cflags=%#lx, c_lflags=%#lx, ", (long) tios.c_cflag, (long) tios.c_lflag); tprintf("c_line=%u, ", tios.c_line); if (!(tios.c_lflag & ICANON)) tprintf("c_cc[VMIN]=%d, c_cc[VTIME]=%d, ", tios.c_cc[VMIN], tios.c_cc[VTIME]); tprints("c_cc="); print_quoted_string((char *) tios.c_cc, NCCS, QUOTE_FORCE_HEX); tprints("}"); }
static void decode_nand_ecclayout_user(struct tcb *const tcp, const kernel_ulong_t addr) { struct nand_ecclayout_user nlay; unsigned int i; tprints(", "); if (umove_or_printaddr(tcp, addr, &nlay)) return; tprintf("{eccbytes=%#x, eccpos={", nlay.eccbytes); for (i = 0; i < ARRAY_SIZE(nlay.eccpos); ++i) { if (i) tprints(", "); tprintf("%#x", nlay.eccpos[i]); } tprintf("}, oobavail=%#x, oobfree={", nlay.oobavail); for (i = 0; i < ARRAY_SIZE(nlay.oobfree); ++i) { if (i) tprints(", "); tprintf("{offset=%#x, length=%#x}", nlay.oobfree[i].offset, nlay.oobfree[i].length); } tprints("}"); }
static void decode_nand_oobinfo(struct tcb *const tcp, const kernel_ulong_t addr) { struct nand_oobinfo ninfo; unsigned int i, j; tprints(", "); if (umove_or_printaddr(tcp, addr, &ninfo)) return; tprints("{useecc="); printxval(mtd_nandecc_options, ninfo.useecc, "MTD_NANDECC_???"); tprintf(", eccbytes=%#x", ninfo.eccbytes); tprints(", oobfree={"); for (i = 0; i < ARRAY_SIZE(ninfo.oobfree); ++i) { if (i) tprints("}, "); tprints("{"); for (j = 0; j < ARRAY_SIZE(ninfo.oobfree[0]); ++j) { if (j) tprints(", "); tprintf("%#x", ninfo.oobfree[i][j]); } } tprints("}}, eccpos={"); for (i = 0; i < ARRAY_SIZE(ninfo.eccpos); ++i) { if (i) tprints(", "); tprintf("%#x", ninfo.eccpos[i]); } tprints("}"); }
MPERS_PRINTER_DECL(bool, fetch_struct_quotastat, struct tcb *const tcp, const kernel_ulong_t data, void *p) { struct xfs_dqstats *dq = p; struct_xfs_dqstats dqstat; if (umove_or_printaddr(tcp, data, &dqstat)) return false; dq->qs_version = dqstat.qs_version; dq->qs_flags = dqstat.qs_flags; dq->qs_pad = dqstat.qs_pad; dq->qs_uquota.qfs_ino = dqstat.qs_uquota.qfs_ino; dq->qs_uquota.qfs_nblks = dqstat.qs_uquota.qfs_nblks; dq->qs_uquota.qfs_nextents = dqstat.qs_uquota.qfs_nextents; dq->qs_gquota.qfs_ino = dqstat.qs_gquota.qfs_ino; dq->qs_gquota.qfs_nblks = dqstat.qs_gquota.qfs_nblks; dq->qs_gquota.qfs_nextents = dqstat.qs_gquota.qfs_nextents; dq->qs_incoredqs = dqstat.qs_incoredqs; dq->qs_btimelimit = dqstat.qs_btimelimit; dq->qs_itimelimit = dqstat.qs_itimelimit; dq->qs_rtbtimelimit = dqstat.qs_rtbtimelimit; dq->qs_bwarnlimit = dqstat.qs_bwarnlimit; dq->qs_iwarnlimit = dqstat.qs_iwarnlimit; return true; }
static void print_old_dirent(struct tcb *tcp, long addr) { #ifdef SH64 typedef struct kernel_dirent old_dirent_t; #else typedef struct { uint32_t d_ino; uint32_t d_off; unsigned short d_reclen; char d_name[1]; } old_dirent_t; #endif old_dirent_t d; if (umove_or_printaddr(tcp, addr, &d)) return; tprintf("{d_ino=%lu, d_off=%lu, d_reclen=%u, d_name=", (unsigned long) d.d_ino, (unsigned long) d.d_off, d.d_reclen); if (d.d_reclen > D_NAME_LEN_MAX) d.d_reclen = D_NAME_LEN_MAX; printpathn(tcp, addr + offsetof(old_dirent_t, d_name), d.d_reclen); tprints("}"); }
MPERS_PRINTER_DECL(int, print_timex)(struct tcb *tcp, const long addr) { struct_timex tx; if (umove_or_printaddr(tcp, addr, &tx)) return -1; tprints("{modes="); printflags(adjtimex_modes, tx.modes, "ADJ_???"); tprintf(", offset=%jd, freq=%jd, maxerror=%ju, esterror=%ju, status=", (intmax_t) tx.offset, (intmax_t) tx.freq, (uintmax_t) tx.maxerror, (uintmax_t) tx.esterror); printflags(adjtimex_status, tx.status, "STA_???"); tprintf(", constant=%jd, precision=%ju, tolerance=%jd", (intmax_t) tx.constant, (uintmax_t) tx.precision, (intmax_t) tx.tolerance); tprintf(", time={%jd, %jd}", (intmax_t) tx.time.tv_sec, (intmax_t) tx.time.tv_usec); tprintf(", tick=%jd, ppsfreq=%jd, jitter=%jd", (intmax_t) tx.tick, (intmax_t) tx.ppsfreq, (intmax_t) tx.jitter); tprintf(", shift=%d, stabil=%jd, jitcnt=%jd", tx.shift, (intmax_t) tx.stabil, (intmax_t) tx.jitcnt); tprintf(", calcnt=%jd, errcnt=%jd, stbcnt=%jd", (intmax_t) tx.calcnt, (intmax_t) tx.errcnt, (intmax_t) tx.stbcnt); #ifdef HAVE_STRUCT_TIMEX_TAI tprintf(", tai=%d", tx.tai); #endif tprints("}"); return 0; }
static int mtslots_ioctl(struct tcb *const tcp, const unsigned int code, const kernel_ulong_t arg) { tprints(", "); const size_t size = _IOC_SIZE(code) / sizeof(int); if (!size) { printaddr(arg); return 1; } int buffer[size]; if (umove_or_printaddr(tcp, arg, &buffer)) return 1; tprints("{code="); printxval(evdev_mtslots, buffer[0], "ABS_MT_???"); tprints(", values=["); unsigned int i; for (i = 1; i < ARRAY_SIZE(buffer); i++) tprintf("%s%d", i > 1 ? ", " : "", buffer[i]); tprints("]}"); return 1; }
static int keycode_V2_ioctl(struct tcb *const tcp, const kernel_ulong_t arg) { tprints(", "); struct input_keymap_entry ike; if (umove_or_printaddr(tcp, arg, &ike)) return 1; tprintf("{flags=%" PRIu8 ", len=%" PRIu8 ", ", ike.flags, ike.len); if (!abbrev(tcp)) { unsigned int i; tprintf("index=%" PRIu16 ", keycode=", ike.index); printxval(evdev_keycode, ike.keycode, "KEY_???"); tprints(", scancode=["); for (i = 0; i < ARRAY_SIZE(ike.scancode); i++) { if (i > 0) tprints(", "); tprintf("%" PRIx8, ike.scancode[i]); } tprints("]"); } else { tprints("..."); } tprints("}"); return 1; }
static int abs_ioctl(struct tcb *const tcp, const kernel_ulong_t arg) { tprints(", "); struct input_absinfo absinfo; if (!umove_or_printaddr(tcp, arg, &absinfo)) { tprintf("{value=%u" ", minimum=%u, ", absinfo.value, absinfo.minimum); if (!abbrev(tcp)) { tprintf("maximum=%u" ", fuzz=%u" ", flat=%u", absinfo.maximum, absinfo.fuzz, absinfo.flat); # ifdef HAVE_STRUCT_INPUT_ABSINFO_RESOLUTION tprintf(", resolution=%u", absinfo.resolution); # endif } else { tprints("..."); } tprints("}"); } return 1; }
static bool decode_tc_sizespec(struct tcb *const tcp, const kernel_ulong_t addr, const unsigned int len, const void *const opaque_data) { #ifdef HAVE_STRUCT_TC_SIZESPEC struct tc_sizespec s; if (len < sizeof(s)) return false; else if (!umove_or_printaddr(tcp, addr, &s)) { PRINT_FIELD_U("{", s, cell_log); PRINT_FIELD_U(", ", s, size_log); PRINT_FIELD_D(", ", s, cell_align); PRINT_FIELD_D(", ", s, overhead); PRINT_FIELD_U(", ", s, linklayer); PRINT_FIELD_U(", ", s, mpu); PRINT_FIELD_U(", ", s, mtu); PRINT_FIELD_U(", ", s, tsize); tprints("}"); } return true; #else return false; #endif }
MPERS_PRINTER_DECL(int, decode_sg_req_info, struct tcb *const tcp, const kernel_ulong_t arg) { struct_sg_req_info info; if (entering(tcp)) return 0; tprints(", "); if (!umove_or_printaddr(tcp, arg, &info)) { tprintf("{req_state=%hhd" ", orphan=%hhd" ", sg_io_owned=%hhd" ", problem=%hhd" ", pack_id=%d" ", usr_ptr=", info.req_state, info.orphan, info.sg_io_owned, info.problem, info.pack_id); printaddr(ptr_to_kulong(info.usr_ptr)); tprintf(", duration=%u}", info.duration); } return RVAL_IOCTL_DECODED; }
static bool decode_gnet_stats_queue(struct tcb *const tcp, const kernel_ulong_t addr, const unsigned int len, const void *const opaque_data) { #ifdef HAVE_STRUCT_GNET_STATS_QUEUE struct gnet_stats_queue qstats; if (len < sizeof(qstats)) return false; else if (!umove_or_printaddr(tcp, addr, &qstats)) { PRINT_FIELD_U("{", qstats, qlen); PRINT_FIELD_U(", ", qstats, backlog); PRINT_FIELD_U(", ", qstats, drops); PRINT_FIELD_U(", ", qstats, requeues); PRINT_FIELD_U(", ", qstats, overlimits); tprints("}"); } return true; #else return false; #endif }
static void decode_inet_diag_hostcond(struct tcb *const tcp, const kernel_ulong_t addr, const unsigned int len) { struct inet_diag_hostcond cond; if (len < sizeof(cond)) { printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX); return; } if (umove_or_printaddr(tcp, addr, &cond)) return; PRINT_FIELD_XVAL("{", cond, family, addrfams, "AF_???"); PRINT_FIELD_U(", ", cond, prefix_len); PRINT_FIELD_U(", ", cond, port); if (len > sizeof(cond)) { tprints(", "); decode_inet_addr(tcp, addr + sizeof(cond), len - sizeof(cond), cond.family, "addr"); } tprints("}"); }
MPERS_PRINTER_DECL(int, hdio_ioctl, struct tcb *tcp, const unsigned int code, const long arg) { switch (code) { case HDIO_GETGEO: if (entering(tcp)) return 0; else { struct_hd_geometry geo; tprints(", "); if (!umove_or_printaddr(tcp, arg, &geo)) tprintf("{heads=%u, sectors=%u, " "cylinders=%hu, start=%lu}", (unsigned) geo.heads, (unsigned) geo.sectors, geo.cylinders, (unsigned long) geo.start); } break; default: return RVAL_DECODED; } return RVAL_DECODED | 1; }
static void print_mreq6(struct tcb *tcp, long addr, unsigned int len) { struct ipv6_mreq mreq; if (len < sizeof(mreq)) goto fail; if (umove_or_printaddr(tcp, addr, &mreq)) return; #ifdef HAVE_INET_NTOP const struct in6_addr *in6 = &mreq.ipv6mr_multiaddr; char address[INET6_ADDRSTRLEN]; if (!inet_ntop(AF_INET6, in6, address, sizeof(address))) goto fail; tprints("{ipv6mr_multiaddr=inet_pton("); print_quoted_string(address, sizeof(address), QUOTE_0_TERMINATED); tprints("), ipv6mr_interface="); print_ifindex(mreq.ipv6mr_interface); tprints("}"); return; #endif /* HAVE_INET_NTOP */ fail: printstr(tcp, addr, len); }
static bool decode_inet_diag_bc_op(struct tcb *const tcp, const kernel_ulong_t addr, const unsigned int len, const void *const opaque_data) { struct inet_diag_bc_op op; if (len < sizeof(op)) return false; if (umove_or_printaddr(tcp, addr, &op)) return true; if (len > sizeof(op)) tprints("{"); print_inet_diag_bc_op(&op); if (len > sizeof(op)) { tprints(", "); decode_bytecode_data(tcp, addr + sizeof(op), len - sizeof(op), op.code); tprints("}"); } return true; }
static int printwaitn(struct tcb *tcp, void (*const print_rusage)(struct tcb *, long)) { if (entering(tcp)) { /* On Linux, kernel-side pid_t is typedef'ed to int * on all arches. Also, glibc-2.8 truncates wait3 and wait4 * pid argument to int on 64bit arches, producing, * for example, wait4(4294967295, ...) instead of -1 * in strace. We have to use int here, not long. */ int pid = tcp->u_arg[0]; tprintf("%d, ", pid); } else { int status; /* status */ if (tcp->u_rval == 0) printaddr(tcp->u_arg[1]); else if (!umove_or_printaddr(tcp, tcp->u_arg[1], &status)) printstatus(status); /* options */ tprints(", "); printflags(wait4_options, tcp->u_arg[2], "W???"); if (print_rusage) { /* usage */ tprints(", "); if (tcp->u_rval > 0) print_rusage(tcp, tcp->u_arg[3]); else printaddr(tcp->u_arg[3]); } } return 0; }
void print_user_desc(struct tcb *const tcp, const kernel_ulong_t addr) { struct user_desc desc; if (umove_or_printaddr(tcp, addr, &desc)) return; tprintf("{entry_number:%d, " "base_addr:%#08x, " "limit:%d, " "seg_32bit:%d, " "contents:%d, " "read_exec_only:%d, " "limit_in_pages:%d, " "seg_not_present:%d, " "useable:%d}", desc.entry_number, desc.base_addr, desc.limit, desc.seg_32bit, desc.contents, desc.read_exec_only, desc.limit_in_pages, desc.seg_not_present, desc.useable); }
static void btrfs_print_qgroup_inherit(struct tcb *tcp, const uint64_t qgi_addr) { struct btrfs_qgroup_inherit inherit; if (umove_or_printaddr(tcp, qgi_addr, &inherit)) return; tprintf("{flags="); printflags64(btrfs_qgroup_inherit_flags, inherit.flags, "BTRFS_QGROUP_INHERIT_???"); tprintf(", num_qgroups=%" PRI__u64 ", num_ref_copies=%" PRI__u64 ", num_excl_copies=%" PRI__u64 ", lim=", inherit.num_qgroups, inherit.num_ref_copies, inherit.num_excl_copies); btrfs_print_qgroup_limit(&inherit.lim); tprints(", qgroups="); if (abbrev(tcp)) { tprints("..."); } else { uint64_t record; print_array(tcp, qgi_addr + offsetof(typeof(inherit), qgroups), inherit.num_qgroups, &record, sizeof(record), umoven_or_printaddr, print_uint64, 0); } tprints("}"); }
static bool decode_ifla_inet6_cacheinfo(struct tcb *const tcp, const kernel_ulong_t addr, const unsigned int len, const void *const opaque_data) { struct { uint32_t max_reasm_len; uint32_t tstamp; uint32_t reachable_time; uint32_t retrans_time; } ci; if (len < sizeof(ci)) return false; else if (!umove_or_printaddr(tcp, addr, &ci)) { PRINT_FIELD_U("{", ci, max_reasm_len); PRINT_FIELD_U(", ", ci, tstamp); PRINT_FIELD_U(", ", ci, reachable_time); PRINT_FIELD_U(", ", ci, retrans_time); tprints("}"); } return true; }
static void btrfs_print_ino_path_container(struct tcb *tcp, const uint64_t fspath_addr) { struct btrfs_data_container container; if (umove_or_printaddr(tcp, fspath_addr, &container)) return; btrfs_print_data_container_header(&container); if (abbrev(tcp)) { tprints("..."); } else { uint64_t val_addr = fspath_addr + offsetof(typeof(container), val); uint64_t offset; print_array(tcp, val_addr, container.elem_cnt, &offset, sizeof(offset), umoven_or_printaddr, print_btrfs_data_container_ino_path, &val_addr); } btrfs_print_data_container_footer(); }
static void btrfs_print_logical_ino_container(struct tcb *tcp, const uint64_t inodes_addr) { struct btrfs_data_container container; if (umove_or_printaddr(tcp, inodes_addr, &container)) return; btrfs_print_data_container_header(&container); if (abbrev(tcp)) { tprints("..."); } else { const uint64_t val_addr = inodes_addr + offsetof(typeof(container), val); uint64_t record[3]; print_array(tcp, val_addr, container.elem_cnt / 3, record, sizeof(record), umoven_or_printaddr, print_btrfs_data_container_logical_ino, 0); } btrfs_print_data_container_footer(); }
static void btrfs_print_balance(struct tcb *tcp, const long arg, bool out) { struct btrfs_ioctl_balance_args balance_args; if (umove_or_printaddr(tcp, arg, &balance_args)) return; tprints("{flags="); printflags64(btrfs_balance_flags, balance_args.flags, "BTRFS_BALANCE_???"); if (out) { tprints(", state="); printflags64(btrfs_balance_state, balance_args.state, "BTRFS_BALANCE_STATE_???"); } if (balance_args.flags & BTRFS_BALANCE_DATA) btrfs_print_balance_args("data", &balance_args.data); if (balance_args.flags & BTRFS_BALANCE_METADATA) btrfs_print_balance_args("meta", &balance_args.meta); if (balance_args.flags & BTRFS_BALANCE_SYSTEM) btrfs_print_balance_args("sys", &balance_args.sys); tprints("}"); }
bool decode_netlink_sock_diag(struct tcb *const tcp, const struct nlmsghdr *const nlmsghdr, const kernel_ulong_t addr, const unsigned int len) { uint8_t family; if (nlmsghdr->nlmsg_type == NLMSG_DONE) return false; if (!umove_or_printaddr(tcp, addr, &family)) { if (family < ARRAY_SIZE(diag_decoders) && len > sizeof(family)) { const netlink_diag_decoder_t decoder = (nlmsghdr->nlmsg_flags & NLM_F_REQUEST) ? diag_decoders[family].request : diag_decoders[family].response; if (decoder) { decoder(tcp, nlmsghdr, family, addr, len); return true; } } decode_family(tcp, family, addr, len); } return true; }
MPERS_PRINTER_DECL(void, printsiginfo_at, struct tcb *const tcp, const kernel_ulong_t addr) { siginfo_t si; if (!umove_or_printaddr(tcp, addr, &si)) printsiginfo(&si); }