Running Program from Call Doesn't Seg Fault - subprocess

My program writenotes keeps seg faulting when I try to write a note that is too long.
./writenotes lolololololololololololololololololololololololololololololololololololololololololololololololololololololololololololololololololo
[ * ] Writing notes
Segmentation fault
Anyways, I was trying to write a python script that calls the program and curiously enough, calling it from a python script doesn't bring a seg fault, which I thought was rather peculiar.
Heres this code:
#!/usr/bin/python
from subprocess import call
call(["./writenotes", "lolololololololololololololololololololololololololololololololololololololololololololololololololololololololololololololololololo"])
Which returns
[ * ] Writing notes
Is this because of parent processing or something like such? How would calling a program through subprocess save a program from a segfault though? Are there other ways to call programs from a script that suffer seg faults?
As a note, the writenotes program was written in C. The other script is python.

You'll almost certainly find your C program is crashing but that Python is hiding that from you. Try instead with:
print call(["./writenotes", "lolololol..."])
and see what you get as a return value.
For example, this program tries to modify a string literal and, when run normally dumps core:
int main (void) {
*"xyzzy" = 'X';
return 0;
}
However, when run from the following script:
from subprocess import call
print call(["./testprog"])
I get the output -11, indicating that signal 11 (usually SIGSEGV) was raised, as per the documentation discussing Popen.returncode which subprocess.call() uses under the covers:
A negative value -N indicates that the child was terminated by signal N (Unix only).
An alternative to checking the return code is to import check_call and CalledProcessError instead of call and then use that function. It will raise an exception if the return code is non-zero.
That's probably not so important if you're only calling one executable (just get the return value in that case) but, if you're doing a lot in sequence, catching an exception from the entire group may be more readable.
Changing the C program to only crash when the first argument is 3:
#include <stdio.h>
#include <string.h>
int main (int argc, char *argv[]) {
if (argc > 1) {
printf ("hello there %s\n", argv[1]);
if (strcmp (argv[1], "3") == 0)
*"xyzzy" = 'X';
}
return 0;
}
and the script to call it with several different arguments:
from subprocess import check_call, CalledProcessError
try:
check_call(["./testprog", "0"])
check_call(["./testprog", "1"])
check_call(["./testprog", "2"])
check_call(["./testprog", "3"])
check_call(["./testprog", "4"])
check_call(["./testprog", "5"])
check_call(["./testprog", "6"])
check_call(["./testprog", "7"])
check_call(["./testprog", "8"])
check_call(["./testprog", "9"])
except CalledProcessError as e:
print e.cmd, "failed with", e.returncode
else:
print "Everything went well"
shows that in action:
hello there 0
hello there 1
hello there 2
hello there 3
['./testprog', '3'] failed with -11

Related

"Program too large" threshold greater than actual instruction count

I've written a couple production BPF agents, but my approach is very iterative until I please the verifier and can move on. I've reached my limit again.
Here's a program that works if I have one fewer && condition -- and breaks otherwise. The confusing part is that the warning implies that 103 insns is greater-than at most 4096 insns. There's obviously something I'm misunderstanding about how this is all strung together.
My ultimate goal is to do logging based on a process' environment -- so alternative approaches are welcome. :)
Error:
$ sudo python foo.py
bpf: Argument list too long. Program too large (103 insns), at most 4096 insns
Failed to load BPF program b'tracepoint__sched__sched_process_exec': Argument list too long
BPF Source:
#include <linux/mm_types.h>
#include <linux/sched.h>
#include <linux/version.h>
int tracepoint__sched__sched_process_exec(
struct tracepoint__sched__sched_process_exec* args
) {
struct task_struct* task = (typeof(task))bpf_get_current_task();
const struct mm_struct* mm = task->mm;
unsigned long env_start = mm->env_start;
unsigned long env_end = mm->env_end;
// Read up to 512 environment variables -- only way I could find to "limit"
// the loop to satisfy the verifier.
char var[12];
for (int n = 0; n < 512; n++) {
int result = bpf_probe_read_str(&var, sizeof var, (void*)env_start);
if (result <= 0) {
break;
}
env_start += result;
if (
var[0] == 'H' &&
var[1] == 'I' &&
var[2] == 'S' &&
var[3] == 'T' &&
var[4] == 'S' &&
var[5] == 'I' &&
var[6] == 'Z' &&
var[7] == 'E'
) {
bpf_trace_printk("Got it: %s\n", var);
break;
}
}
return 0;
}
Basic loader program for reproducing:
#!/usr/bin/env python3
import sys
from bcc import BPF
if __name__ == '__main__':
source = open("./foo.c").read()
try:
BPF(text=source.encode("utf-8")).trace_print()
except Exception as e:
error = str(e)
sys.exit(error)
bpf: Argument list too long. Program too large (103 insns), at most 4096 insns
Looking at the error message, my guess would be that your program has 103 instructions and it's rejected because it's too complex. That is, the verifier gave up before analyzing all instructions on all paths.
On Linux 5.15 with a privileged user, the verifier gives up after reading 1 million instructions (the complexity limit). Since it has to analyze all paths through the program, a program with a small number of instructions can have a very high complexity. That's particularly the case when you have loops and many conditions, as is your case.
Why is the error message confusing? This error message is coming from libbpf.c:
if (ret < 0 && errno == E2BIG) {
fprintf(stderr,
"bpf: %s. Program %s too large (%u insns), at most %d insns\n\n",
strerror(errno), attr->name, insns_cnt, BPF_MAXINSNS);
return -1;
}
Since the bpf(2) syscall returns E2BIG both when the program is too large and when its complexity is too high, libbpf prints the same error message for both cases, always with at most 4096 instructions. I'm confident upstream would accept a patch to improve that error message.

