Re: rpki-client: check fflush on output files

2020-03-09 Thread Theo de Raadt
Jeremie Courreges-Anglas  wrote:

Lovely!

> Agreed.  Here's an updated diff that tests the return value of
> output_finish().  Suggestions welcome for the error message in this
> case.
> 
> It also drops the extra "out = NULL;", and replaces logx() calls with
> warn(3) in this file.  I see no reason to drop those messages and errno
> information.  logx() seems used mostly for statistics.
> 
> Thoughts, tests / oks?
> 
> 
> Index: extern.h
> ===
> RCS file: /d/cvs/src/usr.sbin/rpki-client/extern.h,v
> retrieving revision 1.24
> diff -u -p -r1.24 extern.h
> --- extern.h  6 Mar 2020 17:36:42 -   1.24
> +++ extern.h  9 Mar 2020 08:19:20 -
> @@ -372,7 +372,7 @@ extern char*   outputdir;
>  int   outputfiles(struct vrp_tree *v);
>  FILE *output_createtmp(char *);
>  void  output_cleantmp(void);
> -void  output_finish(FILE *);
> +int   output_finish(FILE *);
>  int   output_bgpd(FILE *, struct vrp_tree *);
>  int   output_bird1v4(FILE *, struct vrp_tree *);
>  int   output_bird1v6(FILE *, struct vrp_tree *);
> Index: output.c
> ===
> RCS file: /d/cvs/src/usr.sbin/rpki-client/output.c,v
> retrieving revision 1.6
> diff -u -p -r1.6 output.c
> --- output.c  6 Mar 2020 17:36:42 -   1.6
> +++ output.c  9 Mar 2020 08:20:39 -
> @@ -67,18 +67,23 @@ outputfiles(struct vrp_tree *v)
>  
>   fout = output_createtmp(outputs[i].name);
>   if (fout == NULL) {
> - logx("cannot create %s", outputs[i].name);
> + warn("cannot create %s", outputs[i].name);
>   rc = 1;
>   continue;
>   }
>   if ((*outputs[i].fn)(fout, v) != 0) {
> - logx("output for %s format failed", outputs[i].name);
> + warn("output for %s format failed", outputs[i].name);
>   fclose(fout);
>   output_cleantmp();
>   rc = 1;
>   continue;
>   }
> - output_finish(fout);
> + if (output_finish(fout) != 0) {
> + warn("finish for %s format failed", outputs[i].name);
> + output_cleantmp();
> + rc = 1;
> + continue;
> + }
>   }
>  
>   return rc;
> @@ -108,14 +113,15 @@ output_createtmp(char *name)
>   return f;
>  }
>  
> -void
> +int
>  output_finish(FILE *out)
>  {
> - fclose(out);
> - out = NULL;
> -
> - rename(output_tmpname, output_name);
> + if (fclose(out) != 0)
> + return -1;
> + if (rename(output_tmpname, output_name) == -1)
> + return -1;
>   output_tmpname[0] = '\0';
> + return 0;
>  }
>  
>  void



Re: rpki-client: check fflush on output files

