mirror of
https://github.com/samba-team/samba.git
synced 2025-01-11 05:18:09 +03:00
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.
This commit is contained in:
parent
189b3d9b24
commit
a92c532573
@ -2936,6 +2936,32 @@ fi
|
||||
|
||||
AC_CHECK_TYPES([blksize_t, blkcnt_t], [], [], [[#include <sys/stat.h>]])
|
||||
|
||||
AC_CACHE_CHECK([for 32 bit blkcnt_t],samba_cv_SIZEOF_BLKCNT_T_4,[
|
||||
AC_TRY_RUN([
|
||||
#if defined(HAVE_UNISTD_H)
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
main() { exit((sizeof(blkcnt_t) == 4) ? 0 : 1); }],
|
||||
samba_cv_SIZEOF_BLKCNT_T_4=yes,samba_cv_SIZEOF_BLKCNT_T_4=no,samba_cv_SIZEOF_BLKCNT_T_4=cross)])
|
||||
if test x"$samba_cv_SIZEOF_BLKCNT_T_4" = x"yes"; then
|
||||
AC_DEFINE(SIZEOF_BLKCNT_T_4,1,[The size of the 'blkcnt_t' type])
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([for 64 bit blkcnt_t],samba_cv_SIZEOF_BLKCNT_T_8,[
|
||||
AC_TRY_RUN([
|
||||
#if defined(HAVE_UNISTD_H)
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
main() { exit((sizeof(blkcnt_t) == 8) ? 0 : 1); }],
|
||||
samba_cv_SIZEOF_BLKCNT_T_8=yes,samba_cv_SIZEOF_BLKCNT_T_8=no,samba_cv_SIZEOF_BLKCNT_T_8=cross)])
|
||||
if test x"$samba_cv_SIZEOF_BLKCNT_T_8" = x"yes"; then
|
||||
AC_DEFINE(SIZEOF_BLKCNT_T_8,1,[The size of the 'blkcnt_t' type])
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([for st_blksize in struct stat],samba_cv_HAVE_STAT_ST_BLKSIZE,[
|
||||
AC_TRY_COMPILE([#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
@ -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
|
||||
|
@ -174,6 +174,20 @@ main() {
|
||||
conf.CHECK_STRUCTURE_MEMBER('struct stat', 'st_flags', define='HAVE_STAT_ST_FLAGS',
|
||||
headers='sys/types.h sys/stat.h unistd.h')
|
||||
|
||||
if "HAVE_BLKCNT_T" in conf.env:
|
||||
conf.CHECK_CODE('''
|
||||
return sizeof(blkcnt_t) == 4 ? 0 : 1''',
|
||||
'SIZEOF_BLKCNT_T_4', execute=True,
|
||||
headers='sys/types.h sys/stat.h unistd.h',
|
||||
msg="Checking whether blkcnt_t is 32 bit")
|
||||
|
||||
if "HAVE_BLKCNT_T" in conf.env:
|
||||
conf.CHECK_CODE('''
|
||||
return sizeof(blkcnt_t) == 8 ? 0 : 1''',
|
||||
'SIZEOF_BLKCNT_T_8', execute=True,
|
||||
headers='sys/types.h sys/stat.h unistd.h',
|
||||
msg="Checking whether blkcnt_t is 64 bit")
|
||||
|
||||
# Check for POSIX capability support
|
||||
conf.CHECK_FUNCS_IN('cap_get_proc', 'cap', headers='sys/capability.h')
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user