While testing my code, I have found out readline makes errno 2. This is ENOENT which means No such file or directory.
Does anyone know why??
#include <readline/readline.h>
#include <stdio.h>
#include <errno.h>
int main()
{
char *a = readline("shell$");
printf("%d\n", errno);
while (a)
{
printf("%s\n", a);
readline("shell$");
}
}
Do I have to set errno to 2 after readline? or Is it an error?
its in Macos
compiled with this comm -> gcc -lreadline main.c
Since I am using the Mac which is provided from a kind of institution, I don't have super privileges. Maybe could it cause the error? permission thing?
If a function does not return error value (or otherwise indicate there was an error), then, generally speaking, valuenof errno is not set or reset by it.
So probably some operation done by readline had an error, but it was recoverable and readline succeeded and did not touch errno itself.
So, before checking errno, you have to check if the function failed (or otherwise is documented to set errno in some specific way), usually by checking the return value.
Related
This question already has answers here:
Linux syscalls and errno
(4 answers)
Closed 2 years ago.
I'm writing a kernel module, and I need to use the errno variable.
I included <linux/errno.h> with no problems, and added extern int errno;,
to my code.
I use the variable in the following way: errno = ENOENT;.
When I compile the program I get the following warning, and I cannot load the module:
WARNING: "errno" [module path] undefined!
Why is that happening?
I am using a VM of Ubuntu 12.0.4
EDIT:
My hooked open syscall looks like this:
asmlinkage int hooked_open(char* path, int flags){
if(strstr(path, file_to_hide) != NULL){
return -ENOENT;
}
return original_open(path, flags);
}
When running strace cat file_to_hide when the module is loaded the return value is 4294967294, no error.
When running strace on a file that does not exist, return value is -1 and ENOENT is raised. I would like to be able to imitate that.
From man page of errno:
errno is defined by the ISO C standard to be a modifiable lvalue of type int, and must not be explicitly declared;
On some ancient systems, <errno.h> was not present or did not
declare errno, so that it was necessary to declare errno manually
(i.e., extern int errno). Do not do this. It long ago ceased to
be necessary, and it will cause problems with modern versions of
the C library.
There is no need to explicitly declare errno.
I try to call getenv in my C code, this can return correct env string in terminal, while it returns NULL in GDB/DDD.
void main() {
char * a = getenv("ANCHOR_STEM");
if (strlen(a)>0)
printf("%s\n", a);
}
The GDB/DDD is started from the same terminal.
Even I "show environment", this env exists.
Anyone any idea?
OS/Tools version info:
RHEL Linux hostname1 2.6.32-754.3.5.el6.x86_64 #1 SMP Thu Aug 9 11:56:22 EDT 2018 x86_64 GNU/Linux
GNU gdb (GDB) 7.12
gcc (GCC) 6.3.0
Even I "show environment", this env exists.
When GDB invokes your program, it starts a new shell to run this program in.
When the environment changes for the target program, most often this is the result of your shell initialization file (~/.bashrc, ~/.kshrc, etc.) changing the environment.
It is a really bad idea to change environment for non-interactive shells. Documentation on how to avoid it.
include proper header files
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
Treat warning as error.
If getenv returns NULL it is because it does not find the environment variable. but still you have to be careful. This instruction if (strlen(a)>0) becomes illegal, if getenv(....), fails. getenv sends back NULL and this instruction crash the program. It's better to test the validity of the pointer before to execute this line if (strlen(a)>0) -> which is not necessarily useful.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char * a = getenv("ANCHOR_STEM");
if( NULL != a ){
(void)puts(a);
return EXIT_SUCCESS;
}
(void)puts("none");
return EXIT_FAILURE;
}
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/signum.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')"));
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 */
I want to know how and when can I use the exit() function like the program in my book:
#include<stdio.h>
void main()
{
int goals;
printf("enter number of goals scored");
scanf("%d",&goals);
if(goals<=5)
goto sos;
else
{
printf("hehe");
exit( );
}
sos:
printf("to err is human");
}
When I run it, it shows ERROR: call to undefined function exit().
Also, I want to know how I can create an option to close the window in which the program runs? For example, I made a menu-driven program which had several options and one of them was "exit the menu". How can I make this exit the program (i.e. close the window)?
Try using exit(0); instead. The exit function expects an integer parameter. And don't forget to #include <stdlib.h>.
The exit function is declared in the stdlib header, so you need to have
#include <stdlib.h>
at the top of your program to be able to use exit.
Note also that exit takes an integer argument, so you can't call it like exit(), you have to call as exit(0) or exit(42). 0 usually means your program completed successfully, and nonzero values are used as error codes.
There are also predefined macros EXIT_SUCCESS and EXIT_FAILURE, e.g. exit(EXIT_SUCCESS);
exit(int code); is declared in stdlib.h so you need an
#include <stdlib.h>
Also:
- You have no parameter for the exit(), it requires an int so provide one.
- Burn this book, it uses goto which is (for everyone but linux kernel hackers) bad, very, very, VERY bad.
Edit:
Oh, and
void main()
is bad, too, it's:
int main(int argc, char *argv[])
Try man exit.
Oh, and:
#include <stdlib.h>
int main(void) {
/* ... */
if (error_occured) {
return (EXIT_FAILURE);
}
/* ... */
return (EXIT_SUCCESS);
}
The exit() function is a type of function with a return type without an argument. It's defined by the stdlib header file.
You need to use ( exit(0) or exit(EXIT_SUCCESS)) or (exit(non-zero) or exit(EXIT_FAILURE) ).
The following example shows the usage of the exit() function.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
printf("Start of the program....\n");
printf("Exiting the program....\n");
exit(0);
printf("End of the program....\n");
return 0;
}
Output
Start of the program....
Exiting the program....
You must add a line with #include <stdlib.h> to include that header file
and exit must return a value so assign some integer in exit(any_integer).
In addition to return an exit code to parent process -
In UNIX, an important aspect that I think has been left out is, that exit() at first calls (in reverse order) all those functions, which were registered by atexit() call.
Please refer to SUSv4 for details.
on unix like operating systems exit belongs to group of system calls. system calls are special calls which enable user code (your code) to call kernel code. so exit call makes some OS specific clean-up actions before returning control to OS, it terminates the program.
#include <stdlib.h>
// example 1
int main(int argc, char *argv){
exit(EXIT_SUCCESS);
}
// example 2
int main(int argc, char *argv){
return 0;
}
Some compilers will give you the same opcode from both of these examples but some won't. For example opcode from first function will not include any kind of stack positioning opcode which will be included in the second example like for any other function. You could compile both examples and disassemble them and you will see the difference.
You can use exit from any part of your code and be sure that process terminates. Don't forget to include integer parameter.
Write header file #include<process.h> and replace exit(); with exit(0);. This will definitely work in Turbo C; for other compilers I don't know.
Bad programming practice. Using a goto function is a complete no no in C programming.
Also include header file stdlib.h by writing #include <iostream.h>for using exit() function. Also remember that exit() function takes an integer argument . Use exit(0) if the program completed successfully and exit(-1) or exit function with any non zero value as the argument if the program has error.
Include stdlib.h in your header, and then call abort(); in any place you want to exit your program. Like this:
switch(varName)
{
case 1:
blah blah;
case 2:
blah blah;
case 3:
abort();
}
When the user enters the switch accepts this and give it to the case 3 where you call the abort function. It will exit your screen immediately after hitting enter key.
Use process.h instead of stdlib and iostream... It will work 100%.