unix socket error 14: EFAULT (bad address) - c

I have a very simple question, but I have not managed to find any answers to it all weekend. I am using the sendto() function and it is returning error code 14: EFAULT. The man pages describe it as:
"An invalid user space address was specified for an argument."
I was convinced that this was talking about the IP address I was specifying, but now I suspect it may be the memory address of the message buffer that it is referring to - I can't find any clarification on this anywhere, can anyone clear this up?

EFAULT It happen if the memory address of some argument passed to sendto (or more generally to any system call) is invalid. Think of it as a sort of SIGSEGV in kernel land regarding your syscall. For instance, if you pass a null or invalid buffer pointer (for reading, writing, sending, recieving...), you get that
See errno(3), sendto(2) etc... man pages.
EFAULT is not related to IP addresses at all.

Minimal runnable example with getcpu
Just to make things more concrete, we can have a look at the getcpu system call, which is very simple to understand, and shows the same EFAULT behaviour.
From man getcpu we see that the signature is:
int getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *tcache);
and the memory pointed to by the cpu will contain the ID of the current CPU the process is running on after the syscall, the only possible error being:
ERRORS
EFAULT Arguments point outside the calling process's address space.
So we can test it out with:
main.c
#define _GNU_SOURCE
#include <assert.h>
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/syscall.h>
int main(void) {
int err, ret;
unsigned cpu;
/* Correct operation. */
assert(syscall(SYS_getcpu, &cpu, NULL, NULL) == 0);
printf("%u\n", cpu);
/* Bad trash address == 1. */
ret = syscall(SYS_getcpu, 1, NULL, NULL);
err = errno;
assert(ret == -1);
printf("%d\n", err);
perror("getcpu");
return EXIT_SUCCESS;
}
compile and run:
gcc -ggdb3 -O0 -std=c99 -Wall -Wextra -pedantic -o main.out main.c
./main.out
Sample output:
cpu 3
errno 14
getcpu: Bad address
so we see that the bad call with a trash address of 1 returned 14, which is EFAULT as seen from kernel code: https://stackoverflow.com/a/53958705/895245
Remember that the syscall itself returns -14, and then the syscall C wrapper detects that it is an error due to being negative, returns -1, and sets errno to the actual precise error code.
And since the syscall is so simple, we can confirm this from the kernel 5.4 implementation as well at kernel/sys.c:
SYSCALL_DEFINE3(getcpu, unsigned __user *, cpup, unsigned __user *, nodep,
struct getcpu_cache __user *, unused)
{
int err = 0;
int cpu = raw_smp_processor_id();
if (cpup)
err |= put_user(cpu, cpup);
if (nodep)
err |= put_user(cpu_to_node(cpu), nodep);
return err ? -EFAULT : 0;
}
so clearly we see that -EFAULT is returned if there is a problem with put_user.
It is worth mentioning that my glibc does have a getcpu wrapper as well in sched.h, but that implementation segfaults in case of bad addresses, which is a bit confusing: How do I include Linux header files like linux/getcpu.h? But it is not what the actual syscall does to the process, just whatever glibc is doing with that address.
Tested on Ubuntu 20.04, Linux 5.4.

EFAULT is a macro defined in a file "include/uapi/asm-generic/errno-base.h"
#define EFAULT 14 /* Bad address */

Related

getpgid not implemented with valgrind

Considering this example :
#include <stdio.h>
#include <unistd.h>
int main()
{
int pgid;
if ((pgid = getpgid(0)) == -1)
perror("getpgid");
else
printf("pgid : %d\n", pgid);
}
When I'm running this program without valgrind, everything is going right, and the pgid is printed.
Whenever I'm using valgrind, perror will print getpgid: Function not implemented.
Is it normal that getpgid is not available under valgrind ?
Is there any alternative to get the pgid of a specific pid (excluding
getpgrp) ?
I'm using macOS Sierra 10.12.6 and valgrind-3.15.0.
It seem that valgrind could have some trouble to perform some syscall.
In the valgrind trace, I'm having :
--17135-- WARNING: unhandled amd64-darwin syscall: unix:151
--17135-- You may be able to write your own handler.
--17135-- Read the file README_MISSING_SYSCALL_OR_IOCTL.
--17135-- Nevertheless we consider this a bug. Please report
--17135-- it at http://valgrind.org/support/bug_reports.html.
So I need to create a wrapper for the function, and it should work.
I will report the bug to the support.
You shouldn't test via valgrind on Mac OS X because after Sierra, it is not supported. Instead, also it is what I do, install ubuntu via an virtual machine software then run valgrind.
macOS Mojave 10.14.6's unistd.h has the following part,
#if __DARWIN_UNIX03
void encrypt(char *, int) __DARWIN_ALIAS(encrypt);
#else /* !__DARWIN_UNIX03 */
int encrypt(char *, int);
#endif /* __DARWIN_UNIX03 */
int fchdir(int);
long gethostid(void);
pid_t getpgid(pid_t);
pid_t getsid(pid_t);
Rule of thumb, always try to be portable!
Incidentally, as #Andrew Henle mentions, pid_t can be of system-dependent type. But, it shouldn't be unsigned type to preserve portability since it can be returned as -1 in the case of a failure. Moreover, on Mac OS X its type is int, as seen below
typedef int __int32_t;
typedef __int32_t __darwin_pid_t; /* [???] process and group IDs */
typedef __darwin_pid_t pid_t;

