I am trying to implement my own heap memory allocator, by allocating memory via sbrk() system call, and managing the return buffer. void *sbrk(intptr_t increment); return value:
From man sbrk:
On success, sbrk() returns the previous program break. (If the
break was increased, then this value is a pointer to the start of the
newly allocated memory). On error, (void *) -1 is re‐
turned, and errno is set to ENOMEM
#include <gnu/libc-version.h>
#include <stdio.h>
#include <unistd.h>
#include <assert.h>
/*
puts (gnu_get_libc_version ());
*/
#define VP_ALIGNMENT (4096)
#define ALIGN(size,alignment) ( ((size) + (alignment-1)) & ~((alignment-1)) )
static void *extend_heap(int nbytes)
{
void *sp = sbrk(ALIGN(nbytes, VP_ALIGNMENT));
if (sp == (void*)-1) {
perror("fails to retrieve program brk");
}
return sp;
}
struct S{
char m[4096];
};
int main() {
/* get current brk */
void *cbrk = sbrk(0);
printf("current prog brk: %p\n",cbrk);
/*allocate 4096 bytes and get pointer to the start of the buffer*/
struct S *buf = (struct S*)extend_heap(4000);
printf("prog brk after allocation: %p\n",sbrk(0));
int c=4096;
do {
buf->m[4096-c] = 'a';
} while(--c);
c=4096;
do {
assert(buf->m[4096-c] == 'a');
} while(--c);
return 0;
}
Compile with gcc & gcc flags: cc main.c -pedantic -Wconversion -Werror
the program run as expected, but i dont understand why linux allocates a huge amount of memory, 2200hex bytes when i have asked only for 4096 ?
adding one of the gcc flags -ansi or -std=c89 produce compilation errors below:
In function ‘extend_heap’: main.c:15:20: error: initialization of
‘void *’ from ‘int’ makes pointer from integer without a cast
[-Werror=int-conversion] 15 | void *sp = sbrk(ALIGN(nbytes,
VP_ALIGNMENT));
| ^~~~ main.c: In function ‘main’: main.c:31:22: error: initialization of ‘void *’ from ‘int’ makes
pointer from integer without a cast [-Werror=int-conversion] 31 |
void *cbrk = sbrk(0);
| ^~~~
sbrk returns void*.
why I am getting the error above?
My glibc version = 2.31, gcc version 9.3.0
Thanks.
Related
I have this header and function defined in it called long ptr = PT_REGS_PARM2(ctx); so first running command like following assuming my system config will take care of it finding this header file in /usr/include/bpf/tracing.h.
but couldn't find the header file
root#this:/home/ubuntu/Desktop/ebpf/Linux-exFilter-main/pkg/probe/bpf# clang -O2 -Wall -g -target bpf -I /usr/include/ -c kprobe_send.c -o kprobe_send.o
I also tried with - I and changing <bpf/tracing.h> to "bpf/tracing.h" not worked either.
I started this inclusion of -I after I was compiling this program and it causing error on compile, I could not understand the error but this is following
clang: error: clang frontend command failed with exit code 70 (use -v to see invocation)
#this:/home/ubuntu/Desktop/ebpf/Linux-exFilter-main/pkg/probe/bpf# clang -O2 -Wall -g-target bpf -c kprobe_send.c -o kprobe_send.o
clang: error: unknown argument: '-g-target'
clang: error: no such file or directory: 'bpf'
root#this:/home/ubuntu/Desktop/ebpf/Linux-exFilter-main/pkg/probe/bpf# clang -O2 -Wall -g -target bpf -c kprobe_send.c -o kprobe_send.o
kprobe_send.c:31:2: warning: implicit declaration of function 'srand' is invalid in C99 [-Wimplicit-function-declaration]
srand(time(NULL)); /* Seed the random number generator. */
^
kprobe_send.c:37:11: warning: implicit declaration of function 'rand' is invalid in C99 [-Wimplicit-function-declaration]
int c = randrange(MAX-i);
^
kprobe_send.c:11:22: note: expanded from macro 'randrange'
#define randrange(N) rand() / (RAND_MAX/(N) + 1)
^
kprobe_send.c:51:22: warning: implicit declaration of function 'PT_REGS_PARM2' is invalid in C99 [-Wimplicit-function-declaration]
char *ptr = PT_REGS_PARM2(ctx);
^
kprobe_send.c:51:15: warning: incompatible integer to pointer conversion initializing 'char *' with an expression of type 'int' [-Wint-conversion]
char *ptr = PT_REGS_PARM2(ctx);
^ ~~~~~~~~~~~~~~~~~~
kprobe_send.c:61:22: warning: incompatible integer to pointer conversion passing 'int' to parameter of type 'void *' [-Wint-conversion]
bpf_map_update_elem(fd,&key,&data,BPF_ANY);
^~
Error at line 37: Unsupport signed division for DAG: 0x18aff58: i64 = sdiv 0x18af668, 0x18afe20, kprobe_send.c:37:11Please convert to unsigned div/mod.
fatal error: error in backend: Cannot select: 0x18aff58: i64 = sdiv 0x18af668, 0x18afe20, kprobe_send.c:37:11
0x18af668: i64 = sra 0x189bcd8, Constant:i64<32>, kprobe_send.c:37:11
0x189bcd8: i64 = shl 0x189c4f8, Constant:i64<32>, kprobe_send.c:37:11
0x189c4f8: i64,ch,glue = CopyFromReg 0x189c018, Register:i64 $r0, 0x189c018:1, kprobe_send.c:37:11
0x189c150: i64 = Register $r0
0x189c018: ch,glue = callseq_end 0x189bc08, TargetConstant:i64<0>, TargetConstant:i64<0>, 0x189bc08:1, kprobe_send.c:37:11
0x189bfb0: i64 = TargetConstant<0>
0x189bfb0: i64 = TargetConstant<0>
What the above error even means, I thought it was complaining I did not include any headers so I started including tracing.h to cater to PT_REGS_PARM2(ctx)
How can I get rid of this error?
On this line it says unsupported sign division:
Error at line 37: Unsupport signed division for DAG: 0x18aff58: i64 = sdiv 0x18af668, 0x18afe20, kprobe_send.c:37:11Please convert to unsigned div/mod.
Is this line 37 referring to assembly or my source file? In line 37 of source file I am doing
int c = randrange(MAX-i);
Why is the above simple line is not allowed in ebpf program? This is my line 37 and rest of the bpf program
#include <linux/ptrace.h>
#include <linux/version.h>
#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
#include <string.h>
#include <sys/sendfile.h>
#include <time.h>
//#include <bpf/tracing.h>
#include <stdlib.h>
#define RAND_MAX 0x7fff
#define PERF_SAMPLE_RAW 1U << 0
#define randrange(N) rand() / (RAND_MAX/(N) + 1)
#define MAX 100000000 /* Values will be in the range (1 .. MAX) */
struct {
__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
__uint(key_size, sizeof(int));
__uint(value_size, sizeof(int));
__uint(max_entries, 100);
} my_map SEC(".maps");
SEC("kprobe/__x64_sys_recvfrom")
int bpf_prog1(struct pt_regs *ctx,int fd, const char *buf, size_t count)
{
static int vektor[100000000];
int candidates[MAX];
int i;
long key;
srand(time(NULL)); /* Seed the random number generator. */
for (i=0; i<MAX; i++)
candidates[i] = i;
for (i = 0; i < MAX-1; i++) {
int c = randrange(MAX-i);
int t = candidates[i];
candidates[i] = candidates[i+c];
candidates[i+c] = t;
}
for (i=0; i<10; i++)
vektor[i] = candidates[i] + 1;
struct S {
int pid;
char cookie[90];
char *ptr;
} data={1,""};
char *ptr = PT_REGS_PARM2(ctx);
//data.pid =count;// bpf_get_current_pid_tgid();
//if(buf==NULL)
//memcpy(data.cookie,buf,20);
data.ptr=ptr;
// data.cookie[0]=buf[0];
//bpf_get_current_comm(&data.cookie, sizeof(data.cookie));
key=vektor[i];
bpf_map_update_elem(fd,&key,&data,BPF_ANY);
//bpf_perf_event_output(ctx, &my_map, 1, &data, sizeof(data));
return 0;
}
char _license[] SEC("license") = "GPL";
int _version SEC("version") = 99;
is there any info source where it says what's allowed or what's not allowed because seems to me its just picking arbitrarily what's allowed and what's not looking into ebpf
My kernel: 5.14.1
My clang: 12
libbpf installed but I'd love to find a command that tells its version and or just where it's installed.
On some link I found it says maybe/or definitely (couldn't tell the difference) be a problem of symlink on Ubuntu exact source .. what this even means does it mean I installed libbpf or something and unbuntu messed up with my symlink that help find libbpf headers? How can I understand what this link says? https://github.com/iovisor/kubectl-trace/issues/76#issuecomment-513587108
compiler: https://releases.linaro.org/components/toolchain/binaries/7.5-2019.12/arm-eabi/gcc-linaro-7.5.0-2019.12-x86_64_arm-eabi.tar.xz
test.c:
struct Foo{
char a[32]; // 32 and above will produce warning, but 31 and below will not
char d[9]; // 9 and above will produce warning, but 8 and below will not
};
int main()
{
struct Foo foo = {0};
(void)(foo);
return 0;
}
compile command and warning:
$ arm-eabi-gcc -Wstack-protector -fstack-protector-all -fstack-check -o test test.c
test.c: In function ‘main’:
test.c:6:5: warning: stack protector not protecting local variables: variable length buffer [-Wstack-protector]
int main()
^~~~
The struct in my source is something like Foo in the source shown above, it can not be changed, therefore what can i do with the main function to solve the warning?
Any help would be much appreciated!
I have been trying to intercept calls to malloc and free, following our textbook (CSAPP book).
I have followed their exact code, and nearly the same code that I found online and I keep getting a segmentation fault. I heard our professor saying something about printf that mallocs and frees memory so I think that this happens because I am intercepting a malloc and since I am using a printf function inside the intercepting function, it will call itself recursively.
However I can't seem to find a solution to solving this problem? Our professor demonstrated that intercepting worked ( he didn't show us the code) and prints our information every time a malloc occurs, so I do know that it's possible.
Can anyone suggest a working method??
Here is the code that I used and get nothing:
mymalloc.c
#ifdef RUNTIME
// Run-time interposition of malloc and free based on // dynamic linker's (ld-linux.so) LD_PRELOAD mechanism #define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h> #include <dlfcn.h>
void *malloc(size_t size) {
static void *(*mallocp)(size_t size) = NULL; char *error;
void *ptr;
// get address of libc malloc
if (!mallocp) {
mallocp = dlsym(RTLD_NEXT, "malloc"); if ((error = dlerror()) != NULL) {
fputs(error, stderr);
exit(EXIT_FAILURE);
}
}
ptr = mallocp(size);
printf("malloc(%d) = %p\n", (int)size, ptr); return ptr;
}
#endif
test.c
#include <stdio.h>
#include <stdlib.h>
int main(){
printf("main\n");
int* a = malloc(sizeof(int)*5);
a[0] = 1;
printf("end\n");
}
The result i'm getting:
$ gcc -o test test.c
$ gcc -DRUNTIME -shared -fPIC mymalloc.c -o mymalloc.so
$ LD_PRELOAD=./mymalloc.so ./test
Segmentation Fault
This is the code that I tried and got segmentation fault (from https://gist.github.com/iamben/4124829):
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
void* malloc(size_t size)
{
static void* (*rmalloc)(size_t) = NULL;
void* p = NULL;
// resolve next malloc
if(!rmalloc) rmalloc = dlsym(RTLD_NEXT, "malloc");
// do actual malloc
p = rmalloc(size);
// show statistic
fprintf(stderr, "[MEM | malloc] Allocated: %lu bytes\n", size);
return p;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define STR_LEN 128
int main(int argc, const char *argv[])
{
char *c;
char *str1 = "Hello ";
char *str2 = "World";
//allocate an empty string
c = malloc(STR_LEN * sizeof(char));
c[0] = 0x0;
//and concatenate str{1,2}
strcat(c, str1);
strcat(c, str2);
printf("New str: %s\n", c);
return 0;
}
The makefile from the git repo didn't work so I manually compiled the files and got:
$ gcc -shared -fPIC libint.c -o libint.so
$ gcc -o str str.c
$ LD_PRELOAD=./libint.so ./str
Segmentation fault
I have been doing this for hours and I still get the same incorrect result, despite the fact that I copied textbook code. I would really appreciate any help!!
One way to deal with this is to turn off the printf when your return is called recursively:
static char ACallIsInProgress = 0;
if (!ACallIsInProgress)
{
ACallIsInProgress = 1;
printf("malloc(%d) = %p\n", (int)size, ptr);
ACallIsInProgress = 0;
}
return ptr;
With this, if printf calls malloc, your routine will merely call the actual malloc (via mallocp) and return without causing another printf. You will miss printing information about a call to malloc that the printf does, but that is generally tolerable when interposing is being used to study the general program, not the C library.
If you need to support multithreading, some additional work might be needed.
The printf implementation might allocate a buffer only once, the first time it is used. In that case, you can initialize a flag that turns off the printf similar to the above, call printf once in the main routine (maybe be sure it includes a nice formatting task that causes printf to allocate a buffer, not a plain string), and then set the flag to turn on the printf call and leave it set for the rest of the program.
Another option is for your malloc routine not to use printf at all but to cache data in a buffer to be written later by some other routine or to write raw data to a file using write, with that data interpreted and formatted by a separate program later. Or the raw data could be written by a pipe to a program that formats and prints it and that is not using your interposed malloc.
I am working out of the 2nd edition of Jon Erickson's "Hacking: The Art of Exploitation" using a VM (virutalbox) to run the LiveCD it came with (Ubuntu 7.04). In section 0x272 "Using the Heap", the author explains the malloc() and free() functions using an example on pages 77-79.
The code for the heap_example.c is as follows:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc,char *argv[]){
char *char_ptr;
int *int_ptr;
int mem_size;
if(argc < 2)
mem_size = 50;
else
mem_size = atoi(argv[1]);
printf("\t[+]allocating %d bytes of memory on the heap for char_ptr\n",mem_size);
char_ptr = (char *)malloc(mem_size);
if(char_ptr == NULL){ //Error checking,in case malloc() fails
fprintf(stderr,"Error:could not allocate heap memory.\n");
exit(-1);
}
strcpy(char_ptr,"This is memory is located on the heap.");
printf("char_ptr(%p)-->'%s'\n",char_ptr,char_ptr);
printf("\t[+]allocating 12 bytes of memory on the heap for int_ptr\n");
int_ptr = (int *)malloc(12);
if(int_ptr == NULL){
fprintf(stderr,"Error:could not allocate heap memory.\n");
exit(-1);
}
*int_ptr = 31337;
printf("int_ptr (%p)--> %d\n",int_ptr,*int_ptr);
printf("\t[-]freeing char_ptr's heap memory...\n");
free(char_ptr);
printf("\t[+]allocating another 15 bytes for char_ptr\n");
char_ptr = (char*)malloc(15);
if(char_ptr == NULL){
fprintf(stderr,"Error:could not allocate heap memory.\n");
exit(-1);
}
strcpy(char_ptr,"new memory");
printf("char_ptr (%p)-->'%s'\n",char_ptr,char_ptr);
printf("\t[-]freeing int_ptr's heap memory...\n");
free(int_ptr);
printf("\t[-]freeing char_ptr's heap memory...\n");
free(char_ptr);
}
However, when I type the following instructions stated in the book into my terminal window:
reader#hacking:~/booksrc $ gcc -o heap_example heap_example.c
It spits out the following error message regarding syntax errors in my stdlib.h
In file included from heap_example.c:2:
/usr/include/stdlib.h:469: error: syntax error before "int32_t"
/usr/include/stdlib.h:471: error: syntax error before '*' token
/usr/include/stdlib.h:475: error: syntax error before '*' token
/usr/include/stdlib.h:476: error: syntax error before '}' token
/usr/include/stdlib.h:479: error: syntax error before "int32_t"
Here is where the error seems to take place in my stdlib.h (lines 467 - 479)
struct random_data
{
int32_t *fptr; /* Front pointer. */
int32_t *rptr; /* Rear pointer. */
int32_t *state; /* Array of state values. */
int rand_type; /* Type of random number generator. */
int rand_deg; /* Degree of random number generator. */
int rand_sep; /* Distance between front and rear. */
int32_t *end_ptr; /* Pointer behind state table. */
};
extern int random_r (struct random_data *__restrict __buf,
int32_t *__restrict __result) __THROW __nonnull ((1, 2));
Then when I try to run it:
reader#hacking:~/booksrc $ ./heap_example
I get this:
bash: ./heap_example: No such file or directory
I believe that heap_example.c is the first file in the book that includes the stdlib.h (all the prior examples used only stdio.h, so I had no issues).
Will changing the stdlib.h file fix this problem? If so, how might I go about correcting these errors? I figured I should fix this issue ASAP as the rest of the code examples in this book will probably start to include stdlib.h
Thanks!
I was wondering how to solve a Core dumped issue on my C code.
When I compile it with: g++ -g MatSim.cpp -o MatSim -lstdc++ -O3, I get three warnings, this is one (The other two are similar and are only differentiated by the string variable name):
MatSim.cpp: In function ‘int main()’:
MatSim.cpp:200037:27: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’, declared with attribute warn_unused_result [-Wunused-result]
fscanf(TM,"%255s",string2);
The principal aspects of my code and the related part that the compiler reports:
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <iostream>
#include <fstream>
#include <string.h>
using namespace std;
int to_int(char string[256])
{
if( strcmp(string,"0") == 0 )
{
return 0;
}
...
else if( strcmp(string,"50000") == 0 )
{
return 50000;
}
return -1;
}
int main()
{
int a,b,div,value,k,i,j,tm,ler;
char string[256];
char string1[256];
char string2[256];
FILE *TM;
TM = fopen("TM","r");
if( (TM = fopen("TM","r")) == NULL)
{
printf("Can't open %s\n","TM");
exit(1);
}
fscanf(TM,"%255s",string2);
tm = to_int(string2);
fclose(TM);
...
}
I have tried the reported suggestion in here and I tried to understand what was posted in here. But, I don't see its application on my code.
Finally, when I run the exe file, it returns:
Segmentation fault (core dumped)`.
In your code, you're fopen()ing the file twice. Just get rid of the
TM = fopen("TM","r");
before the if statement.
That said, you should check the value of fscanf() to ensure success. Otherwise, you'll end up reading an uninitialized array string2, which is not null-terminated which in turn invokes undefined behaviour.
Please be aware, almost all string related functions expect a null-terminated char array. If your array is not null terminated, there will be UB. Also, it is a good practice to initialize your automatic local variables to avoid possible UB in later part of code.
You are opening the file twice.
Alll you need is this:
FILE *TM = fopen("TM","r");
if (TM == NULL) { /* file was not opened */ }