2020-03-09 Thread Claudio Jeker
On Mon, Mar 09, 2020 at 09:41:37AM +0100, Jeremie Courreges-Anglas wrote:
> On Sat, Mar 07 2020, Claudio Jeker  wrote:
> > On Sat, Mar 07, 2020 at 08:35:39AM +0100, Jeremie Courreges-Anglas wrote:
> >> On Fri, Mar 06 2020, "Theo de Raadt"  wrote:
> >> >> Jeremie Courreges-Anglas  wrote:
> >> >> > 
> >> >> > 
> >> >> > Checking the return value of fprintf is good but not enough to ensure
> >> >> > that data has properly been written to the file without an error.  To 
> >> >> > do
> >> >> > that we can use fflush(3) in a single place.
> >> [redacted]
> >> >> How about checking the return value of fclose() in output_finish() 
> >> >> instead?
> >> > Oh you want to reach the error-reporting code...
> >> 
> >> And the cleanup-on-error code.  Doing it here looks more appealing than
> >> adding
> >>if (fflush(out) != 0)
> >>return -1;
> >> 
> >> at the end of all the output_* functions.
> >> 
> >> If you're careful about write errors you can avoid feeding an
> >> incomplete/garbage file to your BGP daemon.  The code was already
> >> careful, but did not account for buffering.  This is what this patch
> >> tries to address.
> >> 
> >> >> > Build-tested only.  ok?
> >> >> > 
> >> >> > Bonus: in output_finish(), "out = NULL;" is pointless, so zap it.
> >> >> > I suspect it's a remnant from a time where the output FILE * was
> >> >> > a global.  That would be a separate commit.
> >> 
> >> Diff below again for convenience,
> >> 
> >> 
> >> Index: output.c
> >> ===
> >> RCS file: /d/cvs/src/usr.sbin/rpki-client/output.c,v
> >> retrieving revision 1.6
> >> diff -u -p -p -u -r1.6 output.c
> >> --- output.c   6 Mar 2020 17:36:42 -   1.6
> >> +++ output.c   6 Mar 2020 23:04:18 -
> >> @@ -71,7 +71,7 @@ outputfiles(struct vrp_tree *v)
> >>rc = 1;
> >>continue;
> >>}
> >> -  if ((*outputs[i].fn)(fout, v) != 0) {
> >> +  if ((*outputs[i].fn)(fout, v) != 0 || fflush(fout) != 0) {
> >>logx("output for %s format failed", outputs[i].name);
> >>fclose(fout);
> >>output_cleantmp();
> >> @@ -112,8 +112,6 @@ void
> >>  output_finish(FILE *out)
> >>  {
> >>fclose(out);
> >> -  out = NULL;
> >> -
> >>rename(output_tmpname, output_name);
> >>output_tmpname[0] = '\0';
> >>  }
> >> 
> >
> > I think it would be better to pick up the fclose error in output_finish()
> > and while doing that also check for rename() errors. At least those errors
> > should be logged.
> 
> Agreed.  Here's an updated diff that tests the return value of
> output_finish().  Suggestions welcome for the error message in this
> case.
> 
> It also drops the extra "out = NULL;", and replaces logx() calls with
> warn(3) in this file.  I see no reason to drop those messages and errno
> information.  logx() seems used mostly for statistics.
> 
> Thoughts, tests / oks?

Works for me. Ok claudio@

PS: I think some of the output_* prototypes could be moved to output.c
since those functions are only used internally.
 
> Index: extern.h
> ===
> RCS file: /d/cvs/src/usr.sbin/rpki-client/extern.h,v
> retrieving revision 1.24
> diff -u -p -r1.24 extern.h
> --- extern.h  6 Mar 2020 17:36:42 -   1.24
> +++ extern.h  9 Mar 2020 08:19:20 -
> @@ -372,7 +372,7 @@ extern char*   outputdir;
>  int   outputfiles(struct vrp_tree *v);
>  FILE *output_createtmp(char *);
>  void  output_cleantmp(void);
> -void  output_finish(FILE *);
> +int   output_finish(FILE *);
>  int   output_bgpd(FILE *, struct vrp_tree *);
>  int   output_bird1v4(FILE *, struct vrp_tree *);
>  int   output_bird1v6(FILE *, struct vrp_tree *);
> Index: output.c
> ===
> RCS file: /d/cvs/src/usr.sbin/rpki-client/output.c,v
> retrieving revision 1.6
> diff -u -p -r1.6 output.c
> --- output.c  6 Mar 2020 17:36:42 -   1.6
> +++ output.c  9 Mar 2020 08:20:39 -
> @@ -67,18 +67,23 @@ outputfiles(struct vrp_tree *v)
>  
>   fout = output_createtmp(outputs[i].name);
>   if (fout == NULL) {
> - logx("cannot create %s", outputs[i].name);
> + warn("cannot create %s", outputs[i].name);
>   rc = 1;
>   continue;
>   }
>   if ((*outputs[i].fn)(fout, v) != 0) {
> - logx("output for %s format failed", outputs[i].name);
> + warn("output for %s format failed", outputs[i].name);
>   fclose(fout);
>   output_cleantmp();
>   rc = 1;
>   continue;
>   }
> - output_finish(fout);
> + if (output_finish(fout) != 0) {
> 

Re: rpki-client: check fflush on output files

2020-03-09 Thread Jeremie Courreges-Anglas
On Sat, Mar 07 2020, Claudio Jeker  wrote:
> On Sat, Mar 07, 2020 at 08:35:39AM +0100, Jeremie Courreges-Anglas wrote:
>> On Fri, Mar 06 2020, "Theo de Raadt"  wrote:
>> >> Jeremie Courreges-Anglas  wrote:
>> >> > 
>> >> > 
>> >> > Checking the return value of fprintf is good but not enough to ensure
>> >> > that data has properly been written to the file without an error.  To do
>> >> > that we can use fflush(3) in a single place.
>> [redacted]
>> >> How about checking the return value of fclose() in output_finish() 
>> >> instead?
>> > Oh you want to reach the error-reporting code...
>> 
>> And the cleanup-on-error code.  Doing it here looks more appealing than
>> adding
>>  if (fflush(out) != 0)
>>  return -1;
>> 
>> at the end of all the output_* functions.
>> 
>> If you're careful about write errors you can avoid feeding an
>> incomplete/garbage file to your BGP daemon.  The code was already
>> careful, but did not account for buffering.  This is what this patch
>> tries to address.
>> 
>> >> > Build-tested only.  ok?
>> >> > 
>> >> > Bonus: in output_finish(), "out = NULL;" is pointless, so zap it.
>> >> > I suspect it's a remnant from a time where the output FILE * was
>> >> > a global.  That would be a separate commit.
>> 
>> Diff below again for convenience,
>> 
>> 
>> Index: output.c
>> ===
>> RCS file: /d/cvs/src/usr.sbin/rpki-client/output.c,v
>> retrieving revision 1.6
>> diff -u -p -p -u -r1.6 output.c
>> --- output.c 6 Mar 2020 17:36:42 -   1.6
>> +++ output.c 6 Mar 2020 23:04:18 -
>> @@ -71,7 +71,7 @@ outputfiles(struct vrp_tree *v)
>>  rc = 1;
>>  continue;
>>  }
>> -if ((*outputs[i].fn)(fout, v) != 0) {
>> +if ((*outputs[i].fn)(fout, v) != 0 || fflush(fout) != 0) {
>>  logx("output for %s format failed", outputs[i].name);
>>  fclose(fout);
>>  output_cleantmp();
>> @@ -112,8 +112,6 @@ void
>>  output_finish(FILE *out)
>>  {
>>  fclose(out);
>> -out = NULL;
>> -
>>  rename(output_tmpname, output_name);
>>  output_tmpname[0] = '\0';
>>  }
>> 
>
> I think it would be better to pick up the fclose error in output_finish()
> and while doing that also check for rename() errors. At least those errors
> should be logged.

Agreed.  Here's an updated diff that tests the return value of
output_finish().  Suggestions welcome for the error message in this
case.

It also drops the extra "out = NULL;", and replaces logx() calls with
warn(3) in this file.  I see no reason to drop those messages and errno
information.  logx() seems used mostly for statistics.

Thoughts, tests / oks?


Index: extern.h
===
RCS file: /d/cvs/src/usr.sbin/rpki-client/extern.h,v
retrieving revision 1.24
diff -u -p -r1.24 extern.h
--- extern.h6 Mar 2020 17:36:42 -   1.24
+++ extern.h9 Mar 2020 08:19:20 -
@@ -372,7 +372,7 @@ extern char* outputdir;
 int outputfiles(struct vrp_tree *v);
 FILE   *output_createtmp(char *);
 voidoutput_cleantmp(void);
-voidoutput_finish(FILE *);
+int output_finish(FILE *);
 int output_bgpd(FILE *, struct vrp_tree *);
 int output_bird1v4(FILE *, struct vrp_tree *);
 int output_bird1v6(FILE *, struct vrp_tree *);
Index: output.c
===
RCS file: /d/cvs/src/usr.sbin/rpki-client/output.c,v
retrieving revision 1.6
diff -u -p -r1.6 output.c
--- output.c6 Mar 2020 17:36:42 -   1.6
+++ output.c9 Mar 2020 08:20:39 -
@@ -67,18 +67,23 @@ outputfiles(struct vrp_tree *v)
 
fout = output_createtmp(outputs[i].name);
if (fout == NULL) {
-   logx("cannot create %s", outputs[i].name);
+   warn("cannot create %s", outputs[i].name);
rc = 1;
continue;
}
if ((*outputs[i].fn)(fout, v) != 0) {
-   logx("output for %s format failed", outputs[i].name);
+   warn("output for %s format failed", outputs[i].name);
fclose(fout);
output_cleantmp();
rc = 1;
continue;
}
-   output_finish(fout);
+   if (output_finish(fout) != 0) {
+   warn("finish for %s format failed", outputs[i].name);
+   output_cleantmp();
+   rc = 1;
+   continue;
+   }
}
 
return rc;
@@ -108,14 +113,15 @@ output_createtmp(char *name)
return f;
 }
 
-void
+int
 output_finish(FILE *out)
 {
-   fclose(out);
-   out = NULL;
-

Re: rpki-client: check fflush on output files

2020-03-07 Thread Claudio Jeker
On Sat, Mar 07, 2020 at 08:35:39AM +0100, Jeremie Courreges-Anglas wrote:
> On Fri, Mar 06 2020, "Theo de Raadt"  wrote:
> >> Jeremie Courreges-Anglas  wrote:
> >> > 
> >> > 
> >> > Checking the return value of fprintf is good but not enough to ensure
> >> > that data has properly been written to the file without an error.  To do
> >> > that we can use fflush(3) in a single place.
> [redacted]
> >> How about checking the return value of fclose() in output_finish() instead?
> > Oh you want to reach the error-reporting code...
> 
> And the cleanup-on-error code.  Doing it here looks more appealing than
> adding
>   if (fflush(out) != 0)
>   return -1;
> 
> at the end of all the output_* functions.
> 
> If you're careful about write errors you can avoid feeding an
> incomplete/garbage file to your BGP daemon.  The code was already
> careful, but did not account for buffering.  This is what this patch
> tries to address.
> 
> >> > Build-tested only.  ok?
> >> > 
> >> > Bonus: in output_finish(), "out = NULL;" is pointless, so zap it.
> >> > I suspect it's a remnant from a time where the output FILE * was
> >> > a global.  That would be a separate commit.
> 
> Diff below again for convenience,
> 
> 
> Index: output.c
> ===
> RCS file: /d/cvs/src/usr.sbin/rpki-client/output.c,v
> retrieving revision 1.6
> diff -u -p -p -u -r1.6 output.c
> --- output.c  6 Mar 2020 17:36:42 -   1.6
> +++ output.c  6 Mar 2020 23:04:18 -
> @@ -71,7 +71,7 @@ outputfiles(struct vrp_tree *v)
>   rc = 1;
>   continue;
>   }
> - if ((*outputs[i].fn)(fout, v) != 0) {
> + if ((*outputs[i].fn)(fout, v) != 0 || fflush(fout) != 0) {
>   logx("output for %s format failed", outputs[i].name);
>   fclose(fout);
>   output_cleantmp();
> @@ -112,8 +112,6 @@ void
>  output_finish(FILE *out)
>  {
>   fclose(out);
> - out = NULL;
> -
>   rename(output_tmpname, output_name);
>   output_tmpname[0] = '\0';
>  }
> 

I think it would be better to pick up the fclose error in output_finish()
and while doing that also check for rename() errors. At least those errors
should be logged.

-- 
:wq Claudio



Re: rpki-client: check fflush on output files

2020-03-06 Thread Jeremie Courreges-Anglas
On Fri, Mar 06 2020, "Theo de Raadt"  wrote:
>> Jeremie Courreges-Anglas  wrote:
>> > 
>> > 
>> > Checking the return value of fprintf is good but not enough to ensure
>> > that data has properly been written to the file without an error.  To do
>> > that we can use fflush(3) in a single place.
[redacted]
>> How about checking the return value of fclose() in output_finish() instead?
> Oh you want to reach the error-reporting code...

And the cleanup-on-error code.  Doing it here looks more appealing than
adding
if (fflush(out) != 0)
return -1;

at the end of all the output_* functions.

If you're careful about write errors you can avoid feeding an
incomplete/garbage file to your BGP daemon.  The code was already
careful, but did not account for buffering.  This is what this patch
tries to address.

>> > Build-tested only.  ok?
>> > 
>> > Bonus: in output_finish(), "out = NULL;" is pointless, so zap it.
>> > I suspect it's a remnant from a time where the output FILE * was
>> > a global.  That would be a separate commit.

Diff below again for convenience,


Index: output.c
===
RCS file: /d/cvs/src/usr.sbin/rpki-client/output.c,v
retrieving revision 1.6
diff -u -p -p -u -r1.6 output.c
--- output.c6 Mar 2020 17:36:42 -   1.6
+++ output.c6 Mar 2020 23:04:18 -
@@ -71,7 +71,7 @@ outputfiles(struct vrp_tree *v)
rc = 1;
continue;
}
-   if ((*outputs[i].fn)(fout, v) != 0) {
+   if ((*outputs[i].fn)(fout, v) != 0 || fflush(fout) != 0) {
logx("output for %s format failed", outputs[i].name);
fclose(fout);
output_cleantmp();
@@ -112,8 +112,6 @@ void
 output_finish(FILE *out)
 {
fclose(out);
-   out = NULL;
-
rename(output_tmpname, output_name);
output_tmpname[0] = '\0';
 }


-- 
jca | PGP : 0x1524E7EE / 5135 92C1 AD36 5293 2BDF  DDCC 0DFA 74AE 1524 E7EE



Re: rpki-client: check fflush on output files

2020-03-06 Thread Theo de Raadt
Oh you want to reach the error-reporting code...

> How about checking the return value of fclose() in output_finish() instead?
> 
> Jeremie Courreges-Anglas  wrote:
> > 
> > 
> > Checking the return value of fprintf is good but not enough to ensure
> > that data has properly been written to the file without an error.  To do
> > that we can use fflush(3) in a single place.
> > 
> > Build-tested only.  ok?
> > 
> > Bonus: in output_finish(), "out = NULL;" is pointless, so zap it.
> > I suspect it's a remnant from a time where the output FILE * was
> > a global.  That would be a separate commit.
> > 
> > 
> > Index: output.c
> > ===
> > RCS file: /d/cvs/src/usr.sbin/rpki-client/output.c,v
> > retrieving revision 1.6
> > diff -u -p -p -u -r1.6 output.c
> > --- output.c6 Mar 2020 17:36:42 -   1.6
> > +++ output.c6 Mar 2020 19:09:13 -
> > @@ -71,7 +71,7 @@ outputfiles(struct vrp_tree *v)
> > rc = 1;
> > continue;
> > }
> > -   if ((*outputs[i].fn)(fout, v) != 0) {
> > +   if ((*outputs[i].fn)(fout, v) != 0 || fflush(fout) != 0) {
> > logx("output for %s format failed", outputs[i].name);
> > fclose(fout);
> > output_cleantmp();
> > @@ -112,8 +112,6 @@ void
> >  output_finish(FILE *out)
> >  {
> > fclose(out);
> > -   out = NULL;
> > -
> > rename(output_tmpname, output_name);
> > output_tmpname[0] = '\0';
> >  }
> > 
> > 
> > 
> > -- 
> > jca | PGP : 0x1524E7EE / 5135 92C1 AD36 5293 2BDF  DDCC 0DFA 74AE 1524 E7EE
> > 
> 



Re: rpki-client: check fflush on output files

2020-03-06 Thread Theo de Raadt
How about checking the return value of fclose() in output_finish() instead?

Jeremie Courreges-Anglas  wrote:
> 
> 
> Checking the return value of fprintf is good but not enough to ensure
> that data has properly been written to the file without an error.  To do
> that we can use fflush(3) in a single place.
> 
> Build-tested only.  ok?
> 
> Bonus: in output_finish(), "out = NULL;" is pointless, so zap it.
> I suspect it's a remnant from a time where the output FILE * was
> a global.  That would be a separate commit.
> 
> 
> Index: output.c
> ===
> RCS file: /d/cvs/src/usr.sbin/rpki-client/output.c,v
> retrieving revision 1.6
> diff -u -p -p -u -r1.6 output.c
> --- output.c  6 Mar 2020 17:36:42 -   1.6
> +++ output.c  6 Mar 2020 19:09:13 -
> @@ -71,7 +71,7 @@ outputfiles(struct vrp_tree *v)
>   rc = 1;
>   continue;
>   }
> - if ((*outputs[i].fn)(fout, v) != 0) {
> + if ((*outputs[i].fn)(fout, v) != 0 || fflush(fout) != 0) {
>   logx("output for %s format failed", outputs[i].name);
>   fclose(fout);
>   output_cleantmp();
> @@ -112,8 +112,6 @@ void
>  output_finish(FILE *out)
>  {
>   fclose(out);
> - out = NULL;
> -
>   rename(output_tmpname, output_name);
>   output_tmpname[0] = '\0';
>  }
> 
> 
> 
> -- 
> jca | PGP : 0x1524E7EE / 5135 92C1 AD36 5293 2BDF  DDCC 0DFA 74AE 1524 E7EE
> 



rpki-client: check fflush on output files

2020-03-06 Thread Jeremie Courreges-Anglas


Checking the return value of fprintf is good but not enough to ensure
that data has properly been written to the file without an error.  To do
that we can use fflush(3) in a single place.

Build-tested only.  ok?

Bonus: in output_finish(), "out = NULL;" is pointless, so zap it.
I suspect it's a remnant from a time where the output FILE * was
a global.  That would be a separate commit.


Index: output.c
===
RCS file: /d/cvs/src/usr.sbin/rpki-client/output.c,v
retrieving revision 1.6
diff -u -p -p -u -r1.6 output.c
--- output.c6 Mar 2020 17:36:42 -   1.6
+++ output.c6 Mar 2020 19:09:13 -
@@ -71,7 +71,7 @@ outputfiles(struct vrp_tree *v)
rc = 1;
continue;
}
-   if ((*outputs[i].fn)(fout, v) != 0) {
+   if ((*outputs[i].fn)(fout, v) != 0 || fflush(fout) != 0) {
logx("output for %s format failed", outputs[i].name);
fclose(fout);
output_cleantmp();
@@ -112,8 +112,6 @@ void
 output_finish(FILE *out)
 {
fclose(out);
-   out = NULL;
-
rename(output_tmpname, output_name);
output_tmpname[0] = '\0';
 }



-- 
jca | PGP : 0x1524E7EE / 5135 92C1 AD36 5293 2BDF  DDCC 0DFA 74AE 1524 E7EE