Determine `OSTYPE` during runtime in C program

In a C program, I need to find the OSTYPE during runtime, on the basis of which I will do some operations.
Here is the code
#include <stdlib.h>
#include <string.h>
int main () {
const char * ostype = getenv("OSTYPE");
if (strcasecmp(ostype, /* insert os name */) == 0) ...
return 0;
}
But getenv returns NULL (and there is segmentation fault). When I do a echo $OSTYPE in the terminal it prints darwin15 . But when I do env | grep OSTYPE nothing gets printed, which means it is not in the list of environment variables. To make it work on my local machine I can go to the .bash_profile and export the OSTYPE manually but that doesn't solve the problem if I want to run a generated executable on a new machine.
Why is OSTYPE available while running terminal, but apparently not there in the list of environment variables. How to get around this ?
For the crash, you should check if the return was NULL or not before using it in strcmp or any function. From man 3 getenv:
The getenv() function returns a pointer to the value in the
environment, or NULL if there is no match.
If you're at POSIX (most Unix's and somehow all Linux's), I agree with Paul's comment on uname.
But actually you can check for OSTYPE at compile time with precompiler (with #ifdef's), here's a similar question on so: Determine OS during runtime
Edit: uname
Good point Jonathan. man 2 uname on my linux tells how to use (and begin POSIX, macos has the same header, too):
SYNOPSIS
#include <sys/utsname.h>
int uname(struct utsname *buf);
DESCRIPTION
uname() returns system information in the structure pointed to by buf. The utsname struct is
defined in :
struct utsname {
char sysname[]; /* Operating system name (e.g., "Linux") */
char nodename[]; /* Name within "some implementation-defined
network" */
char release[]; /* Operating system release (e.g., "2.6.28") */
char version[]; /* Operating system version */
char machine[]; /* Hardware identifier */
#ifdef _GNU_SOURCE
char domainname[]; /* NIS or YP domain name */
#endif
};

No error message when using system() to execute program with buffer overflow vulnerability

Consider the following program (vul.c) with buffer overflow vulnerability.
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv)
{
char buf[10];
strcpy(buf, argv[1]);
printf("%s\n", buf);
return 0;
}
Above program compiled using gcc -o vul vul.c and executed on arch linux - linux 4.4.16-1-lts x86-64 gave following output when executed in terminal with ./vul $(perl -e 'print "A"x100') command:
AAAAAAAAAAA...A
Segmentation fault (core dumped)
Then checking the program status using echo $? command gave 139 output.
Following program (exp.c) (for crashing the above program)
#include <stdlib.h>
int main(void)
{
printf("%d\n", system("./vul $(perl -e 'print \"A\"x100')"));
return 0;
}
compiled using gcc -o exp exp.c when executed with ./exp command on same system gave following output:
AAAAAAAAAAAA...A
139
I have two questions:
Why no error message was generated by 2nd program? and,
I need to compile the program with -fstack-protector flag to enable the *** stack smashing detected *** error messages in arch linux but not in Ubuntu. In Ubuntu, it might be that this flag is include by default in gcc or is there any other reason?
As I pointed out in my comment,system returns an int with the programs's return value, which is normally it's error code (0 if successful).
If you want to print the error as a nice looking message, you can probably use strerror.
According to #rht's comment (see my next edit) and the answers to the question referenced in that comment, the returned value will be 0 on success and on error it will be error | 0x80. To get the original error code, use 128 - err_code.
try this:
#include <stdlib.h>
#include <errno.h>
int main(void)
{
int tmp = system("./vul $(perl -e 'print \"A\"x100)");
if(tmp < 0)
error("Couldn't run system command");
else if(tmp >0)
printf(stderr, "System command returned error: %s", strerror(128 - tmp));
else
; // nothing
return 0;
}
The fact that vul.c does (or does not) print an error message should be irrelevant for your exp.c program, since it depends on vul.c's compile flags values and any default compiler flags - things exp.c can't control.
EDIT(2) - in answer to the comment.
It could be that the error message returned isn't an errno value, but a signal trap value.
These are sometimes hard to differentiate and I have no good advice about how you can tell which one it is without using memcmp against the answer.
In this case you know vul.c will never return it's errno value, which leaves you only with signal trap errors, so you can use strsignal to print the error message.
As pointed out in #rht's comment, which references this question:
Passing tmp to strsignal generates the same error message: "unknown signal 139". The reason is that there is no signal with this signal number. /usr/include/bits/s‌​ignum.h contains all the signals with their signal numbers. Passing tmp-128 to strsignal works.
i.e.
#include <stdlib.h>
#include <string>
int main(void)
{
int tmp = system("./vul $(perl -e 'print \"A\"x100)");
if(tmp < 0)
error("Couldn't run system command");
else if(tmp >0)
printf(stderr, "System command returned error: %s", strsignal(tmp - 128));
else
; // nothing
return 0;
}
EDIT
The question was edited because it's code was mis-copied. I altered the answer to reflect that change.
From my comment to #Myst 's answer for "passing tmp-128 to strsignal()" function, after experimenting a little I found that it does not work in situations where the program exited normally but returned status other than 0.
Following are the contents of my /usr/include/bits/waitstatus.h:
/* If WIFEXITED(STATUS), the low-order 8 bits of the status. */
#define __WEXITSTATUS(status) (((status) & 0xff00) >> 8)
/* If WIFSIGNALED(STATUS), the terminating signal. */
#define __WTERMSIG(status) ((status) & 0x7f)
/* Nonzero if STATUS indicates normal termination. */
#define __WIFEXITED(status) (__WTERMSIG(status) == 0)
/* Nonzero if STATUS indicates termination by a signal. */
#define __WIFSIGNALED(status) \
(((signed char) (((status) & 0x7f) + 1) >> 1) > 0)
Above code show that, exit status of a program is a 16bit number, the high order 8 bits of which are the status that the program returned and some/all of the remaining bits are set if the program exited because of a signal, 7 bits of which denote the signal that caused the program to exit. That's why subtracting 128 from the exit status returned by system() will not work in the situation as described above.
System()'s source code
Since system() function too uses fork() to create a new process and waits for the termination of the process, the same method of checking a child process's status in parent process can also be applied here. Following program demonstrates this:
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>
int main(void)
{
int status = system("prg_name");
if (WIFEXITED(status))
printf("Exited Normally, status = %d\n", WEXITSTATUS(status));
else if (WIFSIGNALED(status))
printf("Killed by Signal %d which was %s\n", WTERMSIG(status), strsignal(WTERMSIG(status)));
return 0;
}
Answering my own 2nd question.
gcc -Q -v vul.c command displayed the options passed to the gcc. The options in Ubuntu included -fstack-protector-strong flag but not in arch-linux. So in Ubuntu, the flag is passed by default to gcc.
There exists two problems in your vul.c and exp.c.
In vul.c,
char buf[10];
10 is not sufficient in this case, since the argv[1], i.e., $(perl -e 'print "A"x100', is larger than the buffer to be allocated. Enlarge the buf size should fix the segmentation fault.
In exp.c, you're missing one single quote, and should be modified as followed:
printf("%d\n", system("./vul $(perl -e 'print \"A\"x100')"));

Linux: executing code that is loaded to memory manually

I'm expermenting with function pointers on Linux and trying to execute this C program:
#include <stdio.h>
#include <string.h>
int myfun()
{
return 42;
}
int main()
{
char data[500];
memcpy(data, myfun, sizeof(data));
int (*fun_pointer)() = (void*)data;
printf("%d\n", fun_pointer());
return 0;
}
Unfortunately it segfaults on fun_pointer() call. I suspect that it is connected with some memory flags, but I don't found information about it.
Could you explain why this code segfaults? Don't see to the fixed data array size, it is ok and copying without calling the function is successfull.
UPD: Finally I've found that the memory segment should be marked as executable using mprotect system call called with PROT_EXEC flag. Moreover the memory segment should be returned by mmap function as stated in the POSIX specification.
There is the same code that uses allocated by mmap memory with PROT_EXEC flag (and works):
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
int myfun()
{
return 42;
}
int main()
{
size_t size = (char*)main - (char*)myfun;
char *data = mmap(NULL, size, PROT_EXEC | PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
memcpy(data, myfun, size);
int (*fun_pointer)() = (void*)data;
printf("%d\n", fun_pointer());
munmap(data, size);
return 0;
}
This example should be complied with -fPIC gcc option to ensure that the code in functions is position-independent.
Several problems there:
Your data array stays in data segment, not in code segment.
The address relocation is not handled.
The code size is not known, just guessed.
In addition to Diask's answer you probably want to use some JIT compilation techniques (to generate executable code in memory), and you should be sure that the memory zone containing the code is executable (see mprotect(2) and the NX bit; often the call stack is not executable for security reasons). You could use GNU lightning (quickly emitting slow machine code), asmjit, libjit, LLVM, GCCJIT (able to slowly emit fast optimized machine code). You could also emit some C code in some temporary file /tmp/emittedcode.c, fork a compilation command gcc -Wall -O -fPIC -shared /tmp/emittedcode.c -o /tmp/emittedcode.so then dlopen(3) that shared object /tmp/emittedcode.so and use dlsym(3) to find function pointers by their name there.
See also this, this, this, this and that answers. Read about trampoline code, closures, and continuations & CPS.
Of course, copying code from one zone to another usually don't work (it has to be position independent code to make that work, or you need your own relocation machinery, a bit like a linker does).
It's because this line is wrong:
memcpy(data, myfun, sizeof(data));
You are copying the code (compiled) of the function instead of the address of the function.
myfun and &myfun will have the same adress, so to do your memcpy operation, you will have to use a function pointer and then copy from its address.
Example:
int (*p)();
p = myfun;
memcpy(data, &p, sizeof(data));

Casting buffer to function and executing in OS X

I'm trying to run some assembly code saved in a buffer on OS X, but I keep getting a segmentation fault. The code looks like this:
int main()
{
unsigned char buff[] = "\x66\x6a\7f\x66\xb8\x01\x00\x00\x00\x66\x83\xec\x04\xcd\x80";
( void (*)()buff )(); /* same as calling return 127 */
return 0; /* program should never reach here */
}
The code in buff is generated by nasm and it works, it causes the program to return 127. When running through a c program like so though, I get a segmentation fault. Is there a different way to do this in OS X?
First, this will not compile, because you are missing the parentheses necessary to make void (*)() a cast. The line should be ((void (*)())buff)();.
Second, if you compile without optimization, buff is likely constructed on the stack, and execution will fail because Mac OS X marks the stack as not executable.
Third, if you compile with optimization, buff is likely prepared in some data segment, and you may be able to execute it. But the instructions you have are inappropriate for the Mac OS X platform, and you get a normal access exception. You could step through the instructions in the debugger to figure out what is wrong.
The behavior of converting an object pointer to a function pointer and calling the function is not defined by the C standard. You should not rely on it to work.
Among the errors in the assembly code:
It moves one to the %ax register, which is the low two bytes of the %rax register. This leaves the high six bytes uncontrolled. Then it attempts to use %rax as an address. This fails because the value in the %rax register is not pointing at accessible memory.
It attempts to execute the instruction int $0x80. This is some Microsoft Windows, DOS, or Linux service call. On Mac OS X, it is an illegal instruction.
The stack is non executable by default -- you need to mark a page as executable with mprotect(2) in order to make it executable. Making the stack executable is highly not recommended, so if you want to run code generated at runtime, you should allocate memory on the heap instead.
For example:
#include <sys/mman.h>
#include <unistd.h>
...
// Error checking omitted for expository purposes
// Allocate 1 page of read-write memory
size_t page_size = getpagesize();
void *mem = mmap(NULL, page_size,
PROT_READ | PROT_WRITE,
MAP_ANON | MAP_PRIVATE,
-1, 0);
// Copy the shell code into the memory
char shellcode[] = "...";
memcpy(mem, shellcode, sizeof(shellcode));
// Change memory to executable and non-writable
mprotect(mem, page_size, PROT_READ | PROT_EXEC);
// Run the code
((void (*)())mem)();
// Free the memory
munmap(mem, page_size);

Resources