I am using gcc 5.1.0 on Windows.
When calling memset I am receiving a SEGFAULT, which does not occur when -flto flag (link time optimisation) is enabled.
/*#### function.h ####*/
void secure_bzero (void *s,size_t size);
/*##### function.c ####*/
/* Securely erase size bytes from s */
void WEAK __attribute__((noinline)) secure_bzero (void *s,size_t size) {
memset(s,0,size);
}
I noticed the segmentation fault, when I wanted to debug my application in CodeBlocks. I enabled the debugging symbols flag (-g) and got warned that Combining -flto with -g is "currently experimental and expected to produce wrong results."
I don't understand how the segmentation fault is produced here.
thanks to Eugene Sh. hint to post a complete example:
#include "function.h"
int main(){
unsigned char seed[32];
for (int i=0; i<32; i++){
seed[i] = i;
}
secure_bzero(seed,sizeof(seed));
return 1;
}
Related
I am trying to implement stack canaries manually and without the standard library. Therefore I have created a simple PoC with the help of this guide from the OSDev wiki. The article suggests that a simple implementation must provide the __stack_chk_guard variable and the __stack_chk_fail() handler.
However, when I compile using GCC and provide the -fstack-protector-all flag, the executable does not contain any stack canary check at all. What am I missing to get GCC to include the stack canary logic?
gcc -Wall -nostdlib -nodefaultlibs -fstack-protector-all -g -m64 -o poc main.c customlib.h
main.c
#include "customlib.h"
#define STACK_CHK_GUARD (0xDEADBEEFFFFFFFF & ~0xFF)
uintptr_t __stack_chk_guard = STACK_CHK_GUARD;
__attribute__((noreturn)) void __stack_chk_fail()
{
__exit(123);
while(1);
}
int main()
{
__attribute__((unused)) char buffer[16];
for (size_t index = 0; index < 32; index++)
{
buffer[index] = 'A';
}
return 0;
}
customlib.h
This code is mostly irrelevant and is just necessary so that the program can be compiled and linked correctly.
typedef unsigned long int size_t;
typedef unsigned long int uintptr_t;
size_t __syscall(size_t arg1, size_t arg2, size_t arg3, size_t arg4, size_t arg5, size_t arg6)
{
asm("int $0x80\n"
: "=a"(arg1)
: "a"(arg1), "b"(arg2), "c"(arg3), "d"(arg4), "S"(arg5), "D"(arg6));
return arg1;
}
void _exit(int exit_code)
{
__syscall(1, exit_code, 0, 0, 0, 0);
while(1);
}
extern int main();
void _start()
{
main();
_exit(0);
}
GCC version 10.2.0, Linux 5.10.36-2-MANJARO GNU/Linux
It looks like the Arch gcc package (which the Manjaro package is based on) is turning off -fstack-protector when building without the standard library (Done for Arch bug 64270).
This behavior is apparently also present in Gentoo.
I haven't tried this, but I believe you should be able to dump the GCC specs using gcc -dumpspecs into a file, keeping only the section *cc1_options, removing %{nostdlib|nodefaultlibs|ffreestanding:-fno-stack-protector} from it, and passing it to gcc with gcc -specs=your_spec_file.
Alternately, you can rebuild the gcc package with this patch removed.
If I call pthread_join continuously (without using other functions) it will cause a segmentation fault.
I can solve the problem by inserting a sleep(); , printf() or anything else between two calls of pthread_join.
OS & GCC Version:
gcc --version
gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Complie command:
gcc demo_thread.c -lpthread -o demo_thread.out
Source code (demo_thread.c):
#include <stdio.h>
#include <stdlib.h>
void *f1(void *);
int main() {
int k = 2;
pthread_t fa[k];
for(int i=0; i<k; i++) {
pthread_create(&fa[i], NULL, f1, NULL);
}
for(int i=0; i<k; i++) {
// printf("%ul\n", fa[i]); // uncomment this line, problem disapper.
pthread_join(fa[i]);
}
}
void *f1(void *arg) {
for(int i=0; i<4;i++) {
printf("%d\n",i );
}
return 0;
}
How did you even make that compile? I just now realized you did not use #include <pthread.h> and you used one argument instead of two for pthread_join.
If I leave out the include I get
error: unknown type name ‘pthread_t’
And if I do include it then I get
error: too few arguments to function ‘pthread_join’
Oh I see that if I include #include <stdlib.h> and leave out <pthread.h> then it will have a definition for pthread_t but nothing for pthread_join. There are still plenty of warnings though:
warning: implicit declaration of function ‘pthread_join’
You should always build programs with the -Wall -W -pedantic arguments to the compiler. And fix the warnings.
And to explain the crash: Since you don't pass NULL as the second argument to pthread_join it will be receiving a "random" value and then writing into it as if it was a pointer. Which it isn't. So it will either write a value into your allocated memory where it shouldn't, or it will get a segmentation fault.
And to explain how printf or sleep fixes the problem: Making those function calls must change the value of the RSI register (RSI is used for the second function argument) enough that it is either a valid pointer or NULL.
I have installed Clang in my machine (ubuntu) in order to find memory leaks in my C code. I wrote a sample code in order to check the working of it which is as follows:
/* File: hello.c for leak detection */
#include <stdio.h>
#include <stdlib.h>
void *x;
int main() {
x = malloc(2);
x = 0; // Memory leak
return 0;
}
I found some options in internet to compile like
$ scan-build clang --analyze hello.c
and
$ scan-build clang -fsanitize=address hello.c
But none of them are showing any signs of memory leak.
scan-build: Using '/usr/bin/clang' for static analysis scan-build:
Removing directory '/tmp/scan-build-2015-07-02-122717-16928-1' because
it contains no reports. scan-build: No bugs found.
Can anyone kindly tell how to correctly use Clang for Memory leak detection.
Interestingly, the clang static analyzer finds the memory leak if you declare void *x inside main:
int main() {
void *x = malloc(2);
x = 0; // Memory leak
return 0;
}
Analyzing this code by running:
scan-build clang -g hello.c
gives a warning like:
hello.c:9:3: warning: Potential leak of memory pointed to by 'x'
return 0;
^~~~~~~~
I am currently studying C implementations of Linux terminal commands in class but I can't seem to get the following example to run on my machine. I'm using the latest distro of Ubuntu. It will compile but with a warning. "assignment makes pointer from integer without a cast" it refers to the line with a=ctime(&n->ut_time); I found this code online. It is suppose to replicate the terminal command "Who" to display system users. I'm simply trying to study how it works but I cant seem to get it to run. Any help or explanations would be appreciated.
#include<stdio.h>
#include<sys/utsname.h>
#include<utmp.h>
int main(void)
{
struct utmp *n;
char *a;
int i;
setutent();
n=getutent();
while(n!=NULL)
{
if(n->ut_type==7)
{
printf("%-9s",n->ut_user);
printf("%-12s",n->ut_line);
a=ctime(&n->ut_time);
printf(" ");
for(i=4;i<16;i++)
{
printf("%c",a[i]);
}
printf(" (");
printf("%s",n->ut_host);
printf(")\n");
}
n=getutent();
}
}
Transferring comment to answer
The compiler is telling you you've not got #include <time.h> so ctime() is assumed to return an int and not a char *. All hell breaks loose (segmentation faults, etc) because you are not paying attention to the compiler warnings.
Remember, while you're learning C, the compiler knows a lot more about C than you do. Its warnings should be heeded. (When you know C reasonably well, you still pay attention to the compiler warnings - and make the code compile cleanly without warnings. I use gcc -Wall -Wextra -Werror and some extra options — usually -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition -Wold-style-declaration; sometimes -Wshadow, -pedantic; and occasionally a few others.)
My code is trying to find the entropy of a signal (stored in 'data' and 'interframe' - in the full code these would contain the signal, here I've just put in some random values). When I compile with 'gcc temp.c' it compiles and runs fine.
Output:
entropy: 40.174477
features: 0022FD06
features[0]: 40
entropy: 40
But when I compile with 'gcc -mstackrealign -msse -Os -ftree-vectorize temp.c' then it compiles, but fails to execute beyond line 48. It needs to have all four flags in order to fail - any three of them and it runs fine.
The code probably looks weird - I've chopped just the failing bits out of a much bigger program. I only have the foggiest idea of what the compiler flags do, someone else put them in (and there's usually more of them, but I worked out that these were the bad ones).
All help much appreciated!
#include <stdint.h>
#include <inttypes.h>
#include <stdio.h>
#include <math.h>
static void calc_entropy(volatile int16_t *features, const int16_t* data,
const int16_t* interframe, int frame_length);
int main()
{
int frame_length = 128;
int16_t data[128] = {1, 2, 3, 4};
int16_t interframe[128] = {1, 1, 1};
int16_t a = 0;
int16_t* features = &a;
calc_entropy(features, data, interframe, frame_length);
features += 1;
fprintf(stderr, "\nentropy: %d", a);
return 0;
}
static void calc_entropy(volatile int16_t *features, const int16_t* data,
const int16_t* interframe, int frame_length)
{
float histo[65536] = {0};
float* histo_zero = histo + 32768;
volatile float entropy = 0.0f;
int i;
for(i=0; i<frame_length; i++){
histo_zero[data[i]]++;
histo_zero[interframe[i]]++;
}
for(i=-32768; i < 32768; i++){
if(histo_zero[i])
entropy -= histo_zero[i]*logf(histo_zero[i]/(float)(frame_length*2));
}
fprintf(stderr, "\nentropy: %f", entropy);
fprintf(stderr, "\nfeatures: %p", features);
features[0] = entropy; //execution fails here
fprintf(stderr, "\nfeatures[0]: %d", features[0]);
}
Edit: I'm using gcc 4.5.2, with x86 architecture. Also, if I compile and run it on VirtualBox running ubuntu (gcc -lm -mstackrealign -msse -Os -ftree-vectorize temp.c) it executes correctly.
Edit2: I get
entropy: 40.174477
features: 00000000
and then a message from windows telling me that the program has stopped running.
Edit3: In the five months since I originally posted the question I've updated to gcc 4.7.0, and the code now runs fine. I went back to gcc 4.5.2, and it failed. Still don't know why!
ottavio#magritte:/tmp$ gcc x.c -o x -lm -mstackrealign -msse -Os -ftree-vectorize
ottavio#magritte:/tmp$ ./x
entropy: 40.174477
features: 0x7fff5fe151ce
features[0]: 40
entropy: 40
ottavio#magritte;/tmp$ gcc x.c -o x -lm
ottavio#magritte:/tmp$ ./x
entropy: 40.174477
features: 0x7fffd7eff73e
features[0]: 40
entropy: 40
ottavio#magritte:/tmp$
So, what's wrong with it? gcc 4.6.1 and x86_64 architecture.
It seems to be running here as well, and the only thing I see that might be funky is that you are taking a 16 bit value (features[0]) and converting a 32 bit float (entropy)
features[0] = entropy; //execution fails here
into that value, which of course will shave it off.
It shouldn't matter, but for the heck of it, see if it makes any difference if change your int16_t values to int32_t values.