]> granicus.if.org Git - strace/commitdiff
Fix corner cases of xattr family syscalls decoding
authorDmitry V. Levin <ldv@altlinux.org>
Tue, 10 May 2016 18:52:06 +0000 (18:52 +0000)
committerDmitry V. Levin <ldv@altlinux.org>
Tue, 10 May 2016 21:50:37 +0000 (21:50 +0000)
* xattr.c (print_xattr_val): Do not take insize into account, print it
as unsigned long.
Do not decode xattr values of size larger than XATTR_SIZE_MAX.
Use static buffer for fetching xattr values.
(print_xattr_list): Do not decode string when size is zero.

xattr.c

diff --git a/xattr.c b/xattr.c
index c47ebd6dd41909d597c41044da56cd2947ce4ef4..30a8467ca390f21d130030de909e1c2b349fd9c0 100644 (file)
--- a/xattr.c
+++ b/xattr.c
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 2002-2005 Roland McGrath <roland@redhat.com>
  * Copyright (c) 2004 Ulrich Drepper <drepper@redhat.com>
- * Copyright (c) 2005-2015 Dmitry V. Levin <ldv@altlinux.org>
+ * Copyright (c) 2005-2016 Dmitry V. Levin <ldv@altlinux.org>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
 
 #include "xlat/xattrflags.h"
 
+#ifndef XATTR_SIZE_MAX
+# define XATTR_SIZE_MAX 65536
+#endif
+
 static void
 print_xattr_val(struct tcb *tcp,
                unsigned long addr,
                unsigned long insize,
                unsigned long size)
 {
-       char *buf = NULL;
-       unsigned int len;
+       static char buf[XATTR_SIZE_MAX];
 
        tprints(", ");
 
-       if (insize == 0)
-               goto done;
-
-       len = size;
-       if (size != (unsigned long) len)
-               goto done;
-
-       if (!len) {
-               tprintf("\"\", %ld", insize);
-               return;
-       }
-
-       if (!verbose(tcp) || (exiting(tcp) && syserror(tcp)))
-               goto done;
-
-       buf = malloc(len);
-       if (!buf)
-               goto done;
-
-       if (umoven(tcp, addr, len, buf) < 0) {
-               free(buf);
-               buf = NULL;
-               goto done;
-       }
-
-       /* Don't print terminating NUL if there is one. */
-       if (buf[len - 1] == '\0')
-               --len;
-
-done:
-       if (buf) {
-               print_quoted_string(buf, len, 0);
-               free(buf);
-       } else {
+       if (!addr || size > sizeof(buf))
                printaddr(addr);
+       else if (!size || !umoven_or_printaddr(tcp, addr, size, buf)) {
+               /* Don't print terminating NUL if there is one. */
+               if (size && buf[size - 1] == '\0')
+                       --size;
+
+               print_quoted_string(buf, size, 0);
        }
-       tprintf(", %ld", insize);
+       tprintf(", %lu", insize);
 }
 
 SYS_FUNC(setxattr)
@@ -134,13 +110,10 @@ SYS_FUNC(fgetxattr)
 static void
 print_xattr_list(struct tcb *tcp, unsigned long addr, unsigned long size)
 {
-       if (syserror(tcp)) {
+       if (!size || syserror(tcp)) {
                printaddr(addr);
        } else {
-               unsigned long len =
-                       (size < (unsigned long) tcp->u_rval) ?
-                               size : (unsigned long) tcp->u_rval;
-               printstr(tcp, addr, len);
+               printstr(tcp, addr, tcp->u_rval);
        }
        tprintf(", %lu", size);
 }