Bug 629640

Summary: Wrong open file flags result in wrong behaviour when opening un-existed file for reading
Product: Red Hat Enterprise Linux 6 Reporter: Jim Meyering <meyering>
Component: gdbmAssignee: Marek Skalický <mskalick>
Status: CLOSED ERRATA QA Contact: Robin Hack <rhack>
Severity: medium Docs Contact:
Priority: low    
Version: 6.1CC: cww, databases-maint, dowdle, hhorak, mskalick, olchansk, ovasik, pasteur, ppisar, psklenar, rhack, rmj
Target Milestone: rcKeywords: Patch
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: gdbm-1.8.0-37.el6 Doc Type: Bug Fix
Doc Text:
Cause: Wrong open file flags. Consequence: Result in wrong behaviour when opening un-existed file for reading. Fix: Fixed file flags. Result: Opening un-existed file for reading does not create file.
Story Points: ---
Clone Of: Environment:
Last Closed: 2015-01-05 08:20:43 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On:    
Bug Blocks: 1075802    
Attachments:
Description Flags
proposed patch used in gdbm-1.8.3 none

Description Jim Meyering 2010-09-02 14:53:38 UTC
Description of problem:
gdbm-1.8.0 is 11 years old.  1.8.3 has numerous improvements and is only 9 years old, and using anything newer than 1.8.0 would avoid at least one failure in ruby's test suite: See http://bugzilla.redhat.com/602435#c50


Version-Release number of selected component (if applicable):
gdbm-1.8.0-36.el6.x86_64

How reproducible: always


Steps to Reproduce:
1. Here's a quick test to demonstrate the problem:
ruby -e 'require "gdbm"; gdbm = GDBM.open("x", nil); print gdbm'
2.
3.
  
Actual results: prints a non-nil value and creates a file named "x"


Expected results: prints "nil" and does *not* create any file


Additional info:

Comment 2 Karel Klíč 2010-09-06 15:56:38 UTC
Yes, with gdbm 1.8.3 it works as expected, and with gdmb 1.8.0 it does not.

Most flaws fixed in 1.8.3 are also fixed in our 1.8.0, and the diff between our 1.8.0 and 1.8.3 is surprisingly small. Unfortunately this particular bug remains unfixed.

Comment 3 RHEL Program Management 2011-01-07 15:32:30 UTC
This request was evaluated by Red Hat Product Management for
inclusion in the current release of Red Hat Enterprise Linux.
Because the affected component is not scheduled to be updated
in the current release, Red Hat is unfortunately unable to
address this request at this time. Red Hat invites you to
ask your support representative to propose this request, if
appropriate and relevant, in the next release of Red Hat
Enterprise Linux. If you would like it considered as an
exception in the current release, please ask your support
representative.

Comment 4 RHEL Program Management 2011-07-05 23:47:17 UTC
This request was evaluated by Red Hat Product Management for
inclusion in the current release of Red Hat Enterprise Linux.
Because the affected component is not scheduled to be updated
in the current release, Red Hat is unfortunately unable to
address this request at this time. Red Hat invites you to
ask your support representative to propose this request, if
appropriate and relevant, in the next release of Red Hat
Enterprise Linux. If you would like it considered as an
exception in the current release, please ask your support
representative.

Comment 5 Honza Horak 2012-06-12 08:24:26 UTC
Created attachment 591139 [details]
proposed patch used in gdbm-1.8.3

This fix is used in gdbm-1.8.3 and works on the reproducer above.
Related changelog comment:
* gdbmopen.c: Fix typo; s/GDBM_OPENMASK/GDBM_WRITER/.

Comment 9 Honza Horak 2013-05-29 07:45:07 UTC
Updating Bug summary, since we will rather fix the particular bug instead of rebasing.

Comment 20 Marek Skalický 2014-12-10 08:43:01 UTC
Steps to Reproduce:
1. Here's a quick test to demonstrate the problem:
ruby -e 'require "gdbm"; gdbm = GDBM.open("x", nil); print gdbm'
  
Actual results: prints a non-nil value and creates a file named "x"

Expected results: prints "nil" and does *not* create any file

Comment 24 errata-xmlrpc 2015-01-05 08:20:43 UTC
Since the problem described in this bug report should be
resolved in a recent advisory, it has been closed with a
resolution of ERRATA.

For information on the advisory, and where to find the updated
files, follow the link below.

If the solution does not work for you, open a new bug report.

https://rhn.redhat.com/errata/RHBA-2015-0005.html

Comment 25 Petr Pisar 2015-01-07 08:10:53 UTC
This change breaks perl test suite.

