From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752258AbdK3SKp (ORCPT ); Thu, 30 Nov 2017 13:10:45 -0500 Received: from mail-vk0-f66.google.com ([209.85.213.66]:46450 "EHLO mail-vk0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750885AbdK3SKn (ORCPT ); Thu, 30 Nov 2017 13:10:43 -0500 X-Google-Smtp-Source: AGs4zMYVbgJPwbcJLhn6g9LsSP2gOSrKci/TBNzIYqZVvdy8cWqBOZoAOyNvqJciJ5LayUSkPIyKoWQ+Nfm1DTjo7fU= MIME-Version: 1.0 In-Reply-To: References: <20171126063117.oytmra3tqoj5546u@wfg-t540p.sh.intel.com> <20171127210301.GA55812@localhost.corp.microsoft.com> <20171128124534.3jvuala525wvn64r@wfg-t540p.sh.intel.com> <20171129175430.GA58181@big-sky.attlocal.net> From: Kees Cook Date: Thu, 30 Nov 2017 10:10:41 -0800 X-Google-Sender-Auth: 71FUpolAD5bI4swDIbB47ytR58o Message-ID: Subject: Re: [pcpu] BUG: KASAN: use-after-scope in pcpu_setup_first_chunk+0x1e3b/0x29e2 To: Dmitry Vyukov Cc: Dennis Zhou , Fengguang Wu , Ard Biesheuvel , Linux-MM , Tejun Heo , Christoph Lameter , Linus Torvalds , Josef Bacik , LKML , LKP , Andrey Ryabinin , Mark Rutland Content-Type: text/plain; charset="UTF-8" Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Thu, Nov 30, 2017 at 1:59 AM, Dmitry Vyukov wrote: > On Wed, Nov 29, 2017 at 6:54 PM, Dennis Zhou wrote: >> Hi everyone, >> >> I spent a bit of time learning more about this problem as Fengguang was >> able to determine the root commit f7dd2507893cc3. I reproduced the bug >> in userspace to make life a bit easier and below the assignment occurs >> before the unpoison. This is fine if we're sequentially proceeding, but >> as in the case in percpu, it's calling the function in a for loop >> causing the assignment to happen after it has been poisoned in the prior >> iteration. >> >> [0.00%]: >> _1 = (long unsigned int) i_4; >> _2 = _1 * 16; >> _3 = p_8 + _2; >> list_14 = _3; >> __u = {}; >> ASAN_MARK (UNPOISON, &__u, 8); >> __u.__val = list_14; >> >> [0.00%]: >> _24 = __u.__val; >> ASAN_MARK (POISON, &__u, 8); >> list_14->prev = list_14; >> i_13 = i_4 + 1; >> >> [0.00%]: >> # i_4 = PHI >> if (i_4 <= 9) >> goto ; [0.00%] >> else >> goto ; [0.00%] >> >> I don't know how to go about fixing this though. The reproducing code is >> below and was compiled with gcc-7 and the structleak_plugin. > > > Are we sure that structleak plugin is not at fault? If yes, then we > need to report this to https://gcc.gnu.org/bugzilla/ with instructions > on how to build/use the plugin. I thought from earlier in this thread that the bug just changed locations depending on the plugin. Does the issue still exist with the plugin disabled? -Kees > > >> I hope this helps. >> >> Thanks, >> Dennis >> >> ---- >> #include >> #include >> >> #define barrier() >> >> #define WRITE_ONCE(x, val) \ >> ({ \ >> union { typeof(x) __val; char __c[1]; } __u = \ >> { .__val = (typeof(x)) (val) }; \ >> __write_once_size(&(x), __u.__c, sizeof(x)); \ >> __u.__val; \ >> }) >> >> typedef uint8_t __u8; >> typedef uint16_t __u16; >> typedef uint32_t __u32; >> typedef uint64_t __u64; >> >> static inline __attribute__((always_inline)) void __write_once_size(volatile void *p, void *res, int size) >> { >> switch (size) { >> case 1: *(volatile __u8 *)p = *(__u8 *)res; break; >> case 2: *(volatile __u16 *)p = *(__u16 *)res; break; >> case 4: *(volatile __u32 *)p = *(__u32 *)res; break; >> case 8: *(volatile __u64 *)p = *(__u64 *)res; break; >> default: >> barrier(); >> __builtin_memcpy((void *)p, (const void *)res, size); >> barrier(); >> } >> } >> >> struct list_head { >> struct list_head *next, *prev; >> }; >> >> static inline __attribute__((always_inline)) void INIT_LIST_HEAD(struct list_head *list) >> { >> WRITE_ONCE(list->next, list); >> list->prev = list; >> } >> >> int main(int argc, char *argv[]) >> { >> struct list_head *p = malloc(10 * sizeof(struct list_head)); >> int i; >> >> for (i = 0; i < 10; i++) { >> INIT_LIST_HEAD(&p[i]); >> } >> >> free(p); >> >> return 0; >> } -- Kees Cook Pixel Security From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-ua0-f200.google.com (mail-ua0-f200.google.com [209.85.217.200]) by kanga.kvack.org (Postfix) with ESMTP id B23426B0273 for ; Thu, 30 Nov 2017 13:10:44 -0500 (EST) Received: by mail-ua0-f200.google.com with SMTP id e26so4444793uaf.7 for ; Thu, 30 Nov 2017 10:10:44 -0800 (PST) Received: from mail-sor-f65.google.com (mail-sor-f65.google.com. [209.85.220.65]) by mx.google.com with SMTPS id p77sor352041vkd.8.2017.11.30.10.10.43 for (Google Transport Security); Thu, 30 Nov 2017 10:10:43 -0800 (PST) MIME-Version: 1.0 In-Reply-To: References: <20171126063117.oytmra3tqoj5546u@wfg-t540p.sh.intel.com> <20171127210301.GA55812@localhost.corp.microsoft.com> <20171128124534.3jvuala525wvn64r@wfg-t540p.sh.intel.com> <20171129175430.GA58181@big-sky.attlocal.net> From: Kees Cook Date: Thu, 30 Nov 2017 10:10:41 -0800 Message-ID: Subject: Re: [pcpu] BUG: KASAN: use-after-scope in pcpu_setup_first_chunk+0x1e3b/0x29e2 Content-Type: text/plain; charset="UTF-8" Sender: owner-linux-mm@kvack.org List-ID: To: Dmitry Vyukov Cc: Dennis Zhou , Fengguang Wu , Ard Biesheuvel , Linux-MM , Tejun Heo , Christoph Lameter , Linus Torvalds , Josef Bacik , LKML , LKP , Andrey Ryabinin , Mark Rutland On Thu, Nov 30, 2017 at 1:59 AM, Dmitry Vyukov wrote: > On Wed, Nov 29, 2017 at 6:54 PM, Dennis Zhou wrote: >> Hi everyone, >> >> I spent a bit of time learning more about this problem as Fengguang was >> able to determine the root commit f7dd2507893cc3. I reproduced the bug >> in userspace to make life a bit easier and below the assignment occurs >> before the unpoison. This is fine if we're sequentially proceeding, but >> as in the case in percpu, it's calling the function in a for loop >> causing the assignment to happen after it has been poisoned in the prior >> iteration. >> >> [0.00%]: >> _1 = (long unsigned int) i_4; >> _2 = _1 * 16; >> _3 = p_8 + _2; >> list_14 = _3; >> __u = {}; >> ASAN_MARK (UNPOISON, &__u, 8); >> __u.__val = list_14; >> >> [0.00%]: >> _24 = __u.__val; >> ASAN_MARK (POISON, &__u, 8); >> list_14->prev = list_14; >> i_13 = i_4 + 1; >> >> [0.00%]: >> # i_4 = PHI >> if (i_4 <= 9) >> goto ; [0.00%] >> else >> goto ; [0.00%] >> >> I don't know how to go about fixing this though. The reproducing code is >> below and was compiled with gcc-7 and the structleak_plugin. > > > Are we sure that structleak plugin is not at fault? If yes, then we > need to report this to https://gcc.gnu.org/bugzilla/ with instructions > on how to build/use the plugin. I thought from earlier in this thread that the bug just changed locations depending on the plugin. Does the issue still exist with the plugin disabled? -Kees > > >> I hope this helps. >> >> Thanks, >> Dennis >> >> ---- >> #include >> #include >> >> #define barrier() >> >> #define WRITE_ONCE(x, val) \ >> ({ \ >> union { typeof(x) __val; char __c[1]; } __u = \ >> { .__val = (typeof(x)) (val) }; \ >> __write_once_size(&(x), __u.__c, sizeof(x)); \ >> __u.__val; \ >> }) >> >> typedef uint8_t __u8; >> typedef uint16_t __u16; >> typedef uint32_t __u32; >> typedef uint64_t __u64; >> >> static inline __attribute__((always_inline)) void __write_once_size(volatile void *p, void *res, int size) >> { >> switch (size) { >> case 1: *(volatile __u8 *)p = *(__u8 *)res; break; >> case 2: *(volatile __u16 *)p = *(__u16 *)res; break; >> case 4: *(volatile __u32 *)p = *(__u32 *)res; break; >> case 8: *(volatile __u64 *)p = *(__u64 *)res; break; >> default: >> barrier(); >> __builtin_memcpy((void *)p, (const void *)res, size); >> barrier(); >> } >> } >> >> struct list_head { >> struct list_head *next, *prev; >> }; >> >> static inline __attribute__((always_inline)) void INIT_LIST_HEAD(struct list_head *list) >> { >> WRITE_ONCE(list->next, list); >> list->prev = list; >> } >> >> int main(int argc, char *argv[]) >> { >> struct list_head *p = malloc(10 * sizeof(struct list_head)); >> int i; >> >> for (i = 0; i < 10; i++) { >> INIT_LIST_HEAD(&p[i]); >> } >> >> free(p); >> >> return 0; >> } -- Kees Cook Pixel Security -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to majordomo@kvack.org. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: email@kvack.org From mboxrd@z Thu Jan 1 00:00:00 1970 Content-Type: multipart/mixed; boundary="===============0222962623193485221==" MIME-Version: 1.0 From: Kees Cook To: lkp@lists.01.org Subject: Re: [pcpu] BUG: KASAN: use-after-scope in pcpu_setup_first_chunk+0x1e3b/0x29e2 Date: Thu, 30 Nov 2017 10:10:41 -0800 Message-ID: In-Reply-To: List-Id: --===============0222962623193485221== Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable On Thu, Nov 30, 2017 at 1:59 AM, Dmitry Vyukov wrote: > On Wed, Nov 29, 2017 at 6:54 PM, Dennis Zhou wr= ote: >> Hi everyone, >> >> I spent a bit of time learning more about this problem as Fengguang was >> able to determine the root commit f7dd2507893cc3. I reproduced the bug >> in userspace to make life a bit easier and below the assignment occurs >> before the unpoison. This is fine if we're sequentially proceeding, but >> as in the case in percpu, it's calling the function in a for loop >> causing the assignment to happen after it has been poisoned in the prior >> iteration. >> >> [0.00%]: >> _1 =3D (long unsigned int) i_4; >> _2 =3D _1 * 16; >> _3 =3D p_8 + _2; >> list_14 =3D _3; >> __u =3D {}; >> ASAN_MARK (UNPOISON, &__u, 8); >> __u.__val =3D list_14; >> >> [0.00%]: >> _24 =3D __u.__val; >> ASAN_MARK (POISON, &__u, 8); >> list_14->prev =3D list_14; >> i_13 =3D i_4 + 1; >> >> [0.00%]: >> # i_4 =3D PHI >> if (i_4 <=3D 9) >> goto ; [0.00%] >> else >> goto ; [0.00%] >> >> I don't know how to go about fixing this though. The reproducing code is >> below and was compiled with gcc-7 and the structleak_plugin. > > > Are we sure that structleak plugin is not at fault? If yes, then we > need to report this to https://gcc.gnu.org/bugzilla/ with instructions > on how to build/use the plugin. I thought from earlier in this thread that the bug just changed locations depending on the plugin. Does the issue still exist with the plugin disabled? -Kees > > >> I hope this helps. >> >> Thanks, >> Dennis >> >> ---- >> #include >> #include >> >> #define barrier() >> >> #define WRITE_ONCE(x, val) \ >> ({ \ >> union { typeof(x) __val; char __c[1]; } __u =3D \ >> { .__val =3D (typeof(x)) (val) }; \ >> __write_once_size(&(x), __u.__c, sizeof(x)); \ >> __u.__val; \ >> }) >> >> typedef uint8_t __u8; >> typedef uint16_t __u16; >> typedef uint32_t __u32; >> typedef uint64_t __u64; >> >> static inline __attribute__((always_inline)) void __write_once_size(vola= tile void *p, void *res, int size) >> { >> switch (size) { >> case 1: *(volatile __u8 *)p =3D *(__u8 *)res; break; >> case 2: *(volatile __u16 *)p =3D *(__u16 *)res; break; >> case 4: *(volatile __u32 *)p =3D *(__u32 *)res; break; >> case 8: *(volatile __u64 *)p =3D *(__u64 *)res; break; >> default: >> barrier(); >> __builtin_memcpy((void *)p, (const void *)res, size); >> barrier(); >> } >> } >> >> struct list_head { >> struct list_head *next, *prev; >> }; >> >> static inline __attribute__((always_inline)) void INIT_LIST_HEAD(struct = list_head *list) >> { >> WRITE_ONCE(list->next, list); >> list->prev =3D list; >> } >> >> int main(int argc, char *argv[]) >> { >> struct list_head *p =3D malloc(10 * sizeof(struct list_head)); >> int i; >> >> for (i =3D 0; i < 10; i++) { >> INIT_LIST_HEAD(&p[i]); >> } >> >> free(p); >> >> return 0; >> } -- = Kees Cook Pixel Security --===============0222962623193485221==--