# git rev-parse -q --verify 94bd8a05cd4de344a9a57e52ef7d99550251984f^{commit} 94bd8a05cd4de344a9a57e52ef7d99550251984f already have revision, skipping fetch # git checkout -q -f -B kisskb 94bd8a05cd4de344a9a57e52ef7d99550251984f # git clean -qxdf # < git log -1 # commit 94bd8a05cd4de344a9a57e52ef7d99550251984f # Author: Linus Torvalds # Date: Sun Jan 6 11:15:04 2019 -0800 # # Fix 'acccess_ok()' on alpha and SH # # Commit 594cc251fdd0 ("make 'user_access_begin()' do 'access_ok()'") # broke both alpha and SH booting in qemu, as noticed by Guenter Roeck. # # It turns out that the bug wasn't actually in that commit itself (which # would have been surprising: it was mostly a no-op), but in how the # addition of access_ok() to the strncpy_from_user() and strnlen_user() # functions now triggered the case where those functions would test the # access of the very last byte of the user address space. # # The string functions actually did that user range test before too, but # they did it manually by just comparing against user_addr_max(). But # with user_access_begin() doing the check (using "access_ok()"), it now # exposed problems in the architecture implementations of that function. # # For example, on alpha, the access_ok() helper macro looked like this: # # #define __access_ok(addr, size) \ # ((get_fs().seg & (addr | size | (addr+size))) == 0) # # and what it basically tests is of any of the high bits get set (the # USER_DS masking value is 0xfffffc0000000000). # # And that's completely wrong for the "addr+size" check. Because it's # off-by-one for the case where we check to the very end of the user # address space, which is exactly what the strn*_user() functions do. # # Why? Because "addr+size" will be exactly the size of the address space, # so trying to access the last byte of the user address space will fail # the __access_ok() check, even though it shouldn't. As a result, the # user string accessor functions failed consistently - because they # literally don't know how long the string is going to be, and the max # access is going to be that last byte of the user address space. # # Side note: that alpha macro is buggy for another reason too - it re-uses # the arguments twice. # # And SH has another version of almost the exact same bug: # # #define __addr_ok(addr) \ # ((unsigned long __force)(addr) < current_thread_info()->addr_limit.seg) # # so far so good: yes, a user address must be below the limit. But then: # # #define __access_ok(addr, size) \ # (__addr_ok((addr) + (size))) # # is wrong with the exact same off-by-one case: the case when "addr+size" # is exactly _equal_ to the limit is actually perfectly fine (think "one # byte access at the last address of the user address space") # # The SH version is actually seriously buggy in another way: it doesn't # actually check for overflow, even though it did copy the _comment_ that # talks about overflow. # # So it turns out that both SH and alpha actually have completely buggy # implementations of access_ok(), but they happened to work in practice # (although the SH overflow one is a serious serious security bug, not # that anybody likely cares about SH security). # # This fixes the problems by using a similar macro on both alpha and SH. # It isn't trying to be clever, the end address is based on this logic: # # unsigned long __ao_end = __ao_a + __ao_b - !!__ao_b; # # which basically says "add start and length, and then subtract one unless # the length was zero". We can't subtract one for a zero length, or we'd # just hit an underflow instead. # # For a lot of access_ok() users the length is a constant, so this isn't # actually as expensive as it initially looks. # # Reported-and-tested-by: Guenter Roeck # Cc: Matt Turner # Cc: Yoshinori Sato # Signed-off-by: Linus Torvalds # < /opt/cross/kisskb/gcc-4.6.3-nolibc/powerpc-linux/bin/powerpc-linux-gcc --version # < /opt/cross/kisskb/gcc-4.6.3-nolibc/powerpc-linux/bin/powerpc-linux-ld --version # < git log --format=%s --max-count=1 94bd8a05cd4de344a9a57e52ef7d99550251984f # < make -s -j 10 ARCH=powerpc O=/kisskb/build/linus-rand_powerpc-randconfig_powerpc CROSS_COMPILE=/opt/cross/kisskb/gcc-4.6.3-nolibc/powerpc-linux/bin/powerpc-linux- randconfig KCONFIG_SEED=0x35F83EC0 # Added to kconfig CONFIG_STANDALONE=y # Added to kconfig CONFIG_BUILD_DOCSRC=n # Added to kconfig CONFIG_MODULE_SIG=n # Added to kconfig CONFIG_CPU_BIG_ENDIAN=y # Added to kconfig CONFIG_PPC64=y # Added to kconfig CONFIG_PPC_DISABLE_WERROR=y # Added to kconfig CONFIG_SECTION_MISMATCH_WARN_ONLY=y # Added to kconfig CONFIG_PREVENT_FIRMWARE_BUILD=y # Added to kconfig CONFIG_CC_STACKPROTECTOR_STRONG=n # Added to kconfig CONFIG_GCC_PLUGINS=n # Added to kconfig CONFIG_LD_HEAD_STUB_CATCH=y # Added to kconfig # yes \n | make -s -j 10 ARCH=powerpc O=/kisskb/build/linus-rand_powerpc-randconfig_powerpc CROSS_COMPILE=/opt/cross/kisskb/gcc-4.6.3-nolibc/powerpc-linux/bin/powerpc-linux- oldconfig yes: standard output: Broken pipe # make -s -j 10 ARCH=powerpc O=/kisskb/build/linus-rand_powerpc-randconfig_powerpc CROSS_COMPILE=/opt/cross/kisskb/gcc-4.6.3-nolibc/powerpc-linux/bin/powerpc-linux- /kisskb/src/kernel/printk/printk.c: In function 'devkmsg_sysctl_set_loglvl': /kisskb/src/kernel/printk/printk.c:186:16: warning: 'old' may be used uninitialized in this function [-Wuninitialized] /kisskb/src/arch/powerpc/kernel/eeh.c:1752:12: warning: 'proc_eeh_show' defined but not used [-Wunused-function] /kisskb/src/drivers/base/regmap/regmap.c: In function 'regmap_raw_read': /kisskb/src/drivers/base/regmap/regmap.c:2594:6: warning: 'ret' may be used uninitialized in this function [-Wuninitialized] /kisskb/src/drivers/base/regmap/regmap.c: In function '_regmap_raw_write': /kisskb/src/drivers/base/regmap/regmap.c:1855:6: warning: 'ret' may be used uninitialized in this function [-Wuninitialized] /kisskb/src/net/bridge/br_netlink.c: In function 'br_afspec.isra.31': /kisskb/src/net/bridge/br_netlink.c:652:7: warning: 'err' may be used uninitialized in this function [-Wuninitialized] /kisskb/src/fs/btrfs/ref-verify.c: In function 'btrfs_build_ref_tree': /kisskb/src/fs/btrfs/ref-verify.c:592:7: warning: 'ret' may be used uninitialized in this function [-Wuninitialized] /kisskb/src/fs/btrfs/ref-verify.c:514:35: note: 'ret' was declared here /kisskb/src/fs/btrfs/ref-verify.c:552:6: warning: 'ret' may be used uninitialized in this function [-Wuninitialized] /kisskb/src/fs/btrfs/ref-verify.c:450:12: note: 'ret' was declared here /kisskb/src/lib/test_firmware.c: In function 'trigger_batched_requests_async_store': /kisskb/src/lib/test_firmware.c:781:31: warning: 'rc' may be used uninitialized in this function [-Wuninitialized] /kisskb/src/fs/f2fs/file.c: In function 'f2fs_precache_extents': /kisskb/src/fs/f2fs/file.c:2937:6: warning: 'err' may be used uninitialized in this function [-Wuninitialized] /kisskb/src/fs/f2fs/node.c: In function '__set_nat_cache_dirty': /kisskb/src/include/linux/list.h:93:12: warning: 'head' may be used uninitialized in this function [-Wuninitialized] /kisskb/src/fs/f2fs/node.c:237:24: note: 'head' was declared here /kisskb/src/drivers/i2c/i2c-core-base.c: In function 'i2c_generic_scl_recovery': /kisskb/src/drivers/i2c/i2c-core-base.c:235:5: warning: 'ret' may be used uninitialized in this function [-Wuninitialized] /kisskb/src/fs/udf/unicode.c: In function 'udf_name_conv_char': /kisskb/src/fs/udf/unicode.c:132:8: warning: 'c' may be used uninitialized in this function [-Wuninitialized] /kisskb/src/drivers/iio/temperature/mlx90632.c: In function 'mlx90632_read_raw': /kisskb/src/drivers/iio/temperature/mlx90632.c:349:37: warning: 'object_old_raw' may be used uninitialized in this function [-Wuninitialized] /kisskb/src/drivers/iio/temperature/mlx90632.c:430:56: note: 'object_old_raw' was declared here /kisskb/src/drivers/iio/temperature/mlx90632.c:349:37: warning: 'object_new_raw' may be used uninitialized in this function [-Wuninitialized] /kisskb/src/drivers/iio/temperature/mlx90632.c:430:40: note: 'object_new_raw' was declared here /kisskb/src/drivers/net/ethernet/neterion/vxge/vxge-main.c: In function 'vxge_tx_msix_handle': /kisskb/src/drivers/net/ethernet/neterion/vxge/vxge-main.c:2240:1: warning: the frame size of 1040 bytes is larger than 1024 bytes [-Wframe-larger-than=] /kisskb/src/drivers/net/ethernet/neterion/vxge/vxge-main.c: In function 'vxge_poll_inta': /kisskb/src/drivers/net/ethernet/neterion/vxge/vxge-main.c:1869:1: warning: the frame size of 1040 bytes is larger than 1024 bytes [-Wframe-larger-than=] /kisskb/src/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c: In function '__mlx5_create_flow_table': /kisskb/src/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c:835:5: warning: 'err' may be used uninitialized in this function [-Wuninitialized] /kisskb/src/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c:812:6: note: 'err' was declared here /kisskb/src/drivers/net/ethernet/mellanox/mlx5/core/events.c: In function 'port_module': /kisskb/src/drivers/net/ethernet/mellanox/mlx5/core/events.c:238:3: warning: 'error_str' may be used uninitialized in this function [-Wuninitialized] /opt/cross/kisskb/gcc-4.6.3-nolibc/powerpc-linux/bin/powerpc-linux-ld: drivers/misc/lkdtm/lkdtm.o: .opd is not a regular array of opd entries Completed OK # rm -rf /kisskb/build/linus-rand_powerpc-randconfig_powerpc # Build took: 0:03:53.996451