Comment 26 Honza Horak 2015-01-07 13:49:57 UTC
(In reply to Petr Pisar from comment #25)
> This change breaks perl test suite.

Can you be more specific?

Comment 27 Petr Pisar 2015-01-07 13:54:04 UTC
(In reply to Honza Horak from comment #26)
> (In reply to Petr Pisar from comment #25)
> > This change breaks perl test suite.
> 
> Can you be more specific?

I have not yet investigated it. Rebuilding perl fails with gdbm-1.8.0-37.el6 on x86_64 only. It passes with gdbm-1.8.0-36.el6.

Comment 28 Honza Horak 2015-01-07 14:05:38 UTC
(In reply to Petr Pisar from comment #27)
> I have not yet investigated it. Rebuilding perl fails with gdbm-1.8.0-37.el6
> on x86_64 only. It passes with gdbm-1.8.0-36.el6.

Please, give us know as soon as you find out more. Thanks.

Comment 29 Petr Pisar 2015-01-07 15:34:41 UTC
This Perl code changed behaviour:

$ cat gdbmfix 
#!/usr/bin/perl
use strict;
use warnings;
use GDBM_File;

unlink <Op.dbmx*>;
my %h;
tie(%h, 'GDBM_File', 'Op.dbmx', &GDBM_WRCREAT, 0640)
        or die "Initialization failed";
$h{'goner1'} = 'snork';
untie(%h);

$ ./gdbmfix 
gdbm store returned -1, errno 0, key "goner1" at ./gdbmfix line 10.

The failed line 10 is the "$h{'goner1'} = 'snork';" line. I debugged the gdbm library and the -1 comes from this check at the very beginning of gdbm_store():

  /* First check to make sure this guy is a writer. */
  if (dbf->read_write != GDBM_WRITER)
    {
      gdbm_errno = GDBM_READER_CANT_STORE;
      return -1;
    }

Debugger show that the dbf->read_write holds value 2 while GDBM_WRITER macro is declared as 1.

It looks like the gdbm_open() does not set the database handle is opened for writing:

When calling gdbm_open():

Breakpoint 1, gdbm_open (file=0x63f1f0 "Op.dbmx", block_size=0, flags=2, mode=416, fatal_func=0x7ffff7d25420 <Perl_croak_nocontext>) at gdbmopen.c:76

When leaving the gdbm_open():

Breakpoint 2, gdbm_open (file=0x63f1f0 "Op.dbmx", block_size=0, flags=2, mode=416, fatal_func=0x7ffff7d25420 <Perl_croak_nocontext>) at gdbmopen.c:398
398       return dbf;
(gdb) p *dbf
$6 = {name = 0x62d090 "Op.dbmx", read_write = 2, fast_write = 1, central_free = 0, coalesce_blocks = 0, file_locking = 1, fatal_err = 0x7ffff7d25420 <Perl_croak_nocontext>, desc = 7, 
  header = 0x62a8f0, dir = 0x69b720, bucket_cache = 0x0, cache_size = 0, last_read = -1, bucket = 0x0, bucket_dir = 0, cache_entry = 0x0, header_changed = 0 '\000', 
  directory_changed = 0 '\000', bucket_changed = 0 '\000', second_changed = 0 '\000'}

The flags=2 is GDBM_WRCREAT which corresponds to the Perl code.

Comment 30 Petr Pisar 2015-01-07 15:39:37 UTC
This is caused by the last hunk of the gdbm patch:

diff -up gdbm-1.8.0/gdbmopen.c.gdbmopen gdbm-1.8.0/gdbmopen.c
--- gdbm-1.8.0/gdbmopen.c.gdbmopen  2012-06-12 10:08:02.853499099 +0200
+++ gdbm-1.8.0/gdbmopen.c   2012-06-12 10:08:13.620769745 +0200
@@ -129,19 +129,17 @@ gdbm_open (file, block_size, flags, mode
    dbf->desc = open (dbf->name, O_RDONLY, 0);
    break;

-      case GDBM_OPENMASK:
+      case GDBM_WRITER:
    dbf->desc = open (dbf->name, O_RDWR, 0);
    break;

       case GDBM_NEWDB:
    dbf->desc = open (dbf->name, O_RDWR|O_CREAT, mode);
-   flags = GDBM_WRITER;
    need_trunc = TRUE;
    break;

       default:
    dbf->desc = open (dbf->name, O_RDWR|O_CREAT, mode);
-   flags = GDBM_WRITER; ← THIS IS MISSING
    break;

Comment 31 Konstantin Olchanski 2015-01-07 22:20:46 UTC
This update breaks NIS:

[root@ladd00 LADD-NIS]# rpm -q gdbm
gdbm-1.8.0-37.el6.x86_64
[root@ladd00 LADD-NIS]# make -C /var/yp
make: Entering directory `/var/yp'
...
gmake[1]: Entering directory `/var/yp/LADD-NIS'
Updating auto.daq...
makedbm: dbm_store: Success
gmake[1]: [auto.daq] Error 1 (ignored)
...
[root@ladd00 LADD-NIS]# ls -l /var/yp/LADD-NIS
total 268
-rw------- 1 root root 12481 Jan  7 14:11 auto.daq
-rw------- 1 root root 12288 Jan  7 14:18 auto.daq~
...
(observe how file auto.daq is not updated, auto.daq~ is left behind instead)

K.O.

Comment 33 Petr Pisar 2015-01-09 06:26:27 UTC
I reported the regression as bug #1180392.

Comment 34 Scott Dowdle 2015-01-18 04:46:05 UTC
I concur.  I opened up bug 1183180 prior to finding this... and yes since reverting back to gdbm-devel-1.8.0-36.el6.x86_64.rpm ypserv (specifically tools like ypinit and makedbm) works again.  With this update, ypserv breaks because it can no longer update it's data in /var/yp/{domain}.

This is serious breakage for anyone using ypserv.