[PATCH 1/2] Add a test for longjmp from user context

Adhemerval Zanella Netto adhemerval.zanella@linaro.org
Tue Dec 19 14:06:53 GMT 2023



On 14/12/23 21:04, Noah Goldstein wrote:
> On Thu, Dec 14, 2023 at 4:43 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>>
>> On Thu, Dec 14, 2023 at 2:39 PM Noah Goldstein <goldstein.w.n@gmail.com> wrote:
>>>
>>> On Thu, Dec 14, 2023 at 1:37 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>>>>
>>>> Verify that longjmp works correctly after setcontext is called to switch
>>>> to a user context.
>>>> ---
>>>>  stdlib/Makefile           |  1 +
>>>>  stdlib/tst-setcontext10.c | 87 +++++++++++++++++++++++++++++++++++++++
>>>>  2 files changed, 88 insertions(+)
>>>>  create mode 100644 stdlib/tst-setcontext10.c
>>>>
>>>> diff --git a/stdlib/Makefile b/stdlib/Makefile
>>>> index 0b154e57c5..8c6249aab4 100644
>>>> --- a/stdlib/Makefile
>>>> +++ b/stdlib/Makefile
>>>> @@ -234,6 +234,7 @@ tests := \
>>>>    tst-setcontext7 \
>>>>    tst-setcontext8 \
>>>>    tst-setcontext9 \
>>>> +  tst-setcontext10 \
>>>>    tst-strfmon_l \
>>>>    tst-strfrom \
>>>>    tst-strfrom-locale \
>>>> diff --git a/stdlib/tst-setcontext10.c b/stdlib/tst-setcontext10.c
>>>> new file mode 100644
>>>> index 0000000000..2926753cb1
>>>> --- /dev/null
>>>> +++ b/stdlib/tst-setcontext10.c
>>>> @@ -0,0 +1,87 @@
>>>> +/* Check longjmp from user context to main context.
>>>> +   Copyright (C) 2023 Free Software Foundation, Inc.
>>>> +   This file is part of the GNU C Library.
>>>> +
>>>> +   The GNU C Library is free software; you can redistribute it and/or
>>>> +   modify it under the terms of the GNU Lesser General Public
>>>> +   License as published by the Free Software Foundation; either
>>>> +   version 2.1 of the License, or (at your option) any later version.
>>>> +
>>>> +   The GNU C Library is distributed in the hope that it will be useful,
>>>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>>>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>>>> +   Lesser General Public License for more details.
>>>> +
>>>> +   You should have received a copy of the GNU Lesser General Public
>>>> +   License along with the GNU C Library; if not, see
>>>> +   <https://www.gnu.org/licenses/>.  */
>>>> +
>>>> +#include <stdio.h>
>>>> +#include <stdlib.h>
>>>> +#include <setjmp.h>
>>>> +#include <ucontext.h>
>>>> +#include <unistd.h>
>>>> +
>>>> +static jmp_buf jmpbuf;
>>>> +static ucontext_t ctx;
>>>> +
>>>> +static void f2 (void);
>>>> +
>>>> +static void
>>>> +__attribute__ ((noinline, noclone))
>>>> +f1 (void)
>>>> +{
>>>> +  printf ("start f1\n");
>>>> +  f2 ();
>>>> +}
>>>> +
>>>> +static void
>>>> +__attribute__ ((noinline, noclone))
>>>> +f2 (void)
>>>> +{
>>>> +  printf ("start f2\n");
>>>> +  if (setcontext (&ctx) != 0)
>>>> +    {
>>>> +      printf ("%s: setcontext: %m\n", __FUNCTION__);
>>>> +      exit (EXIT_FAILURE);
>>>> +    }
>>>> +}
>>>> +
>>>> +static void
>>>> +f3 (void)
>>>> +{
>>>> +  printf ("start f3\n");
>>>> +  longjmp (jmpbuf, 1);
>>>> +}
>>>> +
>>>> +static int
>>>> +__attribute__ ((noinline, noclone))
>>>> +do_test_1 (void)
>>>> +{
>>>> +  char st1[32768];
>>>> +
>>>> +  if (setjmp (jmpbuf) != 0)
>>>> +    return 0;
>>>> +
>>>> +  puts ("making contexts");
>>>> +  if (getcontext (&ctx) != 0)
>>>> +    {
>>>> +      printf ("%s: getcontext: %m\n", __FUNCTION__);
>>>> +      exit (EXIT_FAILURE);
>>>> +    }
>>>> +  ctx.uc_stack.ss_sp = st1;
>>>> +  ctx.uc_stack.ss_size = sizeof st1;
>>>> +  ctx.uc_link = NULL;
>>>> +  makecontext (&ctx, (void (*) (void)) f3, 0);
>>>> +  f1 ();
>>>> +  puts ("FAIL: returned from f1 ()");
>>>> +  exit (EXIT_FAILURE);
>>>> +}
>>>> +
>>>> +static int
>>>> +do_test (void)
>>>> +{
>>>> +  return do_test_1 ();
>>>> +}
>>>> +
>>>> +#include <support/test-driver.c>
>>>> --
>>>> 2.43.0
>>>>
>>>
>>> What is the success path here?
>>
>> When longjmp is called from the user context, do_test_1
>> returns 0:
>>
>> if (setjmp (jmpbuf) != 0)
>>   return 0;
>>
>> --
>> H.J.
> 
> LGTM.
> 
> Reviewed-by: Noah Goldstein <goldstein.w.n@gmail.com>

I am seeing failures with gcc version 13.2.1 / binutils 2.41.0.20231122 with
glibc configured with --enable-stack-protector=all --enable-tunables=yes 
--enable-bind-now=yes --enable-profile=yes --enable-fortify-source=2 
--enable-hardcoded-path-in-tests --enable-cet (the hardware does not support
CET):

$ make test t=stdlib/tst-setcontext10
[...]
*** longjmp causes uninitialized stack frame ***: terminated
make[2]: Leaving directory '/home/azanella/Projects/glibc/glibc-git-master/stdlib'
FAIL: stdlib/tst-setcontext10
original exit status 1
making contexts
start f1
start f2
start f3
Didn't expect signal from child: got `Aborted'


More information about the Libc-alpha mailing list