Bug 1180392

Summary: gdbm-1.8.0-37.el6 refuses to store into a database opened for reading and writing
Product: Red Hat Enterprise Linux 6 Reporter: Petr Pisar <ppisar>
Component: gdbmAssignee: Marek Skalický <mskalick>
Status: CLOSED ERRATA QA Contact: Robin Hack <rhack>
Severity: urgent Docs Contact:
Priority: urgent    
Version: 6.6CC: databases-maint, dowdle, fkrska, gassmann, hhorak, jkurik, lzachar, mschuppe, mskalick, nparmar, olchansk, ovasik, pasteur, psklenar, rhack, rmj, thomas.oulevey
Target Milestone: rcKeywords: Regression
Target Release: ---   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: gdbm-1.8.0-38.el6 Doc Type: Bug Fix
Doc Text:
Cause: Wrong patch applied to fix an issue when opening non-existing file in ruby. Consequence: gdbm uses wrong internal flags for file handlers and refuses to store into a database opened for reading and writing. Fix: Internal gdbm flags for file handlers are fixed. Result: gdbm stores into a database opened for reading and writing.
Story Points: ---
Clone Of:
: 1183570 (view as bug list) Environment:
Last Closed: 2015-01-27 14:54:46 UTC Type: Bug
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: 1183570, 1211527    
Attachments:
Description Flags
Fix gdbm open flags
none
Minimal patch to fix the original issue
none
reproducer for bz#1180392 none

Description Petr Pisar 2015-01-09 06:16:58 UTC
This is a standalone bug report for issue noticed in comment #25 of bug #629640.

Non-affected version: gdbm-1.8.0-36.el6
Affected version: gdbm-1.8.0-37.el6

After upgrading to gdbm-1.8.0-37.el6, this Perl code changed behaviour on x86_64:

$ 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.

This is caused by the last hunk of the gdbm patch introduced in gdbm-1.8.0-37.el6:

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 2 Petr Pisar 2015-01-09 06:23:22 UTC
This breaks perl tests suite and NIS database compilation.

Comment 4 Marek Skalický 2015-01-09 10:17:17 UTC
Created attachment 978095 [details]
Fix gdbm open flags

Comment 5 Marek Skalický 2015-01-09 10:20:29 UTC
Fix in #629640 was backported from gdbm-1.10. But there had to be changed also gdbmstore.c file.

This patch fix this bug.

Comment 8 Honza Horak 2015-01-09 15:12:54 UTC
Created attachment 978190 [details]
Minimal patch to fix the original issue

(In reply to Marek Skalický from comment #5)
> Fix in #629640 was backported from gdbm-1.10. But there had to be changed
> also gdbmstore.c file.

And also gdbmdelete.c and gdbmclose.c would need a change, but all these changes are not necessary to fix the original issue. They do not do any harm if done all together, but since we want the minimal patch, only the one-line typo corresponding with the following changelog item should actually be fixed:
* gdbmopen.c: Fix typo; s/GDBM_OPENMASK/GDBM_WRITER/

The attached patch is actually the correct fix that should have been applied as a fix for the original bug report.

Comment 13 Honza Horak 2015-01-12 09:52:53 UTC
Created attachment 979036 [details]
reproducer for bz#1180392

Steps to reproduce (use the attached file 'test_store.c':
1. #> yum install gdbm-devel
2. $> gcc -lgdbm test_store.c
3. $> ./a.out
4. $> echo $?

Actual results:
error while storing file: Success
1

Expected results:
0

Comment 18 Petr Pisar 2015-01-19 09:28:10 UTC
*** Bug 1183180 has been marked as a duplicate of this bug. ***

Comment 23 Marek Skalický 2015-01-21 07:50:37 UTC
*** Bug 1184254 has been marked as a duplicate of this bug. ***

Comment 26 errata-xmlrpc 2015-01-27 14:54:46 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-0089.html

Comment 27 Petr Pisar 2015-04-07 16:43:54 UTC
*** Bug 1209448 has been marked as a duplicate of this bug. ***