From a367db8e5b0e1d852af1c3d358c9f7204077fd73 Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Thu, 19 Nov 2015 18:13:53 +0000 Subject: [PATCH] Mpersify parsers of readdir and getdents syscalls * defs.h (dirent_types): New xlat prototype. * dirent.c: Stop including "xlat/direnttypes.h". (kernel_dirent): New typedef. Mpersify it. (print_old_dirent): Use it instead of old_dirent_t. (SYS_FUNC(getdents)): Use it instead of struct kernel_dirent. Rename direnttypes to dirent_types. (SYS_FUNC(getdents64)): Move ... * dirent64.c: ... here. Rename direnttypes to dirent_types. Include "xlat/dirent_types.h". * Makefile.am (strace_SOURCES): Add dirent64.c. * xlat/direnttypes.in: Rename to xlat/dirent_types.in. --- Makefile.am | 1 + defs.h | 1 + dirent.c | 165 +++++++---------------- dirent64.c | 123 +++++++++++++++++ xlat/{direnttypes.in => dirent_types.in} | 0 5 files changed, 177 insertions(+), 113 deletions(-) create mode 100644 dirent64.c rename xlat/{direnttypes.in => dirent_types.in} (100%) diff --git a/Makefile.am b/Makefile.am index c6af7d99..a79d50c2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -49,6 +49,7 @@ strace_SOURCES = \ count.c \ desc.c \ dirent.c \ + dirent64.c \ empty.h \ epoll.c \ evdev.c \ diff --git a/defs.h b/defs.h index 1fe5975a..5e40f4db 100644 --- a/defs.h +++ b/defs.h @@ -413,6 +413,7 @@ extern const struct xlat addrfams[]; extern const struct xlat adjtimex_modes[]; extern const struct xlat adjtimex_status[]; extern const struct xlat at_flags[]; +extern const struct xlat dirent_types[]; extern const struct xlat open_access_modes[]; extern const struct xlat open_mode_flags[]; extern const struct xlat resource_flags[]; diff --git a/dirent.c b/dirent.c index dec436b5..cd50968d 100644 --- a/dirent.c +++ b/dirent.c @@ -1,29 +1,55 @@ +/* + * Copyright (c) 1991, 1992 Paul Kranenburg + * Copyright (c) 1993 Branko Lankester + * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey + * Copyright (c) 1996-1999 Wichert Akkerman + * Copyright (c) 2005-2015 Dmitry V. Levin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + #include "defs.h" -#include -#define D_NAME_LEN_MAX 256 +#include DEF_MPERS_TYPE(kernel_dirent) + +#include -struct kernel_dirent { +typedef struct { unsigned long d_ino; unsigned long d_off; unsigned short d_reclen; char d_name[1]; -}; +} kernel_dirent; + +#include MPERS_DEFS + +#define D_NAME_LEN_MAX 256 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; + kernel_dirent d; if (umove_or_printaddr(tcp, addr, &d)) return; @@ -32,7 +58,7 @@ print_old_dirent(struct tcb *tcp, long addr) (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); + printpathn(tcp, addr + offsetof(kernel_dirent, d_name), d.d_reclen); tprints("}"); } @@ -53,8 +79,6 @@ SYS_FUNC(readdir) return 0; } -#include "xlat/direnttypes.h" - SYS_FUNC(getdents) { unsigned int i, len, dents = 0; @@ -74,7 +98,7 @@ SYS_FUNC(getdents) /* Beware of insanely large or too small values in tcp->u_rval */ if (tcp->u_rval > 1024*1024) len = 1024*1024; - else if (tcp->u_rval < (int) sizeof(struct kernel_dirent)) + else if (tcp->u_rval < (int) sizeof(kernel_dirent)) len = 0; else len = tcp->u_rval; @@ -93,19 +117,20 @@ SYS_FUNC(getdents) if (!abbrev(tcp)) tprints("["); - for (i = 0; len && i <= len - sizeof(struct kernel_dirent); ) { - struct kernel_dirent *d = (struct kernel_dirent *) &buf[i]; + for (i = 0; len && i <= len - sizeof(kernel_dirent); ) { + kernel_dirent *d = (kernel_dirent *) &buf[i]; if (!abbrev(tcp)) { - int oob = d->d_reclen < sizeof(struct kernel_dirent) || + int oob = d->d_reclen < sizeof(kernel_dirent) || i + d->d_reclen - 1 >= len; int d_name_len = oob ? len - i : d->d_reclen; - d_name_len -= offsetof(struct kernel_dirent, d_name) + 1; + d_name_len -= offsetof(kernel_dirent, d_name) + 1; if (d_name_len > D_NAME_LEN_MAX) d_name_len = D_NAME_LEN_MAX; tprintf("%s{d_ino=%lu, d_off=%lu, d_reclen=%u, d_name=", - i ? ", " : "", d->d_ino, d->d_off, d->d_reclen); + i ? ", " : "", (unsigned long) d->d_ino, + (unsigned long) d->d_off, d->d_reclen); if (print_quoted_string(d->d_name, d_name_len, QUOTE_0_TERMINATED) > 0) { @@ -116,101 +141,15 @@ SYS_FUNC(getdents) if (oob) tprints("?"); else - printxval(direnttypes, buf[i + d->d_reclen - 1], "DT_???"); + printxval(dirent_types, buf[i + d->d_reclen - 1], "DT_???"); tprints("}"); } dents++; - if (d->d_reclen < sizeof(struct kernel_dirent)) { - tprints("/* d_reclen < sizeof(struct kernel_dirent) */"); - break; - } - i += d->d_reclen; - } - if (!abbrev(tcp)) - tprints("]"); - else - tprintf("/* %u entries */", dents); - tprintf(", %lu", tcp->u_arg[2]); - free(buf); - return 0; -} - -SYS_FUNC(getdents64) -{ - /* the minimum size of a valid dirent64 structure */ - const unsigned int d_name_offset = offsetof(struct dirent64, d_name); - - unsigned int i, len, dents = 0; - char *buf; - - if (entering(tcp)) { - printfd(tcp, tcp->u_arg[0]); - tprints(", "); - return 0; - } - if (syserror(tcp) || !verbose(tcp)) { - printaddr(tcp->u_arg[1]); - tprintf(", %lu", tcp->u_arg[2]); - return 0; - } - - /* Beware of insanely large or too small tcp->u_rval */ - if (tcp->u_rval > 1024*1024) - len = 1024*1024; - else if (tcp->u_rval < (int) d_name_offset) - len = 0; - else - len = tcp->u_rval; - - if (len) { - buf = malloc(len); - if (!buf || umoven(tcp, tcp->u_arg[1], len, buf) < 0) { - printaddr(tcp->u_arg[1]); - tprintf(", %lu", tcp->u_arg[2]); - free(buf); - return 0; - } - } else { - buf = NULL; - } - - if (!abbrev(tcp)) - tprints("["); - for (i = 0; len && i <= len - d_name_offset; ) { - struct dirent64 *d = (struct dirent64 *) &buf[i]; - if (!abbrev(tcp)) { - int d_name_len; - if (d->d_reclen >= d_name_offset - && i + d->d_reclen <= len) { - d_name_len = d->d_reclen - d_name_offset; - } else { - d_name_len = len - i - d_name_offset; - } - if (d_name_len > D_NAME_LEN_MAX) - d_name_len = D_NAME_LEN_MAX; - - tprintf("%s{d_ino=%" PRIu64 ", d_off=%" PRId64 - ", d_reclen=%u, d_type=", - i ? ", " : "", - d->d_ino, - d->d_off, - d->d_reclen); - printxval(direnttypes, d->d_type, "DT_???"); - - tprints(", d_name="); - if (print_quoted_string(d->d_name, d_name_len, - QUOTE_0_TERMINATED) > 0) { - tprints("..."); - } - - tprints("}"); - } - if (d->d_reclen < d_name_offset) { - tprints("/* d_reclen < offsetof(struct dirent64, d_name) */"); + if (d->d_reclen < sizeof(kernel_dirent)) { + tprints("/* d_reclen < sizeof(kernel_dirent) */"); break; } i += d->d_reclen; - dents++; } if (!abbrev(tcp)) tprints("]"); diff --git a/dirent64.c b/dirent64.c new file mode 100644 index 00000000..3c90a258 --- /dev/null +++ b/dirent64.c @@ -0,0 +1,123 @@ +/* + * Copyright (c) 1991, 1992 Paul Kranenburg + * Copyright (c) 1993 Branko Lankester + * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey + * Copyright (c) 1996-1999 Wichert Akkerman + * Copyright (c) 2005-2015 Dmitry V. Levin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "defs.h" +#include + +#include "xlat/dirent_types.h" + +#define D_NAME_LEN_MAX 256 + +SYS_FUNC(getdents64) +{ + /* the minimum size of a valid dirent64 structure */ + const unsigned int d_name_offset = offsetof(struct dirent64, d_name); + + unsigned int i, len, dents = 0; + char *buf; + + if (entering(tcp)) { + printfd(tcp, tcp->u_arg[0]); + tprints(", "); + return 0; + } + if (syserror(tcp) || !verbose(tcp)) { + printaddr(tcp->u_arg[1]); + tprintf(", %lu", tcp->u_arg[2]); + return 0; + } + + /* Beware of insanely large or too small values in tcp->u_rval */ + if (tcp->u_rval > 1024*1024) + len = 1024*1024; + else if (tcp->u_rval < (int) d_name_offset) + len = 0; + else + len = tcp->u_rval; + + if (len) { + buf = malloc(len); + if (!buf || umoven(tcp, tcp->u_arg[1], len, buf) < 0) { + printaddr(tcp->u_arg[1]); + tprintf(", %lu", tcp->u_arg[2]); + free(buf); + return 0; + } + } else { + buf = NULL; + } + + if (!abbrev(tcp)) + tprints("["); + for (i = 0; len && i <= len - d_name_offset; ) { + struct dirent64 *d = (struct dirent64 *) &buf[i]; + if (!abbrev(tcp)) { + int d_name_len; + if (d->d_reclen >= d_name_offset + && i + d->d_reclen <= len) { + d_name_len = d->d_reclen - d_name_offset; + } else { + d_name_len = len - i - d_name_offset; + } + if (d_name_len > D_NAME_LEN_MAX) + d_name_len = D_NAME_LEN_MAX; + + tprintf("%s{d_ino=%" PRIu64 ", d_off=%" PRId64 + ", d_reclen=%u, d_type=", + i ? ", " : "", + d->d_ino, + d->d_off, + d->d_reclen); + printxval(dirent_types, d->d_type, "DT_???"); + + tprints(", d_name="); + if (print_quoted_string(d->d_name, d_name_len, + QUOTE_0_TERMINATED) > 0) { + tprints("..."); + } + + tprints("}"); + } + if (d->d_reclen < d_name_offset) { + tprints("/* d_reclen < offsetof(struct dirent64, d_name) */"); + break; + } + i += d->d_reclen; + dents++; + } + if (!abbrev(tcp)) + tprints("]"); + else + tprintf("/* %u entries */", dents); + tprintf(", %lu", tcp->u_arg[2]); + free(buf); + return 0; +} diff --git a/xlat/direnttypes.in b/xlat/dirent_types.in similarity index 100% rename from xlat/direnttypes.in rename to xlat/dirent_types.in -- 2.40.0