summaryrefslogtreecommitdiff
path: root/source3/modules/vfs_default.c
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2012-04-06 14:20:12 -0700
committerJeremy Allison <jra@samba.org>2012-04-06 14:20:12 -0700
commita92c532573b293f5c0ed4a386c866bc9a3dbeef3 (patch)
tree75fbd0f91fc7cd5b577244eaad44bacdd6f12c2e /source3/modules/vfs_default.c
parent189b3d9b24bf553ff7096397c389f20ba99e0dfa (diff)
downloadsamba-a92c532573b293f5c0ed4a386c866bc9a3dbeef3.tar.gz
samba-a92c532573b293f5c0ed4a386c866bc9a3dbeef3.tar.bz2
samba-a92c532573b293f5c0ed4a386c866bc9a3dbeef3.zip
Bug found by Herb. blkcnt_t st_ex_blksize is defined as a signed value. When it is
on a 32-bit system and defined as a long, then inside vfswrap_get_alloc_size() we cast to a uint64_t. This sign-extends when converting to unsigned, so if the high bit of st_ex_blksize is set we return insane values to clients.
Diffstat (limited to 'source3/modules/vfs_default.c')
-rw-r--r--source3/modules/vfs_default.c13
1 files changed, 13 insertions, 0 deletions
diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c
index cf2bdb05c5..915eae67d3 100644
--- a/source3/modules/vfs_default.c
+++ b/source3/modules/vfs_default.c
@@ -1119,7 +1119,20 @@ static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
}
#if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
+ /* The type of st_blocksize is blkcnt_t which *MUST* be
+ signed (according to POSIX) and can be less than 64-bits.
+ Ensure when we're converting to 64 bits wide we don't
+ sign extend. */
+#if defined(SIZEOF_BLKCNT_T_8)
result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
+#elif defined(SIZEOF_BLKCNT_T_4)
+ {
+ uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
+ result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
+ }
+#else
+#error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
+#endif
#else
result = get_file_size_stat(sbuf);
#endif