From: Jeremy Allison Date: Mon, 23 Jan 2017 18:20:13 +0000 (-0800) Subject: s3: VFS: shadow_copy2: Fix usage of saved_errno to only set errno on error. X-Git-Tag: samba-4.4.10~37 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=eeef5e408ba03815cf175539f5c83c34cb05aa24;p=thirdparty%2Fsamba.git s3: VFS: shadow_copy2: Fix usage of saved_errno to only set errno on error. Rationale: VFS calls must act like their POSIX equivalents, and the POSIX versions *only* set errno on a failure. There is actually code in the upper smbd layers that depends on errno being correct on a fail return from a VFS call. For a compound VFS module like this, a common pattern is : SMB_VFS_CALL_X() { int ret; syscall1(); ret = syscall2(); syscall3(); return ret; } Where if *any* of the contained syscallX()'s fail, they'll set errno. However, the actual errno we should return is *only* the one returned if syscall2() fails (the others are lstat's checking for existence etc.). So what we should do to correctly return only the errno from syscall2() is: SMB_VFS_CALL_X() { int ret; int saved_errno = 0; syscall1() ret = syscall2(); if (ret == -1) { saved_errno = errno; } syscall3() if (saved_errno != 0) { errno = saved_errno; } return ret; } BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531 Signed-off-by: Jeremy Allison Reviewed-by: Uri Simchoni (backported from commit cda6764f1a8db96182bfd1855440bc6a1ba1abee) --- diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c index aecc4822558..f773d4f98c2 100644 --- a/source3/modules/vfs_shadow_copy2.c +++ b/source3/modules/vfs_shadow_copy2.c @@ -619,7 +619,8 @@ static char *shadow_copy2_do_convert(TALLOC_CTX *mem_ctx, char *insert = NULL; char *converted = NULL; size_t insertlen, connectlen = 0; - int i, saved_errno; + int saved_errno = 0; + int i; size_t min_offset; struct shadow_copy2_config *config; size_t in_share_offset = 0; @@ -802,12 +803,16 @@ static char *shadow_copy2_do_convert(TALLOC_CTX *mem_ctx, errno = ENOENT; } fail: - saved_errno = errno; + if (result == NULL) { + saved_errno = errno; + } TALLOC_FREE(converted); TALLOC_FREE(insert); TALLOC_FREE(slashes); TALLOC_FREE(path); - errno = saved_errno; + if (saved_errno != 0) { + errno = saved_errno; + } return result; } @@ -866,7 +871,7 @@ static DIR *shadow_copy2_opendir(vfs_handle_struct *handle, time_t timestamp = 0; char *stripped = NULL; DIR *ret; - int saved_errno; + int saved_errno = 0; char *conv; if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, @@ -882,9 +887,13 @@ static DIR *shadow_copy2_opendir(vfs_handle_struct *handle, return NULL; } ret = SMB_VFS_NEXT_OPENDIR(handle, conv, mask, attr); - saved_errno = errno; + if (ret == NULL) { + saved_errno = errno; + } TALLOC_FREE(conv); - errno = saved_errno; + if (saved_errno != 0) { + errno = saved_errno; + } return ret; } @@ -964,7 +973,8 @@ static int shadow_copy2_stat(vfs_handle_struct *handle, time_t timestamp = 0; char *stripped = NULL; char *tmp; - int ret, saved_errno; + int saved_errno = 0; + int ret; if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, smb_fname->base_name, @@ -986,7 +996,9 @@ static int shadow_copy2_stat(vfs_handle_struct *handle, } ret = SMB_VFS_NEXT_STAT(handle, smb_fname); - saved_errno = errno; + if (ret == -1) { + saved_errno = errno; + } TALLOC_FREE(smb_fname->base_name); smb_fname->base_name = tmp; @@ -994,7 +1006,9 @@ static int shadow_copy2_stat(vfs_handle_struct *handle, if (ret == 0) { convert_sbuf(handle, smb_fname->base_name, &smb_fname->st); } - errno = saved_errno; + if (saved_errno != 0) { + errno = saved_errno; + } return ret; } @@ -1004,7 +1018,8 @@ static int shadow_copy2_lstat(vfs_handle_struct *handle, time_t timestamp = 0; char *stripped = NULL; char *tmp; - int ret, saved_errno; + int saved_errno = 0; + int ret; if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, smb_fname->base_name, @@ -1026,7 +1041,9 @@ static int shadow_copy2_lstat(vfs_handle_struct *handle, } ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname); - saved_errno = errno; + if (ret == -1) { + saved_errno = errno; + } TALLOC_FREE(smb_fname->base_name); smb_fname->base_name = tmp; @@ -1034,7 +1051,9 @@ static int shadow_copy2_lstat(vfs_handle_struct *handle, if (ret == 0) { convert_sbuf(handle, smb_fname->base_name, &smb_fname->st); } - errno = saved_errno; + if (saved_errno != 0) { + errno = saved_errno; + } return ret; } @@ -1066,7 +1085,8 @@ static int shadow_copy2_open(vfs_handle_struct *handle, time_t timestamp = 0; char *stripped = NULL; char *tmp; - int ret, saved_errno; + int saved_errno = 0; + int ret; if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, smb_fname->base_name, @@ -1088,12 +1108,16 @@ static int shadow_copy2_open(vfs_handle_struct *handle, } ret = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode); - saved_errno = errno; + if (ret == -1) { + saved_errno = errno; + } TALLOC_FREE(smb_fname->base_name); smb_fname->base_name = tmp; - errno = saved_errno; + if (saved_errno != 0) { + errno = saved_errno; + } return ret; } @@ -1102,7 +1126,8 @@ static int shadow_copy2_unlink(vfs_handle_struct *handle, { time_t timestamp = 0; char *stripped = NULL; - int ret, saved_errno; + int saved_errno = 0; + int ret; struct smb_filename *conv; if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, @@ -1125,9 +1150,13 @@ static int shadow_copy2_unlink(vfs_handle_struct *handle, return -1; } ret = SMB_VFS_NEXT_UNLINK(handle, conv); - saved_errno = errno; + if (ret == -1) { + saved_errno = errno; + } TALLOC_FREE(conv); - errno = saved_errno; + if (saved_errno != 0) { + errno = saved_errno; + } return ret; } @@ -1136,7 +1165,8 @@ static int shadow_copy2_chmod(vfs_handle_struct *handle, const char *fname, { time_t timestamp = 0; char *stripped = NULL; - int ret, saved_errno; + int saved_errno = 0; + int ret; char *conv; if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, @@ -1152,9 +1182,13 @@ static int shadow_copy2_chmod(vfs_handle_struct *handle, const char *fname, return -1; } ret = SMB_VFS_NEXT_CHMOD(handle, conv, mode); - saved_errno = errno; + if (ret == -1) { + saved_errno = errno; + } TALLOC_FREE(conv); - errno = saved_errno; + if (saved_errno != 0) { + errno = saved_errno; + } return ret; } @@ -1163,7 +1197,8 @@ static int shadow_copy2_chown(vfs_handle_struct *handle, const char *fname, { time_t timestamp = 0; char *stripped = NULL; - int ret, saved_errno; + int saved_errno = 0; + int ret; char *conv; if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, @@ -1179,9 +1214,13 @@ static int shadow_copy2_chown(vfs_handle_struct *handle, const char *fname, return -1; } ret = SMB_VFS_NEXT_CHOWN(handle, conv, uid, gid); - saved_errno = errno; + if (ret == -1) { + saved_errno = errno; + } TALLOC_FREE(conv); - errno = saved_errno; + if (saved_errno != 0) { + errno = saved_errno; + } return ret; } @@ -1273,7 +1312,8 @@ static int shadow_copy2_ntimes(vfs_handle_struct *handle, { time_t timestamp = 0; char *stripped = NULL; - int ret, saved_errno; + int saved_errno = 0; + int ret; struct smb_filename *conv; if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, @@ -1296,9 +1336,13 @@ static int shadow_copy2_ntimes(vfs_handle_struct *handle, return -1; } ret = SMB_VFS_NEXT_NTIMES(handle, conv, ft); - saved_errno = errno; + if (ret == -1) { + saved_errno = errno; + } TALLOC_FREE(conv); - errno = saved_errno; + if (saved_errno != 0) { + errno = saved_errno; + } return ret; } @@ -1307,7 +1351,8 @@ static int shadow_copy2_readlink(vfs_handle_struct *handle, { time_t timestamp = 0; char *stripped = NULL; - int ret, saved_errno; + int saved_errno = 0; + int ret; char *conv; if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, @@ -1323,9 +1368,13 @@ static int shadow_copy2_readlink(vfs_handle_struct *handle, return -1; } ret = SMB_VFS_NEXT_READLINK(handle, conv, buf, bufsiz); - saved_errno = errno; + if (ret == -1) { + saved_errno = errno; + } TALLOC_FREE(conv); - errno = saved_errno; + if (saved_errno != 0) { + errno = saved_errno; + } return ret; } @@ -1334,7 +1383,8 @@ static int shadow_copy2_mknod(vfs_handle_struct *handle, { time_t timestamp = 0; char *stripped = NULL; - int ret, saved_errno; + int saved_errno = 0; + int ret; char *conv; if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, @@ -1350,9 +1400,13 @@ static int shadow_copy2_mknod(vfs_handle_struct *handle, return -1; } ret = SMB_VFS_NEXT_MKNOD(handle, conv, mode, dev); - saved_errno = errno; + if (ret == -1) { + saved_errno = errno; + } TALLOC_FREE(conv); - errno = saved_errno; + if (saved_errno != 0) { + errno = saved_errno; + } return ret; } @@ -1363,7 +1417,7 @@ static char *shadow_copy2_realpath(vfs_handle_struct *handle, char *stripped = NULL; char *tmp = NULL; char *result = NULL; - int saved_errno; + int saved_errno = 0; if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, ×tamp, &stripped)) { @@ -1381,10 +1435,14 @@ static char *shadow_copy2_realpath(vfs_handle_struct *handle, result = SMB_VFS_NEXT_REALPATH(handle, tmp); done: - saved_errno = errno; + if (result == NULL) { + saved_errno = errno; + } TALLOC_FREE(tmp); TALLOC_FREE(stripped); - errno = saved_errno; + if (saved_errno != 0) { + errno = saved_errno; + } return result; } @@ -1753,7 +1811,8 @@ static int shadow_copy2_mkdir(vfs_handle_struct *handle, { time_t timestamp = 0; char *stripped = NULL; - int ret, saved_errno; + int saved_errno = 0; + int ret; char *conv; if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, @@ -1769,9 +1828,13 @@ static int shadow_copy2_mkdir(vfs_handle_struct *handle, return -1; } ret = SMB_VFS_NEXT_MKDIR(handle, conv, mode); - saved_errno = errno; + if (ret == -1) { + saved_errno = errno; + } TALLOC_FREE(conv); - errno = saved_errno; + if (saved_errno != 0) { + errno = saved_errno; + } return ret; } @@ -1779,7 +1842,8 @@ static int shadow_copy2_rmdir(vfs_handle_struct *handle, const char *fname) { time_t timestamp = 0; char *stripped = NULL; - int ret, saved_errno; + int saved_errno = 0; + int ret; char *conv; if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, @@ -1795,9 +1859,13 @@ static int shadow_copy2_rmdir(vfs_handle_struct *handle, const char *fname) return -1; } ret = SMB_VFS_NEXT_RMDIR(handle, conv); - saved_errno = errno; + if (ret == -1) { + saved_errno = errno; + } TALLOC_FREE(conv); - errno = saved_errno; + if (saved_errno != 0) { + errno = saved_errno; + } return ret; } @@ -1806,7 +1874,8 @@ static int shadow_copy2_chflags(vfs_handle_struct *handle, const char *fname, { time_t timestamp = 0; char *stripped = NULL; - int ret, saved_errno; + int saved_errno = 0; + int ret; char *conv; if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, @@ -1822,9 +1891,13 @@ static int shadow_copy2_chflags(vfs_handle_struct *handle, const char *fname, return -1; } ret = SMB_VFS_NEXT_CHFLAGS(handle, conv, flags); - saved_errno = errno; + if (ret == -1) { + saved_errno = errno; + } TALLOC_FREE(conv); - errno = saved_errno; + if (saved_errno != 0) { + errno = saved_errno; + } return ret; } @@ -1835,7 +1908,7 @@ static ssize_t shadow_copy2_getxattr(vfs_handle_struct *handle, time_t timestamp = 0; char *stripped = NULL; ssize_t ret; - int saved_errno; + int saved_errno = 0; char *conv; if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, @@ -1852,9 +1925,13 @@ static ssize_t shadow_copy2_getxattr(vfs_handle_struct *handle, return -1; } ret = SMB_VFS_NEXT_GETXATTR(handle, conv, aname, value, size); - saved_errno = errno; + if (ret == -1) { + saved_errno = errno; + } TALLOC_FREE(conv); - errno = saved_errno; + if (saved_errno != 0) { + errno = saved_errno; + } return ret; } @@ -1865,7 +1942,7 @@ static ssize_t shadow_copy2_listxattr(struct vfs_handle_struct *handle, time_t timestamp = 0; char *stripped = NULL; ssize_t ret; - int saved_errno; + int saved_errno = 0; char *conv; if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, @@ -1881,9 +1958,13 @@ static ssize_t shadow_copy2_listxattr(struct vfs_handle_struct *handle, return -1; } ret = SMB_VFS_NEXT_LISTXATTR(handle, conv, list, size); - saved_errno = errno; + if (ret == -1) { + saved_errno = errno; + } TALLOC_FREE(conv); - errno = saved_errno; + if (saved_errno != 0) { + errno = saved_errno; + } return ret; } @@ -1892,7 +1973,8 @@ static int shadow_copy2_removexattr(vfs_handle_struct *handle, { time_t timestamp = 0; char *stripped = NULL; - int ret, saved_errno; + int saved_errno = 0; + int ret; char *conv; if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, @@ -1908,9 +1990,13 @@ static int shadow_copy2_removexattr(vfs_handle_struct *handle, return -1; } ret = SMB_VFS_NEXT_REMOVEXATTR(handle, conv, aname); - saved_errno = errno; + if (ret == -1) { + saved_errno = errno; + } TALLOC_FREE(conv); - errno = saved_errno; + if (saved_errno != 0) { + errno = saved_errno; + } return ret; } @@ -1922,7 +2008,7 @@ static int shadow_copy2_setxattr(struct vfs_handle_struct *handle, time_t timestamp = 0; char *stripped = NULL; ssize_t ret; - int saved_errno; + int saved_errno = 0; char *conv; if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, @@ -1939,9 +2025,13 @@ static int shadow_copy2_setxattr(struct vfs_handle_struct *handle, return -1; } ret = SMB_VFS_NEXT_SETXATTR(handle, conv, aname, value, size, flags); - saved_errno = errno; + if (ret == -1) { + saved_errno = errno; + } TALLOC_FREE(conv); - errno = saved_errno; + if (saved_errno != 0) { + errno = saved_errno; + } return ret; } @@ -1951,7 +2041,7 @@ static int shadow_copy2_chmod_acl(vfs_handle_struct *handle, time_t timestamp = 0; char *stripped = NULL; ssize_t ret; - int saved_errno; + int saved_errno = 0; char *conv; if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, @@ -1967,9 +2057,13 @@ static int shadow_copy2_chmod_acl(vfs_handle_struct *handle, return -1; } ret = SMB_VFS_NEXT_CHMOD_ACL(handle, conv, mode); - saved_errno = errno; + if (ret == -1) { + saved_errno = errno; + } TALLOC_FREE(conv); - errno = saved_errno; + if (saved_errno != 0) { + errno = saved_errno; + } return ret; } @@ -1982,7 +2076,7 @@ static int shadow_copy2_get_real_filename(struct vfs_handle_struct *handle, time_t timestamp = 0; char *stripped = NULL; ssize_t ret; - int saved_errno; + int saved_errno = 0; char *conv; DEBUG(10, ("shadow_copy2_get_real_filename called for path=[%s], " @@ -2009,9 +2103,13 @@ static int shadow_copy2_get_real_filename(struct vfs_handle_struct *handle, ret = SMB_VFS_NEXT_GET_REAL_FILENAME(handle, conv, name, mem_ctx, found_name); DEBUG(10, ("NEXT_REAL_FILE_NAME returned %d\n", (int)ret)); - saved_errno = errno; + if (ret == -1) { + saved_errno = errno; + } TALLOC_FREE(conv); - errno = saved_errno; + if (saved_errno != 0) { + errno = saved_errno; + } return ret; } @@ -2023,7 +2121,7 @@ static const char *shadow_copy2_connectpath(struct vfs_handle_struct *handle, char *tmp = NULL; char *result = NULL; char *parent_dir = NULL; - int saved_errno; + int saved_errno = 0; size_t rootpath_len = 0; struct shadow_copy2_config *config = NULL; @@ -2098,11 +2196,15 @@ static const char *shadow_copy2_connectpath(struct vfs_handle_struct *handle, DBG_DEBUG("connect path is [%s]\n", result); done: - saved_errno = errno; + if (result == NULL) { + saved_errno = errno; + } TALLOC_FREE(tmp); TALLOC_FREE(stripped); TALLOC_FREE(parent_dir); - errno = saved_errno; + if (saved_errno != 0) { + errno = saved_errno; + } return result; } @@ -2113,7 +2215,7 @@ static uint64_t shadow_copy2_disk_free(vfs_handle_struct *handle, time_t timestamp = 0; char *stripped = NULL; ssize_t ret; - int saved_errno; + int saved_errno = 0; char *conv; if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, path, @@ -2133,9 +2235,13 @@ static uint64_t shadow_copy2_disk_free(vfs_handle_struct *handle, ret = SMB_VFS_NEXT_DISK_FREE(handle, conv, bsize, dfree, dsize); - saved_errno = errno; + if (ret == -1) { + saved_errno = errno; + } TALLOC_FREE(conv); - errno = saved_errno; + if (saved_errno != 0) { + errno = saved_errno; + } return ret; } @@ -2147,7 +2253,7 @@ static int shadow_copy2_get_quota(vfs_handle_struct *handle, const char *path, time_t timestamp = 0; char *stripped = NULL; int ret; - int saved_errno; + int saved_errno = 0; char *conv; if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, path, ×tamp, @@ -2166,9 +2272,13 @@ static int shadow_copy2_get_quota(vfs_handle_struct *handle, const char *path, ret = SMB_VFS_NEXT_GET_QUOTA(handle, conv, qtype, id, dq); - saved_errno = errno; + if (ret == -1) { + saved_errno = errno; + } TALLOC_FREE(conv); - errno = saved_errno; + if (saved_errno != 0) { + errno = saved_errno; + } return ret; }