mrc0mmand / rpms / libguestfs

Forked from rpms/libguestfs 3 years ago
Clone

Blame SOURCES/0056-daemon-xattr-Refactor-code-which-splits-attr-names-f.patch

10436e
From 052549a055bbedc402418bc52bcbfa3bfcb97952 Mon Sep 17 00:00:00 2001
10436e
From: "Richard W.M. Jones" <rjones@redhat.com>
10436e
Date: Thu, 12 Mar 2020 13:57:06 +0000
10436e
Subject: [PATCH] daemon: xattr: Refactor code which splits attr names from the
10436e
 kernel.
10436e
10436e
The kernel returns xattr names in a slightly peculiar format.  We
10436e
parsed this format several times in the code.  Refactor this parsing
10436e
so we only do it in one place.
10436e
10436e
(cherry picked from commit 5c175fe73264bbf1d3ef79bb066dfb6aff902ad1)
10436e
---
10436e
 daemon/xattr.c | 127 ++++++++++++++++++++++++++++++-------------------
10436e
 1 file changed, 79 insertions(+), 48 deletions(-)
10436e
10436e
diff --git a/daemon/xattr.c b/daemon/xattr.c
10436e
index bc5c2df97..3e1144963 100644
10436e
--- a/daemon/xattr.c
10436e
+++ b/daemon/xattr.c
10436e
@@ -89,6 +89,36 @@ do_lremovexattr (const char *xattr, const char *path)
10436e
   return _removexattr (xattr, path, lremovexattr);
10436e
 }
10436e
 
