@@ -55,24 +55,29 @@ def setUp(self):
5555 self .cancel ('%s is needed for the test to be run' % packages )
5656 for file_name in ['test.c' , 'libc_livepatch1.c' , 'libc_livepatch1.dsc' ,
5757 'test_2func.c' , 'libc_livepatch_2func.c' , 'libc_livepatch_2func.dsc' ,
58- 'Makefile' ]:
58+ 'libc_livepatch_nested.c' , 'libc_livepatch_nested.dsc' , 'Makefile' ,
59+ 'live_patch_nested.tar.gz' , 'test_long.c' ]:
5960 self .copyutil (file_name )
6061
61- def apply_livepatch (self , test = 'test' , livepatch = 'libc_livepatch1.so ' ):
62+ def start_test (self , test = 'test' ):
6263 """
63- function applies a live patch to the running test program and returns
64- the stderr output
64+ function starts running test program
6565 """
6666 self .test_process = process .SubProcess (
6767 'LD_PRELOAD=/usr/lib64/libpulp.so.0 ./%s' % test , shell = True , sudo = True )
6868 self .pid = self .test_process .start ()
69- a = self .test_process .get_stderr ()
7069 time .sleep (10 )
70+
71+ def apply_livepatch (self , livepatch = 'libc_livepatch1.so' ):
72+ """
73+ function applies a live patch to the running test program and returns
74+ the stderr output
75+ """
7176 patch_process = process .SubProcess (
7277 'ulp trigger -p %s %s' % (self .pid , livepatch ), shell = True , sudo = True )
7378 patch_process .start ()
7479 time .sleep (20 )
75- return (self .test_process .get_stderr ())
80+ return (self .test_process .get_stderr ())
7681
7782 def revert_livepatch (self , livepatch = 'libc_livepatch1.so' ):
7883 """
@@ -103,6 +108,7 @@ def test_basic(self):
103108 os .chdir (self .teststmpdir )
104109 process .system ('make' , shell = True )
105110 process .system ('ulp packer libc_livepatch1.dsc' , shell = True )
111+ self .start_test ()
106112 livepatch_output = self .apply_livepatch ()
107113 apply_count = self .count_string (livepatch_output )
108114 if apply_count < 10 :
@@ -167,10 +173,15 @@ def test_multiple_process_livepatching(self):
167173 self .fail ("Livepatch revert failed for %s processes" % (patch_number - patch_revert_number ))
168174
169175 def test_two_function_livepatching (self ):
176+ """
177+ This test function ensures that a livepatch with two functions is successfully applied,
178+ both functions are live-patched, and the livepatch can be correctly reverted.
179+ """
170180 os .chdir (self .teststmpdir )
171181 process .system ('make' , shell = True )
172182 process .system ('ulp packer libc_livepatch_2func.dsc' , shell = True )
173- livepatch_output = self .apply_livepatch ('test_2func' , 'libc_livepatch_2func.so' )
183+ self .start_test ('test_2func' )
184+ livepatch_output = self .apply_livepatch ('libc_livepatch_2func.so' )
174185 apply_count = self .count_string (livepatch_output )
175186 apply_count_2 = livepatch_output .count (b'glibc-livepatch-realloc\n ' )
176187 if apply_count_2 < 10 :
@@ -182,3 +193,81 @@ def test_two_function_livepatching(self):
182193 revert_output = self .revert_livepatch ('libc_livepatch_2func.so' )
183194 if self .count_string (revert_output ) - apply_count > 1 :
184195 self .fail ("Reverting patch is not successful" )
196+
197+ def test_nested_function_livepatching (self ):
198+ """
199+ This test function ensures that both a primary livepatch and a nested livepatch
200+ are successfully applied and later reverted.
201+ """
202+ os .chdir (self .teststmpdir )
203+ process .system ('make' , shell = True )
204+ process .system ('ulp packer libc_livepatch1.dsc' , shell = True )
205+ self .start_test ()
206+ livepatch_output = self .apply_livepatch ()
207+ apply_count_1 = livepatch_output .count (b'glibc-livepatch\n ' )
208+ if apply_count_1 < 10 :
209+ self .fail ("Applying first livepatch failed." )
210+ else :
211+ self .log .info ("Successfully applied first livepatch" )
212+ process .system ('ulp packer libc_livepatch_nested.dsc' , shell = True )
213+ livepatch_output = self .apply_livepatch ('libc_livepatch_nested.so' )
214+ time .sleep (10 )
215+ apply_count_2 = livepatch_output .count (b'glibc-livepatch-nested\n ' )
216+ if apply_count_2 < 10 :
217+ self .fail ("Applying nested livepatch failed." )
218+ else :
219+ self .log .info ("Successfully applied nested livepatch" )
220+ process .system_output ('ulp trigger --revert -p %s libc_livepatch_nested.so' % self .pid , shell = True )
221+ time .sleep (10 )
222+ process .system_output ('ulp trigger --revert -p %s libc_livepatch1.so' % self .pid , shell = True )
223+
224+ def test_nested_function_livepatching_multiple (self ):
225+ """
226+ This test function ensures that 12 nested livepatches are successfully applied and
227+ later reverted, with each iteration checked for proper application.
228+ """
229+ os .chdir (self .teststmpdir )
230+ process .system ('tar -xf live_patch_nested.tar.gz' , shell = True )
231+ process .system ('make' , shell = True )
232+ self .start_test ('test_long' )
233+ os .chdir ('live_patch_nested' )
234+ for i in range (1 , 13 ):
235+ process .system ('gcc -fPIC -fpatchable-function-entry=16,14 -shared -o libc_livepatch%s.so'
236+ ' libc_livepatch%s.c -msplit-patch-nops' % (i , i ), shell = True )
237+ process .system ('ulp packer %s/live_patch_nested/libc_livepatch%s.dsc' % (self .teststmpdir , i ), shell = True )
238+ livepatch_output = self .apply_livepatch ('libc_livepatch%s.so' % i )
239+ for i in range (2 , 13 ):
240+ apply_count = livepatch_output .count (('glibc-livepatch' + str (i )).encode ('utf-8' ))
241+ if apply_count < 10 :
242+ self .fail ("Applying livepatch failed for %s iteration." % i )
243+ else :
244+ self .log .info ("Successfully applied livepatch for %s iteration" % i )
245+ for i in range (1 , 13 ):
246+ process .system_output ('ulp trigger --revert -p %s libc_livepatch%s.so' % (self .pid , i ), shell = True )
247+ time .sleep (2 )
248+
249+ def test_nested_function_livepatching_multiple2 (self ):
250+ """
251+ This test function ensures that 12 nested livepatches are successfully applied and later reverted,
252+ with each iteration checked for proper application. The main difference between this test function and
253+ the previous one is the order of reverting livepatches, which happens in reverse order (from 12 to 1) in this version.
254+ """
255+ os .chdir (self .teststmpdir )
256+ process .system ('tar -xf live_patch_nested.tar.gz' , shell = True )
257+ process .system ('make' , shell = True )
258+ self .start_test ('test_long' )
259+ os .chdir ('live_patch_nested' )
260+ for i in range (1 , 13 ):
261+ process .system ('gcc -fPIC -fpatchable-function-entry=16,14 -shared -o libc_livepatch%s.so'
262+ ' libc_livepatch%s.c -msplit-patch-nops' % (i , i ), shell = True )
263+ process .system ('ulp packer %s/live_patch_nested/libc_livepatch%s.dsc' % (self .teststmpdir , i ), shell = True )
264+ livepatch_output = self .apply_livepatch ('libc_livepatch%s.so' % i )
265+ for i in range (2 , 13 ):
266+ apply_count = livepatch_output .count (('glibc-livepatch' + str (i )).encode ('utf-8' ))
267+ if apply_count < 10 :
268+ self .fail ("Applying livepatch failed for %s iteration." % i )
269+ else :
270+ self .log .info ("Successfully applied livepatch for %s iteration" % i )
271+ for i in range (12 , 0 , - 1 ):
272+ process .system_output ('ulp trigger --revert -p %s libc_livepatch%s.so' % (self .pid , i ), shell = True )
273+ time .sleep (2 )
0 commit comments