On Sun, Jul 21, 2019 at 05:57:32PM +0200, Ingo Schwarze wrote:
> Hi,
> 
> Bryan Steele wrote on Fri, Jul 19, 2019 at 06:14:56PM -0400:
> > On Sat, Jul 20, 2019 at 12:03:03AM +0200, Jesper Wallin wrote:
> >> On Fri, Jul 19, 2019 at 05:14:03PM -0400, Bryan Steele wrote:
> 
> >>> I suspect that in secure/-S mode, the :pre[serve] should either be
> >>> disabled, or modified to stop calling sendmail. The mail it is sending
> >>> is purely advisory, and should be easy to disable. See common/recover.c.
> 
> >> Oh, you're right.  A bit ironic that I didn't notice the exec violation
> >> due to the fork being permitted now.  Thanks for pointing this out!
> >> Scrap my old patch, here's a better proposal:
> 
> > ok brynet@
> 
> No, that patch is not OK either.
> 
> It breaks :pre in -S mode because rcv_mailfile() is a blantant misnomer
> that actually has two purposes:
> 1. Create the mail file to indicate that there is something recoverable
> 2. and then actually send the mail.
> 
> While step 2 must be skipped, step 1 for creating the recover.* file
> is still needed, or "vi -r" will later complain "vi: No files to recover"
> even though a vi.* file exists in /tmp/vi.recover/.  Yes, i freely
> admit that the design is horribly contorted.
> 
> So here is a better patch avoiding that problem.
> It is also safer because it is easier to see that fork(2)
> can no longer be reached.  Otherwise, you would need to understand
> that even though rcv_init() calls rcv_mailfile() and rcv_mailfile()
> calls rcv_email(), fork(2) cannot be reached in that way because
> isync is 0 in rcv_mailfile().
> 
> Yours,
>   Ingo
> 
> P.S.
> See below the patch for my analysis of the code, which you may or may
> not find helpful while verifying the patch.

Nice catch and analysis Ingo, I somehow missed that. Indeed, moving
the check into rcv_email before fork makes more sense.

Sorry for jumping the gun.

-Bryan.

> Index: common/recover.c
> ===================================================================
> RCS file: /cvs/src/usr.bin/vi/common/recover.c,v
> retrieving revision 1.29
> diff -u -p -r1.29 recover.c
> --- common/recover.c  10 Nov 2017 18:25:48 -0000      1.29
> +++ common/recover.c  21 Jul 2019 15:45:59 -0000
> @@ -821,6 +821,15 @@ rcv_email(SCR *sp, int fd)
>       struct stat sb;
>       pid_t pid;
>  
> +     /*
> +      * In secure mode, our pledge(2) includes neither "proc"
> +      * nor "exec".  So simply skip sending the mail.
> +      * Later vi -r still works because rcv_mailfile()
> +      * already did all the necessary setup.
> +      */
> +     if (O_ISSET(sp, O_SECURE))
> +             return;
> +
>       if (_PATH_SENDMAIL[0] != '/' || stat(_PATH_SENDMAIL, &sb) == -1)
>               msgq_str(sp, M_SYSERR,
>                   _PATH_SENDMAIL, "not sending email: %s");
> 
> 
> 
> There are three call paths to rcv_mailfile() and rcv_email():
> 
>  * rcv_init() -> rcv_mailfile()
>    purpose: set up .rcv_fd and .rcv_mpath
>      for locking purposes and in case of later dying from a signal
>    calls to rcv_init() are always safe because isync == 0,
>      i.e. rcv_email() is never called 
> 
>  * rcv_sync() -> rcv_email() directly
>    purpose: emergency saving while dying from SIGTERM;
>      RCV_EMAIL is not set in any other situation
>    so the direct call to rcv_email() must be neutered
>    note: RCV_SNAPSHOT is NOT set in this case
> 
>  * rcv_sync() -> rcv_mailfile() -> rcv_email()
>    purpose: manual "pre" command
>      RCV_SNAPSHOT is not set in any other situation
>    note: RCV_EMAIL is NOT set in this case
>    here, the rcv_email() inside rcv_mailfile() must be neutered
> 
> 

Reply via email to