10436e
+/**
10436e
+ * L<listxattr(2)> returns the string C<"foo\0bar\0baz"> of length
10436e
+ * C<len>.  (The last string in the list is \0-terminated but the \0
10436e
+ * is not included in C<len>).
10436e
+ *
10436e
+ * This function splits it into a regular list of strings.
10436e
+ *
10436e
+ * B<Note> that the returned list contains pointers to the original
10436e
+ * strings in C<buf> so be careful that you do not double-free them.
10436e
+ */
10436e
+static char **
10436e
+split_attr_names (char *buf, size_t len)
10436e
+{
10436e
+  size_t i;
10436e
+  DECLARE_STRINGSBUF (ret);
10436e
+
10436e
+  for (i = 0; i < len; i += strlen (&buf[i]) + 1) {
10436e
+    if (add_string_nodup (&ret, &buf[i]) == -1) {
10436e
+      free (ret.argv);
10436e
+      return NULL;
10436e
+    }
10436e
+  }
10436e
+  if (end_stringsbuf (&ret) == -1) {
10436e
+    free (ret.argv);
10436e
+    return NULL;
10436e
+  }
10436e
+
10436e
+  return take_stringsbuf (&ret;;
10436e
+}
10436e
+
10436e
 static int
10436e
 compare_xattrs (const void *vxa1, const void *vxa2)
10436e
 {
10436e
@@ -106,7 +136,8 @@ getxattrs (const char *path,
10436e
 {
10436e
   ssize_t len, vlen;
10436e
   CLEANUP_FREE char *buf = NULL;
10436e
-  size_t i, j;
10436e
+  CLEANUP_FREE /* not string list */ char **names = NULL;
10436e
+  size_t i;
10436e
   guestfs_int_xattr_list *r = NULL;
10436e
 
10436e
   buf = _listxattrs (path, listxattr, &len;;
10436e
@@ -114,18 +145,17 @@ getxattrs (const char *path,
10436e
     /* _listxattrs issues reply_with_perror already. */
10436e
     goto error;
10436e
 
10436e
+  names = split_attr_names (buf, len);
10436e
+  if (names == NULL)
10436e
+    goto error;
10436e
+
10436e
   r = calloc (1, sizeof (*r));
10436e
   if (r == NULL) {
10436e
     reply_with_perror ("calloc");
10436e
     goto error;
10436e
   }
10436e
 
10436e
-  /* What we get from the kernel is a string "foo\0bar\0baz" of length
10436e
-   * len.  First count the strings.
10436e
-   */
10436e
-  r->guestfs_int_xattr_list_len = 0;
10436e
-  for (i = 0; i < (size_t) len; i += strlen (&buf[i]) + 1)
10436e
-    r->guestfs_int_xattr_list_len++;
10436e
+  r->guestfs_int_xattr_list_len = guestfs_int_count_strings (names);
10436e
 
10436e
   r->guestfs_int_xattr_list_val =
10436e
     calloc (r->guestfs_int_xattr_list_len, sizeof (guestfs_int_xattr));
10436e
@@ -134,34 +164,34 @@ getxattrs (const char *path,
10436e
     goto error;
10436e
   }
10436e
 
10436e
-  for (i = 0, j = 0; i < (size_t) len; i += strlen (&buf[i]) + 1, ++j) {
10436e
+  for (i = 0; names[i] != NULL; ++i) {
10436e
     CHROOT_IN;
10436e
-    vlen = getxattr (path, &buf[i], NULL, 0);
10436e
+    vlen = getxattr (path, names[i], NULL, 0);
10436e
     CHROOT_OUT;
10436e
     if (vlen == -1) {
10436e
-      reply_with_perror ("getxattr");
10436e
+      reply_with_perror ("getxattr: %s", names[i]);
10436e
       goto error;
10436e
     }
10436e
 
10436e
     if (vlen > XATTR_SIZE_MAX) {
10436e
       /* The next call to getxattr will fail anyway, so ... */
10436e
-      reply_with_error ("extended attribute is too large");
10436e
+      reply_with_error ("%s: extended attribute is too large", names[i]);
10436e
       goto error;
10436e
     }
10436e
 
10436e
-    r->guestfs_int_xattr_list_val[j].attrname = strdup (&buf[i]);
10436e
-    r->guestfs_int_xattr_list_val[j].attrval.attrval_val = malloc (vlen);
10436e
-    r->guestfs_int_xattr_list_val[j].attrval.attrval_len = vlen;
10436e
+    r->guestfs_int_xattr_list_val[i].attrname = strdup (names[i]);
10436e
+    r->guestfs_int_xattr_list_val[i].attrval.attrval_val = malloc (vlen);
10436e
+    r->guestfs_int_xattr_list_val[i].attrval.attrval_len = vlen;
10436e
 
10436e
-    if (r->guestfs_int_xattr_list_val[j].attrname == NULL ||
10436e
-        r->guestfs_int_xattr_list_val[j].attrval.attrval_val == NULL) {
10436e
+    if (r->guestfs_int_xattr_list_val[i].attrname == NULL ||
10436e
+        r->guestfs_int_xattr_list_val[i].attrval.attrval_val == NULL) {
10436e
       reply_with_perror ("malloc");
10436e
       goto error;
10436e
     }
10436e
 
10436e
     CHROOT_IN;
10436e
-    vlen = getxattr (path, &buf[i],
10436e
-                     r->guestfs_int_xattr_list_val[j].attrval.attrval_val,
10436e
+    vlen = getxattr (path, names[i],
10436e
+                     r->guestfs_int_xattr_list_val[i].attrval.attrval_val,
10436e
                      vlen);
10436e
     CHROOT_OUT;
10436e
     if (vlen == -1) {
10436e
@@ -276,7 +306,7 @@ guestfs_int_xattr_list *
10436e
 do_internal_lxattrlist (const char *path, char *const *names)
10436e
 {
10436e
   guestfs_int_xattr_list *ret = NULL;
10436e
-  size_t i, j;
10436e
+  size_t i;
10436e
   size_t k, m, nr_attrs;
10436e
   ssize_t len, vlen;
10436e
 
10436e
@@ -293,6 +323,7 @@ do_internal_lxattrlist (const char *path, char *const *names)
10436e
     void *newptr;
10436e
     CLEANUP_FREE char *pathname = NULL;
10436e
     CLEANUP_FREE char *buf = NULL;
10436e
+    CLEANUP_FREE /* not string list */ char **attrnames = NULL;
10436e
 
10436e
     /* Be careful in this loop about which errors cause the whole call
10436e
      * to abort, and which errors allow us to continue processing
10436e
@@ -350,12 +381,10 @@ do_internal_lxattrlist (const char *path, char *const *names)
10436e
     if (len == -1)
10436e
       continue; /* not fatal */
10436e
 
10436e
-    /* What we get from the kernel is a string "foo\0bar\0baz" of length
10436e
-     * len.  First count the strings.
10436e
-     */
10436e
-    nr_attrs = 0;
10436e
-    for (i = 0; i < (size_t) len; i += strlen (&buf[i]) + 1)
10436e
-      nr_attrs++;
10436e
+    attrnames = split_attr_names (buf, len);
10436e
+    if (attrnames == NULL)
10436e
+      goto error;
10436e
+    nr_attrs = guestfs_int_count_strings (attrnames);
10436e
 
10436e
     newptr =
10436e
       realloc (ret->guestfs_int_xattr_list_val,
10436e
@@ -378,36 +407,36 @@ do_internal_lxattrlist (const char *path, char *const *names)
10436e
       entry[m].attrval.attrval_val = NULL;
10436e
     }
10436e
 
10436e
-    for (i = 0, j = 0; i < (size_t) len; i += strlen (&buf[i]) + 1, ++j) {
10436e
+    for (i = 0; attrnames[i] != NULL; ++i) {
10436e
       CHROOT_IN;
10436e
-      vlen = lgetxattr (pathname, &buf[i], NULL, 0);
10436e
+      vlen = lgetxattr (pathname, attrnames[i], NULL, 0);
10436e
       CHROOT_OUT;
10436e
       if (vlen == -1) {
10436e
-        reply_with_perror ("getxattr");
10436e
+        reply_with_perror ("getxattr: %s", attrnames[i]);
10436e
         goto error;
10436e
       }
10436e
 
10436e
       if (vlen > XATTR_SIZE_MAX) {
10436e
-        reply_with_error ("extended attribute is too large");
10436e
+        reply_with_error ("%s: extended attribute is too large", attrnames[i]);
10436e
         goto error;
10436e
       }
10436e
 
10436e
-      entry[j+1].attrname = strdup (&buf[i]);
10436e
-      entry[j+1].attrval.attrval_val = malloc (vlen);
10436e
-      entry[j+1].attrval.attrval_len = vlen;
10436e
+      entry[i+1].attrname = strdup (attrnames[i]);
10436e
+      entry[i+1].attrval.attrval_val = malloc (vlen);
10436e
+      entry[i+1].attrval.attrval_len = vlen;
10436e
 
10436e
-      if (entry[j+1].attrname == NULL ||
10436e
-          entry[j+1].attrval.attrval_val == NULL) {
10436e
+      if (entry[i+1].attrname == NULL ||
10436e
+          entry[i+1].attrval.attrval_val == NULL) {
10436e
         reply_with_perror ("malloc");
10436e
         goto error;
10436e
       }
10436e
 
10436e
       CHROOT_IN;
10436e
-      vlen = lgetxattr (pathname, &buf[i],
10436e
-                        entry[j+1].attrval.attrval_val, vlen);
10436e
+      vlen = lgetxattr (pathname, attrnames[i],
10436e
+                        entry[i+1].attrval.attrval_val, vlen);
10436e
       CHROOT_OUT;
10436e
       if (vlen == -1) {
10436e
-        reply_with_perror ("getxattr");
10436e
+        reply_with_perror ("getxattr: %s", attrnames[i]);
10436e
         goto error;
10436e
       }
10436e
     }
10436e
@@ -510,6 +539,7 @@ copy_xattrs (const char *src, const char *dest)
10436e
 {
10436e
   ssize_t len, vlen, ret, attrval_len = 0;
10436e
   CLEANUP_FREE char *buf = NULL, *attrval = NULL;
10436e
+  CLEANUP_FREE /* not string list */ char **names = NULL;
10436e
   size_t i;
10436e
 
10436e
   buf = _listxattrs (src, listxattr, &len;;
10436e
@@ -517,21 +547,22 @@ copy_xattrs (const char *src, const char *dest)
10436e
     /* _listxattrs issues reply_with_perror already. */
10436e
     goto error;
10436e
 
10436e
-  /* What we get from the kernel is a string "foo\0bar\0baz" of length
10436e
-   * len.
10436e
-   */
10436e
-  for (i = 0; i < (size_t) len; i += strlen (&buf[i]) + 1) {
10436e
+  names = split_attr_names (buf, len);
10436e
+  if (names == NULL)
10436e
+    goto error;
10436e
+
10436e
+  for (i = 0; names[i] != NULL; ++i) {
10436e
     CHROOT_IN;
10436e
-    vlen = getxattr (src, &buf[i], NULL, 0);
10436e
+    vlen = getxattr (src, names[i], NULL, 0);
10436e
     CHROOT_OUT;
10436e
     if (vlen == -1) {
10436e
-      reply_with_perror ("getxattr: %s, %s", src, &buf[i]);
10436e
+      reply_with_perror ("getxattr: %s, %s", src, names[i]);
10436e
       goto error;
10436e
     }
10436e
 
10436e
     if (vlen > XATTR_SIZE_MAX) {
10436e
       /* The next call to getxattr will fail anyway, so ... */
10436e
-      reply_with_error ("extended attribute is too large");
10436e
+      reply_with_error ("%s: extended attribute is too large", names[i]);
10436e
       goto error;
10436e
     }
10436e
 
10436e
@@ -546,18 +577,18 @@ copy_xattrs (const char *src, const char *dest)
10436e
     }
10436e
 
10436e
     CHROOT_IN;
10436e
-    vlen = getxattr (src, &buf[i], attrval, vlen);
10436e
+    vlen = getxattr (src, names[i], attrval, vlen);
10436e
     CHROOT_OUT;
10436e
     if (vlen == -1) {
10436e
-      reply_with_perror ("getxattr: %s, %s", src, &buf[i]);
10436e
+      reply_with_perror ("getxattr: %s, %s", src, names[i]);
10436e
       goto error;
10436e
     }
10436e
 
10436e
     CHROOT_IN;
10436e
-    ret = setxattr (dest, &buf[i], attrval, vlen, 0);
10436e
+    ret = setxattr (dest, names[i], attrval, vlen, 0);
10436e
     CHROOT_OUT;
10436e
     if (ret == -1) {
10436e
-      reply_with_perror ("setxattr: %s, %s", dest, &buf[i]);
10436e
+      reply_with_perror ("setxattr: %s, %s", dest, names[i]);
10436e
       goto error;
10436e
     }
10436e
   }
10436e
-- 
10436e
2.26.2
10436e