Sequence of print statement in fork() syatem call

To get a a better understanding of fork() system call , i am randomly playng between fork() and print statement but got stuck in one such code ,the code is
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
int main()
{
printf("\n my process id %d \n",getpid());
pid_t pid1=fork();
printf("\nPID:=%d fork returned %d\n",getpid(),pid1);
pid_t pid2=fork();
printf("\nPID:=%d fork returned %d\n",getpid(),pid2);
pid_t pid3=fork();
printf("\nPID:=%d fork returned %d\n",getpid(),pid3);
return 0;
}
Here is the output obtained-:
I am not able to get the print sequence it is following.Only thing i am getting is that first the process with PID 5079 is executing ,and for all the fork() system call,it is returning child PID to the parent process.I am not getting the further sequence.
The fork() might seem a little confusing at first, but its actually pretty simple. What it does is copy the current process into a new process in another memory location (copy everything, its data, code, current instruction, ...).
So we started with a process with pid = 5079, when we got to the fork call, a child process with pid = 5080 was created, and it has the same code of the parent process.
// Parent Process // // Child Process //
#include<stdio.h> #include<stdio.h>
#include<unistd.h> #include<unistd.h>
#include<stdlib.h> #include<stdlib.h>
int main() int main()
{ {
printf("\... printf("\...
pid_t pid1=fork(); pid_t pid1=fork();
printf("\nPI... //Next line// printf("\nPI... //Next line//
pid_t pid2=fork(); pid_t pid2=fork();
printf("\nPID:=... printf("\nPID:=...
pid_t pid3=fork(); pid_t pid3=fork();
printf("\nPID:=... printf("\nPID:=...
return 0; return 0;
} }
before we continue following the code, the return value of the fork call is as follows: inside the process that called the fork(), the return value is the pid of the child process (pid1 variable in Parent Process = 5080), and inside the child process, the output is 0 (pid1 variable in Child Process = 0).
So the print statement after the fork will be executed by the Parent Process and the Child Process with different getpid() value and different pid1 values, the parent has getpid() = 5079, and pid1 = child's pid = 5080 (you can see this in the third line of the output). The child will make its own print statement, with getpid() = 5080 and pid1 = 0, you can see this in the 8th line of the output, but why the 8th line!!!
The operating system schedules the process, that is, it decides which process the CPU will work on and for how long. so it seems that the OS decided that the parent process (pid = 5079) should run for a little longer, and left the child process (pid = 5080) waiting for the CPU to execute its instructions.
So process 5079 went on with the next fork, creating a new child process with pid = 5081. Then it printed what we expect in the third line, then it went on to the last fork creating process 5082, printing what we would expect in the forth line, then terminating (process 5079 terminated, leaving 5080,5081,5082 waiting, and Adopted by the OS, they need to have a parent, but this isn't important to the output).
Now that 5079 terminated, we have 3 processes waiting in the memory for the CPU to work them. The operating system must decide which process to run, and it seems to have choose the process that is closest to terminate, which is process 5082, let's look at the remaining instructions for each process:
// process 5082 // // process 5081 // // process 5080 //
printf("\nP... printf("\nP... printf("\nP...
return 0; pid_t pid3=fork(); pid_t pid2=fork();
printf("\nP... printf("\nP...
return 0; pid_t pid3=fork();
printf("\nP...
return 0;
Why is this the remaining code? any process created by a fork in some other process will start executing after that fork statement like we have seen earlier. so process 5082 printed line 5 then terminated (its value of pid3 = 0 because it is a child of 5079). After terminating of 5082, 5081 took the CPU, and it printed line 6, then created process 5085 as we can see in line 6 (why not 5083 in order? maybe the OS created some process during the execution of your code).
after printing line 6 process 5081 has terminated. Now we have 5080, and 5085 in the memory. you should now be able to follow the pattern, 5080 was selected to run, creating 5086 and 5087 then terminating. then 5085 ran, followed by 5087, which only had the print statement in the end, both then terminated, and we were left with 5086 which printed, made the last fork creating 5088, then terminated as did 5088 after its print.
Operating systems is a fascinating field, its fun to go beyond the system calls, if you are interested in this I would recommend this book, it is what I studied in college:
https://www.amazon.com/Operating-System-Concepts-Abraham-Silberschatz/dp/0470128720

POSIX write(2) to file descriptor in Swift fails with “Bad file descriptor”

I am writing code in Swift to write to a file on a POSIX system (it is meant to work on Linux and OSX), and using the POSIX open(2) and write(2) system calls. However, I have found that, while writing to standard output works, doing so to an opened file descriptor gives a "Bad file descriptor" error; i.e., when writing to stdout:
> let bytes: [UInt8] = [ 65, 66, 67, 13, 10 ]
> write(STDOUT_FILENO, UnsafePointer(bytes), 5)
ABC
And when opening a file:
> let fd = open("/tmp/testfile", O_CREAT, 0o644)
fd: CInt = 3
> write(fd, UnsafePointer(bytes), 5)
$R1: Int = -1
> print(String.fromCString(strerror(errno)))
Optional("Bad file descriptor")
This happens on both OSX (with import Darwin) and Linux (with import Glibc). In both cases, the file is created, and remains at size 0. Am I doing something wrong, or is there a bug in Swift or the Swift/C interface, and if the latter, does anyone know a workaround (that will work on Linux; using Cocoa/Foundation libraries is not yet an option)? Thanks.
You have to pass the O_WRONLY ("open for writing only") or
O_RDWR ("open for reading and writing") flag to open(),
otherwise you cannot write to the file descriptor:
let fd = open("/tmp/testfile", O_WRONLY | O_CREAT, 0o644)

How to save SystemC variables during vcs simulation and restore back based on stimulus change

My tests are in SystemC env and for all my tests i run a common routine(basically its my init sequence which doesn't vary much based on seed). This common routine is followed by my actual test.
It looks something like this:
Test_MAIN
init_seq();
my_test();;
Here init_seq() is that common routine and my_test() is my actual test that have actual test sequence which initiate multiple SC threads, for initiating various kind of traffic.
Now, my problem is that i want a way to avoid init_seq() for every run. The entire test should run for one time and the next time i should have a mechanism to directly run from my_test()(which is basically skipping/preloading init_seq() part to the simulator).
VCS save and restore can't be used directly as in this case we also will have to restore the SystemC variables.
Could you please direct me on this..!!
Thanks
ByreddyNaresh
I tried with a SystemC test with init() and run() routine, and use VCS save/restart to restore the test. It seems OK to me that a member variable 'cnt' in test is restored successfully.
This is my test:
// test.h
#ifndef TEST_H
#define TEST_H
#include <systemc.h>
class test: public sc_module{
public:
sc_in<bool> init_start;
sc_in<bool> run_start;
void init();
void run();
int cnt;
SC_CTOR(test){
SC_THREAD(init);
sensitive_pos << init_start;
dont_initialize();
SC_THREAD(run);
sensitive_pos << run_start;
dont_initialize();
}
};
#endif
and
// test.cpp
#include "test.h"
void test::init(){
printf("test init:\n");
while(1){
cnt = 10;
printf("init cnt to %d\n", cnt);
wait();
}
}
void test::run(){
printf("test run:\n");
while(1){
cnt++;
printf("cnt = %d\n", cnt);
wait();
}
}
and the top:
// tb.v
module tb;
reg init_start;
reg run_start;
initial begin
init_start = 0;
run_start = 0;
#100
init_start = 1;
#100
$save("save.chk");
#100
run_start = 1;
#100
$finish;
end
test u_test(
.init_start(init_start),
.run_start(run_start)
);
endmodule
After 'save.chk' is generated, I run it directly and the output is:
$ save.chk
Chronologic VCS simulator copyright 1991-2012
Contains Synopsys proprietary information.
Compiler version G-2012.09; Runtime version G-2012.09; Mar 5 18:01 2014
test run:
cnt = 11
$finish called from file "tb.v", line 17.
$finish at simulation time 1300
V C S S i m u l a t i o n R e p o r t
Time: 1300 ps
CPU Time: 0.260 seconds; Data structure size: 0.0Mb
Wed Mar 5 18:01:08 2014
It seems variable 'cnt' is restored from '10', as is done in init() routine.
Don't know if this is the case you met?

Why system doesn't return main's value?

[root# test]$ cat return10.c
#include <stdio.h>
int main(int argc, char *argv[]){
return 10;
}
[root# test]$ perl -e 'print system("/path_to_return10")'
2560
I was expecting 10 but got 2560,why?
See $? in perldoc perlvar.
You got 10 * 256 (return value = 10) + 0 * 128 (there was no core dump) + 0 (process wasn't killed by signal).
as specified in the documentation for the system call in perl (http://perldoc.perl.org/functions/system.html):
The return value is the exit status of the program as returned by the
wait call. To get the actual exit value, shift right by eight (see
below).
indeed: 2560 >> 8 = 10