Bug 629640 - Wrong open file flags result in wrong behaviour when opening un-existed file for reading
Wrong open file flags result in wrong behaviour when opening un-existed file ...
Status: CLOSED ERRATA
Product: Red Hat Enterprise Linux 6
Classification: Red Hat
Component: gdbm (Show other bugs)
6.1
All Linux
low Severity medium
: rc
: ---
Assigned To: Marek Skalický
Robin Hack
: Patch
Depends On:
Blocks: 1075802
  Show dependency treegraph
 
Reported: 2010-09-02 10:53 EDT by Jim Meyering
Modified: 2015-01-17 23:46 EST (History)
12 users (show)

See Also:
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 03:20:43 EST
Type: ---
Regression: ---
Mount Type: ---
Documentation: ---
CRM:
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---


Attachments (Terms of Use)
proposed patch used in gdbm-1.8.3 (664 bytes, patch)
2012-06-12 04:24 EDT, Honza Horak
no flags Details | Diff

  None (edit)
Description Jim Meyering 2010-09-02 10:53:38 EDT
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 11:56:38 EDT
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 Product and Program Management 2011-01-07 10:32:30 EST
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 Product and Program Management 2011-07-05 19:47:17 EDT
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 04:24:26 EDT
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 03:45:07 EDT
Updating Bug summary, since we will rather fix the particular bug instead of rebasing.
Comment 20 Marek Skalický 2014-12-10 03:43:01 EST
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 03:20:43 EST
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 03:10:53 EST
This change breaks perl test suite.
Comment 26 Honza Horak 2015-01-07 08:49:57 EST
(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 08:54:04 EST
(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 09:05:38 EST
(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 10:34:41 EST
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 10:39:37 EST
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 17:20:46 EST
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 01:26:27 EST
I reported the regression as bug #1180392.
Comment 34 Scott Dowdle 2015-01-17 23:46:05 EST
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.

Note You need to log in before you can comment on or make changes to this bug.