From: Wayne Davison Date: Wed, 6 Feb 2008 15:52:00 +0000 (-0800) Subject: Make get_xattr_names() even safer at fetching the list of attr names. X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/commitdiff_plain/71daa07fb1c791c0f5eba3fc1b615df3a46441fc Make get_xattr_names() even safer at fetching the list of attr names. --- diff --git a/xattrs.c b/xattrs.c index 61d4f607..9eca6bdb 100644 --- a/xattrs.c +++ b/xattrs.c @@ -111,6 +111,7 @@ static int rsync_xal_compare_names(const void *x1, const void *x2) static ssize_t get_xattr_names(const char *fname) { ssize_t list_len; + double arg; if (!namebuf) { namebuf_len = 1024; @@ -119,39 +120,36 @@ static ssize_t get_xattr_names(const char *fname) out_of_memory("get_xattr_names"); } - /* The length returned includes all the '\0' terminators. */ - list_len = sys_llistxattr(fname, namebuf, namebuf_len); - if (list_len > (ssize_t)namebuf_len) { - list_len = -1; - errno = ERANGE; - } - if (list_len >= 0) - return list_len; - if (errno == ENOTSUP) - return 0; - if (errno == ERANGE) { - list_len = sys_llistxattr(fname, NULL, 0); - if (list_len < 0) { + while (1) { + /* The length returned includes all the '\0' terminators. */ + list_len = sys_llistxattr(fname, namebuf, namebuf_len); + if (list_len >= 0) { + if ((size_t)list_len <= namebuf_len) + break; + } else if (errno == ENOTSUP) + return 0; + else if (errno != ERANGE) { + arg = (double)namebuf_len; + got_error: rsyserr(FERROR_XFER, errno, - "get_xattr_names: llistxattr(\"%s\",0) failed", - fname); + "get_xattr_names: llistxattr(\"%s\",%.0f) failed", + fname, arg); return -1; } + list_len = sys_llistxattr(fname, NULL, 0); + if (list_len < 0) { + arg = 0; + goto got_error; + } if (namebuf_len) free(namebuf); namebuf_len = list_len + 1024; namebuf = new_array(char, namebuf_len); if (!namebuf) out_of_memory("get_xattr_names"); - list_len = sys_llistxattr(fname, namebuf, namebuf_len); - if (list_len >= 0) - return list_len; } - rsyserr(FERROR_XFER, errno, - "get_xattr_names: llistxattr(\"%s\",%ld) failed", - fname, (long)namebuf_len); - return -1; + return list_len; } /* On entry, the *len_ptr parameter contains the size of the extra space we