Hi Tim,

trondd wrote on Tue, Aug 24, 2021 at 07:45:33PM -0400:
> "Theo de Raadt" <dera...@openbsd.org> wrote:
 
>> +h_alrm(int signo)
>> +{
>> +       GLOBAL_CLP;
>> +
>> +       F_SET(clp, CL_SIGALRM);
>> 
>> F_SET is |=, which is not atomic.
>> 
>> This is unsafe.  Safe signal handlers need to make single stores to
>> atomic-sized variables, which tend to be int-sized, easier to declare
>> as sig_atomic_t.  Most often these are global scope with the following
>> type:
>> 
>>      volatile sig_atomic_t variable
>> 
>> I can see you copied an existing practice.  Sadly all the other
>> signal handlers are also broken in the same way.
>> 
>> The flag bits should be replaced with seperate sig_atomic_t variables.

> Ok.  Took a swing at converting the signal handling to sig_atomic_t flags.
> No additional changes added other than removing a redundant check of the
> flags in cl_read.c.  Seemed to be a pretty straight-forward conversion and
> I haven't found any change in behavior.

Committed, thank you.
  Ingo


CVSROOT:        /cvs
Module name:    src
Changes by:     schwa...@cvs.openbsd.org        2021/09/01 08:28:15

Modified files:
        usr.bin/vi/cl  : cl.h cl_funcs.c cl_main.c cl_read.c 

Log message:
As a first step towards safe signal handling, improve the h_int()
and h_winch() signal handlers to make one single store to a
sig_atomic_t variable.  Note that the h_hup() and h_term() signal
handlers are still unsafe after this commit because they also set
the "killersig" (how fitting!) field in a global struct.

Despite storing information in static global variables rather than
in structs passed around as arguments, this patch does not cause a
change in behaviour because there is always exactly one GS object,
initialized using gs_init() called from the top of main(), and
screen_init() stores a pointer to this one and only GS object in
the .gp member of each and every SCR object.  Talk about useless
abstraction...

Problem pointed out by deraadt@.
Patch from Tim <trondd at kagu hyphen tsuchi dot com> on tech@.
OK deraadt@.


> Index: cl/cl.h
> ===================================================================
> RCS file: /cvs/src/usr.bin/vi/cl/cl.h,v
> retrieving revision 1.10
> diff -u -p -r1.10 cl.h
> --- cl/cl.h   27 May 2016 09:18:11 -0000      1.10
> +++ cl/cl.h   24 Aug 2021 23:34:27 -0000
> @@ -11,6 +11,11 @@
>   *   @(#)cl.h        10.19 (Berkeley) 9/24/96
>   */
>  
> +extern       volatile sig_atomic_t cl_sighup;
> +extern       volatile sig_atomic_t cl_sigint;
> +extern       volatile sig_atomic_t cl_sigterm;
> +extern       volatile sig_atomic_t cl_sigwinch;
> +
>  typedef struct _cl_private {
>       CHAR_T   ibuf[256];     /* Input keys. */
>  
> @@ -45,11 +50,7 @@ typedef struct _cl_private {
>  #define      CL_RENAME_OK    0x0004  /* User wants the windows renamed. */
>  #define      CL_SCR_EX_INIT  0x0008  /* Ex screen initialized. */
>  #define      CL_SCR_VI_INIT  0x0010  /* Vi screen initialized. */
> -#define      CL_SIGHUP       0x0020  /* SIGHUP arrived. */
> -#define      CL_SIGINT       0x0040  /* SIGINT arrived. */
> -#define      CL_SIGTERM      0x0080  /* SIGTERM arrived. */
> -#define      CL_SIGWINCH     0x0100  /* SIGWINCH arrived. */
> -#define      CL_STDIN_TTY    0x0200  /* Talking to a terminal. */
> +#define      CL_STDIN_TTY    0x0020  /* Talking to a terminal. */
>       u_int32_t flags;
>  } CL_PRIVATE;
>  
> Index: cl/cl_funcs.c
> ===================================================================
> RCS file: /cvs/src/usr.bin/vi/cl/cl_funcs.c,v
> retrieving revision 1.20
> diff -u -p -r1.20 cl_funcs.c
> --- cl/cl_funcs.c     27 May 2016 09:18:11 -0000      1.20
> +++ cl/cl_funcs.c     24 Aug 2021 23:34:27 -0000
> @@ -601,7 +601,7 @@ cl_suspend(SCR *sp, int *allowedp)
>       if (cl_ssize(sp, 1, NULL, NULL, &changed))
>               return (1);
>       if (changed)
> -             F_SET(CLP(sp), CL_SIGWINCH);
> +             cl_sigwinch = 1;
>  
>       return (0);
>  }
> Index: cl/cl_main.c
> ===================================================================
> RCS file: /cvs/src/usr.bin/vi/cl/cl_main.c,v
> retrieving revision 1.33
> diff -u -p -r1.33 cl_main.c
> --- cl/cl_main.c      5 May 2016 20:36:41 -0000       1.33
> +++ cl/cl_main.c      24 Aug 2021 23:34:27 -0000
> @@ -33,6 +33,11 @@
>  
>  GS *__global_list;                           /* GLOBAL: List of screens. */
>  
> +volatile sig_atomic_t cl_sighup;
> +volatile sig_atomic_t cl_sigint;
> +volatile sig_atomic_t cl_sigterm;
> +volatile sig_atomic_t cl_sigwinch;
> +
>  static void     cl_func_std(GS *);
>  static CL_PRIVATE *cl_init(GS *);
>  static GS      *gs_init(void);
> @@ -217,16 +222,14 @@ h_hup(int signo)
>  {
>       GLOBAL_CLP;
>  
> -     F_SET(clp, CL_SIGHUP);
> +     cl_sighup = 1;
>       clp->killersig = SIGHUP;
>  }
>  
>  static void
>  h_int(int signo)
>  {
> -     GLOBAL_CLP;
> -
> -     F_SET(clp, CL_SIGINT);
> +     cl_sigint = 1;
>  }
>  
>  static void
> @@ -234,16 +237,14 @@ h_term(int signo)
>  {
>       GLOBAL_CLP;
>  
> -     F_SET(clp, CL_SIGTERM);
> +     cl_sigterm = 1;
>       clp->killersig = SIGTERM;
>  }
>  
>  static void
>  h_winch(int signo)
>  {
> -     GLOBAL_CLP;
> -
> -     F_SET(clp, CL_SIGWINCH);
> +     cl_sigwinch = 1;
>  }
>  #undef       GLOBAL_CLP
>  
> @@ -259,6 +260,11 @@ sig_init(GS *gp, SCR *sp)
>       CL_PRIVATE *clp;
>  
>       clp = GCLP(gp);
> +
> +     cl_sighup = 0;
> +     cl_sigint = 0;
> +     cl_sigterm = 0;
> +     cl_sigwinch = 0;
>  
>       if (sp == NULL) {
>               if (setsig(SIGHUP, &clp->oact[INDX_HUP], h_hup) ||
> Index: cl/cl_read.c
> ===================================================================
> RCS file: /cvs/src/usr.bin/vi/cl/cl_read.c,v
> retrieving revision 1.21
> diff -u -p -r1.21 cl_read.c
> --- cl/cl_read.c      27 May 2016 09:18:11 -0000      1.21
> +++ cl/cl_read.c      24 Aug 2021 23:34:27 -0000
> @@ -54,34 +54,32 @@ cl_event(SCR *sp, EVENT *evp, u_int32_t 
>        * so that we just keep returning them until the editor dies.
>        */
>       clp = CLP(sp);
> -retest:      if (LF_ISSET(EC_INTERRUPT) || F_ISSET(clp, CL_SIGINT)) {
> -             if (F_ISSET(clp, CL_SIGINT)) {
> -                     F_CLR(clp, CL_SIGINT);
> +retest:      if (LF_ISSET(EC_INTERRUPT) || cl_sigint) {
> +             if (cl_sigint) {
> +                     cl_sigint = 0;
>                       evp->e_event = E_INTERRUPT;
>               } else
>                       evp->e_event = E_TIMEOUT;
>               return (0);
>       }
> -     if (F_ISSET(clp, CL_SIGHUP | CL_SIGTERM | CL_SIGWINCH)) {
> -             if (F_ISSET(clp, CL_SIGHUP)) {
> -                     evp->e_event = E_SIGHUP;
> -                     return (0);
> -             }
> -             if (F_ISSET(clp, CL_SIGTERM)) {
> -                     evp->e_event = E_SIGTERM;
> +     if (cl_sighup) {
> +             evp->e_event = E_SIGHUP;
> +             return (0);
> +     }
> +     if (cl_sigterm) {
> +             evp->e_event = E_SIGTERM;
> +             return (0);
> +     }
> +     if (cl_sigwinch) {
> +             cl_sigwinch = 0;
> +             if (cl_ssize(sp, 1, &lines, &columns, &changed))
> +                     return (1);
> +             if (changed) {
> +                     (void)cl_resize(sp, lines, columns);
> +                     evp->e_event = E_WRESIZE;
>                       return (0);
>               }
> -             if (F_ISSET(clp, CL_SIGWINCH)) {
> -                     F_CLR(clp, CL_SIGWINCH);
> -                     if (cl_ssize(sp, 1, &lines, &columns, &changed))
> -                             return (1);
> -                     if (changed) {
> -                             (void)cl_resize(sp, lines, columns);
> -                             evp->e_event = E_WRESIZE;
> -                             return (0);
> -                     }
> -                     /* No real change, ignore the signal. */
> -             }
> +             /* No real change, ignore the signal. */
>       }
>  
>       /* Set timer. */

Reply via email to