I have wrote the following program which using math.h library (in the function count_lines, im using ceil and log10 functions).
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <wait.h>
#include <sys/types.h>
#include <pthread.h>
#include <math.h>
#include <string.h>
void count_lines(short unsigned int G);
int main(int argc, char* argv[]) {
count_lines(18);
return 0;
}
void count_lines(short unsigned int G) {
int status,g=0;
pid_t pid;
do{
pid = fork();
if(pid ==0)
g++;
}while(g<G && pid ==0 );
waitpid(pid, &status, 0);
int num_of_digits = ceil(log10(g) +1);
char* command = (char*) malloc(sizeof(char) * (strlen("grep \"generation is ") + num_of_digits +strlen("\" out.txt ") + strlen("| wc -l")+1));
sprintf(command,"grep \"generation is %d\" out.txt| wc -l", g);
printf("%s\n" , command);
}
I am using clion wsl and in order to link math library I used the following CMakeLists.txt:
cmake_minimum_required(VERSION 3.24)
project(HW1 C)
set(CMAKE_C_STANDARD 99)
add_executable(HW1 main.c)
target_link_libraries(${PROJECT_NAME} m)
When I run the program I get segmentation fault:
grep "generation is 18" out.txt| wc -l
grep "generation is 17" out.txt| wc -l
grep "generation is 16" out.txt| wc -l
grep "generation is 15" out.txt| wc -l
grep "generation is 14" out.txt| wc -l
grep "generation is 13" out.txt| wc -l
grep "generation is 12" out.txt| wc -l
grep "generation is 11" out.txt| wc -l
grep "generation is 10" out.txt| wc -l
grep "generation is 9" out.txt| wc -l
grep "generation is 8" out.txt| wc -l
grep "generation is 7" out.txt| wc -l
grep "generation is 6" out.txt| wc -l
grep "generation is 5" out.txt| wc -l
grep "generation is 4" out.txt| wc -l
grep "generation is 3" out.txt| wc -l
grep "generation is 2" out.txt| wc -l
grep "generation is 1" out.txt| wc -l
/bin/bash: line 1: 5353 Segmentation fault (core dumped) /mnt/c/Users/itzik/Documents/OperatingSystems/HW1/cmake-build-debug/HW1
Process finished with exit code 139
If I dont use math.h functions and replace num_of_digits with some constant number, it works fine and I get the desirable output:
grep "generation is 18" out.txt| wc -l
grep "generation is 17" out.txt| wc -l
grep "generation is 16" out.txt| wc -l
grep "generation is 15" out.txt| wc -l
grep "generation is 14" out.txt| wc -l
grep "generation is 13" out.txt| wc -l
grep "generation is 12" out.txt| wc -l
grep "generation is 11" out.txt| wc -l
grep "generation is 10" out.txt| wc -l
grep "generation is 9" out.txt| wc -l
grep "generation is 8" out.txt| wc -l
grep "generation is 7" out.txt| wc -l
grep "generation is 6" out.txt| wc -l
grep "generation is 5" out.txt| wc -l
grep "generation is 4" out.txt| wc -l
grep "generation is 3" out.txt| wc -l
grep "generation is 2" out.txt| wc -l
grep "generation is 1" out.txt| wc -l
grep "generation is 0" out.txt| wc -l
Process finished with exit code 0
So I guess the segmentation fault occurs when we are trying to read ceil/log10 from the header.
How can I fix it?
Thanks in advance.
Related
Here is a minimal reproducible example of my issue
#include <unistd.h>
int main (int argc, char *argv[])
{
char *a[] = {"ls", "-l", "~", "..", "-A", NULL};
execvp(a[0], a);
return 0;
}
I expected this to work as it would when I run ls -l ~ .. -A in the shell, but on running the executable after compiling I get the following output
❯ clang main.c -o a
❯ ./a
ls: -A: No such file or directory
ls: ~: No such file or directory
..:
total 0
drwxr-xr-x 3 me staff 96 Sep 1 11:56 test
I'm using MacOS/10.13
My code on terminal:
echo -n this | openssl enc -aes-128-cbc -K 0 -iv 0 -base64
c code:
int main(){
system("echo -n this | openssl enc -aes-128-cbc -K 0 -iv 0 -base64");
}
Running ScreenShot
The echo command has the problem that its behavior is not portable between different shells or environments. It is better to use printf instead, which is portable. In your case, replace the echo -n statement with printf, resulting in the following code:
#include <stdlib.h>
int main() {
system("printf this | openssl enc -aes-128-cbc -K 0 -iv 0 -base64");
}
Building and running:
$ gcc test.c -o test
$ ./test
gc8X3os/mFxDE73AebmweQ==
as desired.
I'm trying to merge a set of files using C system() call:
int main(int argc, char* argv[]) {
return system("cat output{1,2} > merged.out");
}
The result is:
$ gcc test.c
$ ./a.out
cat: output{1,2}: No such file or directory
It works if I do it directly in bash:
$ ls output{1,2}
output1 output2
$ cat output{1,2}
1,2
3,4
How can I enable parameter expansion in the system() call?
The reason for this is that system uses /bin/sh, which does not expand braces. For instance, try:
/bin/sh -c 'echo cat output{1,2}'
and compare
/bin/bash -c 'echo cat output{1,2}'
If you must, something like
system("/bin/bash -c 'cat output{1,2} > merged.out'");
but why not simply read both files and write the output to merged.out?
system passes the command to /bin/sh -c. If parameter expansion does not work as expected /bin/sh is not linked to /bin/bash on the system. You can explicitely start a bash shell using this:
return system("bash -c \"cat output{1,2} > merged.out\"");
Expansion is a shell duty. Something like `system("/usr/bin/bash -c \"cat output{1,2}\" > merged.out");" should work.
Here is a program which shows euid:
$ cat main.c
#include <stdio.h>
#include <unistd.h>
int main(int argc, char** argv) {
printf("euid: %d\n", geteuid());
return 0;
}
$ gcc main.c -o main
$ ls -l main
-rwxr-xr-x 1 scdmb scdmb 6425 Mar 30 14:07 main
Let's set set-user-ID-on-execution option:
$ chmod u+s main
$ ls -l main
-rwsr-xr-x 1 scdmb scdmb 6425 Mar 30 14:07 main
Program executed as user scdmb shows right euid:
$ ./main
euid: 1000
$ id -u scdmb
1000
Let's execute program as other user:
$ id -u jakisuser
1001
$ su jakisuser
Password:
Now euid is the same as uid of user jakisuser:
$ ./main
euid: 1001
Why this set-user-ID-on-execution option doesn't cause that second time effective user id is not 1000 (as file owner) but 1001 (as the one who executes program)? Shouldn't it be the same as owner of file main?
I've just tried this here and your program works perfectly.
What I suspect is happening is that you have apparmor or selinux or something else in the way which is preventing your SUID bit from taking effect. I suggest you disable those and try again.
I wish to start a root command from a 'set-user root' program,
so I wrote the following C sample program:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
void main(int argc, char *argv[])
{
if(argc > 2) {
setuid(0);
printf("setuid(0) executed\n");
} else
printf("setuid(0) NOT executed\n");
system(argv[1]);
}
Testing it on Debian 6 (64 bit), I noticed that passing "/bin/sh" as the argument, I always get a ROOT SHELL, even if argc == 2:
$ gcc foo.c -o foo
$ su
Password: *****
# chown root:root ./foo
# chmod 4755 ./foo
# ls -l foo
-rwsr-xr-x 1 root root 6887 11 dic 17.44 foo
# exit
exit
$ ./foo /bin/sh
setuid(0) NOT executed
# exit <<<<< ROOT SHELL
$ ./foo /bin/sh 12345
setuid(0) executed
# exit <<<<< ROOT SHELL
On Slackware 14 (32 bit), it behaves differently:
$ gcc foo.c -o foo
$ su
Password: *****
bash-4.2# chown root:root ./foo
bash-4.2# chmod 4755 ./foo
bash-4.2# ls -l foo
-rwsr-xr-x 1 root root 6292 dic 11 17:53 foo
bash-4.2# exit
exit
$ foo /bin/sh
setuid(0) NOT executed
sh-4.2$ exit <<<<< USER SHELL
exit
$ foo /bin/sh 12345
setuid(0) executed
sh-4.2# exit <<<<< ROOT SHELL
exit
If I give "/usr/bin/dolphin" as argument, there is also a different behaviour.
On Debian I'm not able to get it work:
$ ./foo /usr/bin/dolphin
setuid(0) NOT executed
<unknown program name>(28884)/: KUniqueApplication: Cannot find the D-Bus session server: "Unable to autolaunch when setuid"
<unknown program name>(28883)/: KUniqueApplication: Pipe closed unexpectedly.
On Slackware, it works only if argc == 2, so I cannot start dolphin as root.
Why?
To explain the slightly peculiar setuid behaviour, you need to understand that /bin/sh may actually be bash, and the default behaviour of bash is to drop euid unless it's invoked with -p.
This means that if you invoke bash with -p, then you should see a 'root' like shell:-
natsu ~> id -a
uid=1000(me) gid=1000(me) groups=1000(me),4(adm),15(kmem)
natsu ~> ./foo "/bin/bash -p"
setuid(0) NOT executed
bash-4.2# id -a
uid=1000(me) gid=1000(me) euid=0(root) egid=0(root) groups=0(root),4(adm),15(kmem),1000(me)
Whereas invoked without the -p option yields the observed behaviour:
pshanahan#natsu ~> ./foo /bin/bash
setuid(0) NOT executed
bash-4.2$ id -a
uid=1000(me) gid=1000(me) groups=1000(me),4(adm),15(kmem)
but in reality, you only have effective user id 0, not real user id 0.
getting the GUI to run in this situation... That's another matter altogether; but this should help you understand the behaviour in this case.