Re: Zenbleed

From: mike tancsa <mike_at_sentex.net>
Date: Thu, 27 Jul 2023 17:43:57 UTC
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
%