* Re: [PATCH v3 0/5] Enable -Warray-bounds and -Wzero-length-bounds [not found] <20210827163015.3141722-1-keescook@chromium.org> @ 2021-08-30 18:44 ` Nathan Chancellor 2021-08-30 20:12 ` Kees Cook 2021-08-30 20:16 ` Kees Cook 0 siblings, 2 replies; 4+ messages in thread From: Nathan Chancellor @ 2021-08-30 18:44 UTC (permalink / raw) To: Kees Cook Cc: linux-kernel, Arnd Bergmann, Gustavo A. R. Silva, Rasmus Villemoes, Keith Packard, Dan Williams, Daniel Vetter, clang-built-linux, linux-hardening, llvm On Fri, Aug 27, 2021 at 09:30:10AM -0700, Kees Cook wrote: > v3: > - fix typo in treewide conversion (u8 should have been __u8) > - improve changelog for DECLARE_FLEX_ARRAY patch > - add acks/reviews > v2: https://lore.kernel.org/lkml/20210826050458.1540622-1-keescook@chromium.org/ > v1: https://lore.kernel.org/lkml/20210818081118.1667663-1-keescook@chromium.org/ > > Hi, > > In support of the improved buffer overflow detection for memcpy(), > this enables -Warray-bounds and -Wzero-length-bounds globally. Mostly > it involves some struct member tricks with the new DECLARE_FLEX_ARRAY() > macro. Everything else is just replacing stacked 0-element arrays > with actual unions in two related treewide patches. There is one set of > special cases that were fixed separately[1] and are needed as well. > > I'm expecting to carry this series with the memcpy() series in my > "overflow" tree. Reviews appreciated! :) Hi Kees, I ran this series through my local build tests and uncovered two warnings in the same file that appear to be unhandled as of next-20210830. This is from ARCH=powerpc pseries_defconfig with clang-14, I did not try earlier versions of clang. arch/powerpc/kernel/signal_32.c:780:2: error: array index 3 is past the end of the array (which contains 1 element) [-Werror,-Warray-bounds] unsafe_put_sigset_t(&frame->uc.uc_sigmask, oldset, failed); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ arch/powerpc/kernel/signal_32.c:85:29: note: expanded from macro 'unsafe_put_sigset_t' #define unsafe_put_sigset_t unsafe_put_compat_sigset ^ ./include/linux/compat.h:455:19: note: expanded from macro 'unsafe_put_compat_sigset' unsafe_put_user(__s->sig[3] >> 32, &__c->sig[7], label); \ ^ ~ ./arch/powerpc/include/asm/uaccess.h:426:42: note: expanded from macro 'unsafe_put_user' __put_user_size_goto((__typeof__(*(p)))(x), (p), sizeof(*(p)), e) ^ ./arch/powerpc/include/asm/uaccess.h:114:30: note: expanded from macro '__put_user_size_goto' case 1: __put_user_asm_goto(x, __pus_addr, label, "stb"); break; \ ^ ./arch/powerpc/include/asm/uaccess.h:89:10: note: expanded from macro '__put_user_asm_goto' : "r" (x), "m"UPD_CONSTR (*addr) \ ^ ./include/linux/compiler_types.h:254:42: note: expanded from macro 'asm_volatile_goto' #define asm_volatile_goto(x...) asm goto(x) ^ ./arch/powerpc/include/uapi/asm/signal.h:18:2: note: array 'sig' declared here unsigned long sig[_NSIG_WORDS]; ^ arch/powerpc/kernel/signal_32.c:1044:3: error: array index 2 is past the end of the array (which contains 1 element) [-Werror,-Warray-bounds] unsafe_put_sigset_t(&old_ctx->uc_sigmask, ¤t->blocked, failed); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ arch/powerpc/kernel/signal_32.c:85:29: note: expanded from macro 'unsafe_put_sigset_t' #define unsafe_put_sigset_t unsafe_put_compat_sigset ^ ./include/linux/compat.h:459:19: note: expanded from macro 'unsafe_put_compat_sigset' unsafe_put_user(__s->sig[2] >> 32, &__c->sig[5], label); \ ^ ~ ./arch/powerpc/include/asm/uaccess.h:426:42: note: expanded from macro 'unsafe_put_user' __put_user_size_goto((__typeof__(*(p)))(x), (p), sizeof(*(p)), e) ^ ./arch/powerpc/include/asm/uaccess.h:116:30: note: expanded from macro '__put_user_size_goto' case 4: __put_user_asm_goto(x, __pus_addr, label, "stw"); break; \ ^ ./arch/powerpc/include/asm/uaccess.h:89:10: note: expanded from macro '__put_user_asm_goto' : "r" (x), "m"UPD_CONSTR (*addr) \ ^ ./include/linux/compiler_types.h:254:42: note: expanded from macro 'asm_volatile_goto' #define asm_volatile_goto(x...) asm goto(x) ^ ./arch/powerpc/include/uapi/asm/signal.h:18:2: note: array 'sig' declared here unsigned long sig[_NSIG_WORDS]; ^ Cheers, Nathan ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v3 0/5] Enable -Warray-bounds and -Wzero-length-bounds 2021-08-30 18:44 ` [PATCH v3 0/5] Enable -Warray-bounds and -Wzero-length-bounds Nathan Chancellor @ 2021-08-30 20:12 ` Kees Cook 2021-08-30 20:16 ` Kees Cook 1 sibling, 0 replies; 4+ messages in thread From: Kees Cook @ 2021-08-30 20:12 UTC (permalink / raw) To: Nathan Chancellor Cc: linux-kernel, Arnd Bergmann, Gustavo A. R. Silva, Rasmus Villemoes, Keith Packard, Dan Williams, Daniel Vetter, clang-built-linux, linux-hardening, llvm On Mon, Aug 30, 2021 at 11:44:54AM -0700, Nathan Chancellor wrote: > On Fri, Aug 27, 2021 at 09:30:10AM -0700, Kees Cook wrote: > > v3: > > - fix typo in treewide conversion (u8 should have been __u8) > > - improve changelog for DECLARE_FLEX_ARRAY patch > > - add acks/reviews > > v2: https://lore.kernel.org/lkml/20210826050458.1540622-1-keescook@chromium.org/ > > v1: https://lore.kernel.org/lkml/20210818081118.1667663-1-keescook@chromium.org/ > > > > Hi, > > > > In support of the improved buffer overflow detection for memcpy(), > > this enables -Warray-bounds and -Wzero-length-bounds globally. Mostly > > it involves some struct member tricks with the new DECLARE_FLEX_ARRAY() > > macro. Everything else is just replacing stacked 0-element arrays > > with actual unions in two related treewide patches. There is one set of > > special cases that were fixed separately[1] and are needed as well. > > > > I'm expecting to carry this series with the memcpy() series in my > > "overflow" tree. Reviews appreciated! :) > > Hi Kees, > > I ran this series through my local build tests and uncovered two > warnings in the same file that appear to be unhandled as of > next-20210830. This is from ARCH=powerpc pseries_defconfig with > clang-14, I did not try earlier versions of clang. Thanks for double-checking! > > arch/powerpc/kernel/signal_32.c:780:2: error: array index 3 is past the end of the array (which contains 1 element) [-Werror,-Warray-bounds] > unsafe_put_sigset_t(&frame->uc.uc_sigmask, oldset, failed); > ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > [...] > arch/powerpc/kernel/signal_32.c:1044:3: error: array index 2 is past the end of the array (which contains 1 element) [-Werror,-Warray-bounds] > unsafe_put_sigset_t(&old_ctx->uc_sigmask, ¤t->blocked, failed); > ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This smells like some kind of casting issue. uc_sigmask has only a single unsigned long element but unsafe_put_compat_sigset() seems to be doing stuff with [3], etc. Is it expecting u8? I will keep looking... -- Kees Cook ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v3 0/5] Enable -Warray-bounds and -Wzero-length-bounds 2021-08-30 18:44 ` [PATCH v3 0/5] Enable -Warray-bounds and -Wzero-length-bounds Nathan Chancellor 2021-08-30 20:12 ` Kees Cook @ 2021-08-30 20:16 ` Kees Cook 2021-08-30 22:34 ` Nathan Chancellor 1 sibling, 1 reply; 4+ messages in thread From: Kees Cook @ 2021-08-30 20:16 UTC (permalink / raw) To: Nathan Chancellor Cc: linux-kernel, Arnd Bergmann, Gustavo A. R. Silva, Rasmus Villemoes, Keith Packard, Dan Williams, Daniel Vetter, clang-built-linux, linux-hardening, llvm On Mon, Aug 30, 2021 at 11:44:54AM -0700, Nathan Chancellor wrote: > arch/powerpc/kernel/signal_32.c:780:2: error: array index 3 is past the end of the array (which contains 1 element) [-Werror,-Warray-bounds] > unsafe_put_sigset_t(&frame->uc.uc_sigmask, oldset, failed); > ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Or is this a Clang DCE failure? #define unsafe_put_compat_sigset(compat, set, label) do { \ compat_sigset_t __user *__c = compat; \ const sigset_t *__s = set; \ \ switch (_NSIG_WORDS) { \ case 4: \ unsafe_put_user(__s->sig[3] >> 32, &__c->sig[7], label); \ unsafe_put_user(__s->sig[3], &__c->sig[6], label); \ fallthrough; \ case 3: \ unsafe_put_user(__s->sig[2] >> 32, &__c->sig[5], label); \ unsafe_put_user(__s->sig[2], &__c->sig[4], label); \ fallthrough; \ case 2: \ unsafe_put_user(__s->sig[1] >> 32, &__c->sig[3], label); \ unsafe_put_user(__s->sig[1], &__c->sig[2], label); \ fallthrough; \ case 1: \ unsafe_put_user(__s->sig[0] >> 32, &__c->sig[1], label); \ unsafe_put_user(__s->sig[0], &__c->sig[0], label); \ } \ } while (0) if "set" has only 1 element, then _NSIG_WORDS must be 1. The warnings are coming from cases 4 and 3. (But why not 2, which would also access beyond the end?) -- Kees Cook ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v3 0/5] Enable -Warray-bounds and -Wzero-length-bounds 2021-08-30 20:16 ` Kees Cook @ 2021-08-30 22:34 ` Nathan Chancellor 0 siblings, 0 replies; 4+ messages in thread From: Nathan Chancellor @ 2021-08-30 22:34 UTC (permalink / raw) To: Kees Cook Cc: linux-kernel, Arnd Bergmann, Gustavo A. R. Silva, Rasmus Villemoes, Keith Packard, Dan Williams, Daniel Vetter, clang-built-linux, linux-hardening, llvm On Mon, Aug 30, 2021 at 01:16:41PM -0700, Kees Cook wrote: > On Mon, Aug 30, 2021 at 11:44:54AM -0700, Nathan Chancellor wrote: > > arch/powerpc/kernel/signal_32.c:780:2: error: array index 3 is past the end of the array (which contains 1 element) [-Werror,-Warray-bounds] > > unsafe_put_sigset_t(&frame->uc.uc_sigmask, oldset, failed); > > ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > > Or is this a Clang DCE failure? > > #define unsafe_put_compat_sigset(compat, set, label) do { \ > compat_sigset_t __user *__c = compat; \ > const sigset_t *__s = set; \ > \ > switch (_NSIG_WORDS) { \ > case 4: \ > unsafe_put_user(__s->sig[3] >> 32, &__c->sig[7], label); \ > unsafe_put_user(__s->sig[3], &__c->sig[6], label); \ > fallthrough; \ > case 3: \ > unsafe_put_user(__s->sig[2] >> 32, &__c->sig[5], label); \ > unsafe_put_user(__s->sig[2], &__c->sig[4], label); \ > fallthrough; \ > case 2: \ > unsafe_put_user(__s->sig[1] >> 32, &__c->sig[3], label); \ > unsafe_put_user(__s->sig[1], &__c->sig[2], label); \ > fallthrough; \ > case 1: \ > unsafe_put_user(__s->sig[0] >> 32, &__c->sig[1], label); \ > unsafe_put_user(__s->sig[0], &__c->sig[0], label); \ > } \ > } while (0) > > if "set" has only 1 element, then _NSIG_WORDS must be 1. The warnings > are coming from cases 4 and 3. (But why not 2, which would also access > beyond the end?) I trimmed the warnings down otherwise it would have been 400 lines long :) it did warn for the 2 case. Clang does not like the use of asm goto in unsafe_put_user on powerpc it seems: $ cat warray-bounds.c #define NSIG_WORDS 1 typedef struct { unsigned long sig[NSIG_WORDS]; } sigset_t; int handle_rt_signal32_bad(sigset_t *); int handle_rt_signal32_bad(sigset_t *oldset) { switch (NSIG_WORDS) { case 4: __asm__ goto("" : : "r"(oldset->sig[3] >> 32) : : failed); __asm__ goto("" : : "r"(oldset->sig[3]) : : failed); __attribute__((fallthrough)); case 3: __asm__ goto("" : : "r"(oldset->sig[2] >> 32) : : failed); __asm__ goto("" : : "r"(oldset->sig[2]) : : failed); __attribute__((fallthrough)); case 2: __asm__ goto("" : : "r"(oldset->sig[1] >> 32) : : failed); __asm__ goto("" : : "r"(oldset->sig[1]) : : failed); __attribute__((fallthrough)); case 1: __asm__ goto("" : : "r"(oldset->sig[0] >> 32) : : failed); __asm__ goto("" : : "r"(oldset->sig[0]) : : failed); } return 0; failed: return 1; } void normal_array_access(unsigned long); int handle_rt_signal32_good(sigset_t *); int handle_rt_signal32_good(sigset_t *oldset) { switch (NSIG_WORDS) { case 4: normal_array_access(oldset->sig[3] >> 32); normal_array_access(oldset->sig[3]); __attribute__((fallthrough)); case 3: normal_array_access(oldset->sig[2] >> 32); normal_array_access(oldset->sig[2]); __attribute__((fallthrough)); case 2: normal_array_access(oldset->sig[1] >> 32); normal_array_access(oldset->sig[1]); __attribute__((fallthrough)); case 1: normal_array_access(oldset->sig[0] >> 32); normal_array_access(oldset->sig[0]); } return 0; } $ clang -fsyntax-only -Weverything warray-bounds.c warray-bounds.c:12:27: warning: array index 3 is past the end of the array (which contains 1 element) [-Warray-bounds] __asm__ goto("" : : "r"(oldset->sig[3] >> 32) : : failed); ^ ~ warray-bounds.c:4:2: note: array 'sig' declared here unsigned long sig[NSIG_WORDS]; ^ warray-bounds.c:16:27: warning: array index 2 is past the end of the array (which contains 1 element) [-Warray-bounds] __asm__ goto("" : : "r"(oldset->sig[2] >> 32) : : failed); ^ ~ warray-bounds.c:4:2: note: array 'sig' declared here unsigned long sig[NSIG_WORDS]; ^ warray-bounds.c:20:27: warning: array index 1 is past the end of the array (which contains 1 element) [-Warray-bounds] __asm__ goto("" : : "r"(oldset->sig[1] >> 32) : : failed); ^ ~ warray-bounds.c:4:2: note: array 'sig' declared here unsigned long sig[NSIG_WORDS]; ^ 3 warnings generated. $ gcc -fsyntax-only -Wall -Wextra -Wpedantic warray-bounds.c godbolt link: https://godbolt.org/z/8xYojs1WY I've reported this on LLVM's bug tracker to see what the clang developers can do with you on CC: https://bugs.llvm.org/show_bug.cgi?id=51682 Cheers, Nathan ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2021-08-30 22:34 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20210827163015.3141722-1-keescook@chromium.org>
2021-08-30 18:44 ` [PATCH v3 0/5] Enable -Warray-bounds and -Wzero-length-bounds Nathan Chancellor
2021-08-30 20:12 ` Kees Cook
2021-08-30 20:16 ` Kees Cook
2021-08-30 22:34 ` Nathan Chancellor
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox