From patchwork Wed Jan 4 21:06:57 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [5/7] libjunction: Don't treat opaque byte array as NUL-terminated Date: Wed, 04 Jan 2012 11:06:57 -0000 From: Chuck Lever X-Patchwork-Id: 134361 Message-Id: <20120104210657.8810.73069.stgit@degas.1015granger.net> To: fedfs-utils-devel@oss.oracle.com junction_get_xattr() returns an opaque byte array, but junction_restore_mode() treats it like a NUL-terminated string. Bad function, no biscuit. Fork off a second API that can return a NUL-terminated string. Callers will have to take care to choose the correct API. Introduced in commit 0520ee72: "Initial commit," (March 29, 2011). Signed-off-by: Chuck Lever --- src/libjunction/junction-internal.h | 2 + src/libjunction/junction.c | 57 +++++++++++++++++++++++++++++++++-- 2 files changed, 55 insertions(+), 4 deletions(-) diff --git a/src/libjunction/junction-internal.h b/src/libjunction/junction-internal.h index c013275..5be355d 100644 --- a/src/libjunction/junction-internal.h +++ b/src/libjunction/junction-internal.h @@ -32,6 +32,8 @@ FedFsStatus junction_is_sticky_bit_set(int fd, const char *path); FedFsStatus junction_set_sticky_bit(int fd, const char *path); FedFsStatus junction_is_xattr_present(int fd, const char *path, const char *name); +FedFsStatus junction_read_xattr(int fd, const char *path, const char *name, + char **contents); FedFsStatus junction_get_xattr(int fd, const char *path, const char *name, void **contents, size_t *contentlen); FedFsStatus junction_set_xattr(int fd, const char *path, const char *name, diff --git a/src/libjunction/junction.c b/src/libjunction/junction.c index 7bde11a..832c19f 100644 --- a/src/libjunction/junction.c +++ b/src/libjunction/junction.c @@ -221,6 +221,54 @@ junction_is_xattr_present(int fd, const char *path, const char *name) } /** + * Read the contents of xattr "name" + * + * @param fd an open file descriptor + * @param path NUL-terminated C string containing pathname of a directory + * @param name NUL-terminated C string containing name of xattr to retrieve + * @param contents OUT: NUL-terminated C string containing contents of xattr + * @return a FedFsStatus code + * + * If junction_read_xattr() returns FEDFS_OK, the caller must free "*contents" + * with free(3). + * + * @note Access to trusted attributes requires CAP_SYS_ADMIN. + */ +FedFsStatus +junction_read_xattr(int fd, const char *path, const char *name, char **contents) +{ + char *xattrbuf = NULL; + ssize_t len; + + len = fgetxattr(fd, name, xattrbuf, 0); + if (len == -1) { + xlog(D_GENERAL, "%s: failed to get size of xattr %s on %s: %m", + __func__, name, path); + return FEDFS_ERR_ACCESS; + } + + xattrbuf = malloc(len + 1); + if (xattrbuf == NULL) { + xlog(D_GENERAL, "%s: failed to get buffer for xattr %s on %s", + __func__, name, path); + return FEDFS_ERR_SVRFAULT; + } + + if (fgetxattr(fd, name, xattrbuf, len) == -1) { + xlog(D_GENERAL, "%s: failed to get xattr %s on %s: %m", + __func__, name, path); + free(xattrbuf); + return FEDFS_ERR_ACCESS; + } + xattrbuf[len] = '\0'; + + xlog(D_CALL, "%s: read xattr %s from path %s", + __func__, name, path); + *contents = xattrbuf; + return FEDFS_OK; +} + +/** * Retrieve the contents of xattr "name" * * @param fd an open file descriptor @@ -230,6 +278,9 @@ junction_is_xattr_present(int fd, const char *path, const char *name) * @param contentlen OUT: size of "contents" * @return a FedFsStatus code * + * If junction_get_xattr() returns FEDFS_OK, the caller must free "*contents" + * with free(3). + * * @note Access to trusted attributes requires CAP_SYS_ADMIN. */ FedFsStatus @@ -386,17 +437,15 @@ FedFsStatus junction_restore_mode(const char *pathname) { FedFsStatus retval; + char *buf = NULL; mode_t mode; - size_t len; - void *buf; int fd; retval = junction_open_path(pathname, &fd); if (retval != FEDFS_OK) return retval; - retval = junction_get_xattr(fd, pathname, JUNCTION_XATTR_NAME_MODE, - &buf, &len); + retval = junction_read_xattr(fd, pathname, JUNCTION_XATTR_NAME_MODE, &buf); if (retval != FEDFS_OK) goto out;