#48665 Segfault in ldbm_instance_modify_config_entry
Closed: Fixed None Opened 3 years ago by firstyear.

Triggered during development of #48383. python ldap attempted this mod:

data; {'nsslapd-directory': ['/opt/dirsrv/var/lib/dirsrv/slapd-localhost/db/userRoot'], 'cn': ['userRoot'], 'objectclass': ['top', 'extensibleObject', 'nsBackendInstance'], 'nsslapd-require-index': ['off'], 'nsslapd-suffix': ['dc=example,dc=com'], 'nsslapd-readonly': ['off'], 'nsslapd-dncachememsize': ['10485760'], 'nsslapd-cachesize': ['-1'], 'nsslapd-cachememsize': ['1']}
original data: {'nsslapd-directory': ['/opt/dirsrv/var/lib/dirsrv/slapd-localhost/db/userRoot'], 'cn': ['userRoot'], 'objectclass': ['top', 'extensibleObject', 'nsBackendInstance'], 'nsslapd-require-index': ['off'], 'nsslapd-suffix': ['dc=example,dc=com'], 'nsslapd-readonly': ['off'], 'nsslapd-dncachememsize': ['10485760'], 'nsslapd-cachesize': ['-1'], 'nsslapd-cachememsize': ['10485760']}

mod :[(1, 'nsslapd-cachememsize', None), (0, 'nsslapd-cachememsize', ['1'])]

It looks like if you pass a None, or NULL to certain parts of the config modification code you can completely kill Directory Server.

(gdb) bt
#0  0x00007fffea0ef396 in ldbm_instance_modify_config_entry_callback (pb=<optimized out>, 
    entryBefore=<optimized out>, e=<optimized out>, returncode=0x7fffdce0c690, 
    returntext=0x7fffdce0c8d0 "", arg=0x602e00006d00)
    at /home/wibrown/development/389ds/ds/ldap/servers/slapd/back-ldbm/ldbm_instance_config.c:803
#1  0x00007ffff49e05b1 in dse_call_callback (pb=pb@entry=0x7fffdce11a80, 
    operation=operation@entry=8, flags=flags@entry=1, 
    entryBefore=entryBefore@entry=0x60200046fa40, 
    entryAfter=entryAfter@entry=0x60200046f840, returncode=returncode@entry=0x7fffdce0c690, 
    returntext=returntext@entry=0x7fffdce0c8d0 "", pdse=<optimized out>)
    at /home/wibrown/development/389ds/ds/ldap/servers/slapd/dse.c:2634
#2  0x00007ffff49e4765 in dse_modify (pb=0x7fffdce11a80)
    at /home/wibrown/development/389ds/ds/ldap/servers/slapd/dse.c:1852
#3  0x00007ffff4a52733 in op_shared_modify (pb=pb@entry=0x7fffdce11a80, 
    pw_change=pw_change@entry=0, old_pw=0x0)
    at /home/wibrown/development/389ds/ds/ldap/servers/slapd/modify.c:1054
#4  0x00007ffff4a5527e in do_modify (pb=pb@entry=0x7fffdce11a80)
    at /home/wibrown/development/389ds/ds/ldap/servers/slapd/modify.c:387
#5  0x0000000000426ab3 in connection_dispatch_operation (pb=0x7fffdce11a80, 
    op=0x602e000243a0, conn=0x7fffe0847200)
    at /home/wibrown/development/389ds/ds/ldap/servers/slapd/connection.c:627
#6  connection_threadmain ()
    at /home/wibrown/development/389ds/ds/ldap/servers/slapd/connection.c:1759
#7  0x00007ffff25477bb in _pt_root (arg=0x6026000670e0)
    at ../../../nspr/pr/src/pthreads/ptthread.c:212
#8  0x00007ffff4e64a98 in __asan::AsanThread::ThreadStart (this=0x7fffdce14000)
    at ../../../../libsanitizer/asan/asan_thread.cc:99
#9  0x00007ffff1ee8dc5 in start_thread (arg=0x7fffdce12700) at pthread_create.c:308
#10 0x00007ffff1c1621d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:113
(gdb) list
798             if (ldbm_config_ignored_attr(attr_name)) {
799                 continue;
800             }
801 
802         /* This assumes there is only one bval for this mod. */
803             rc = ldbm_config_set((void *) inst, attr_name,
804                 ldbm_instance_config, mods[i]->mod_bvalues[0], returntext,
805                 CONFIG_PHASE_RUNNING, apply_mod, mods[i]->mod_op);
806         }
807     }
(gdb) 
(gdb) print *inst
$3 = {inst_name = 0x6004002c20b0 "userRoot", inst_be = 0x6022001359a0, 
  inst_li = 0x602800012040, inst_flags = 0, inst_config_mutex = 0x601e00110d40, 
  inst_ref_count = 0x6004002c1fd0, inst_dir_name = 0x6004002c1190 "userRoot", 
  inst_parent_dir_name = 0x60080007f810 "/opt/dirsrv/var/lib/dirsrv/slapd-localhost/db", 
  inst_db_mutex = 0x601e00110e30, inst_handle_head = 0x600600511ae0, 
  inst_handle_tail = 0x600600545110, inst_handle_list_mutex = 0x601e00110f20, 
  inst_id2entry = 0x604a00007580, inst_perf_private = {memory = 0x0}, 
  inst_attrcrypt_state_private = 0x0, attrcrypt_configured = 0, 
  inst_attrs = 0x6006004b4360, inst_cache = {c_maxsize = 10485760, 
    c_cursize = 0x6004002c2090, c_maxentries = -1, c_curentries = 2, 
    c_dntable = 0x7fffe6e3f800, c_idtable = 0x7fffe6e14800, c_hits = 0x6004002c2070, 
    c_tries = 0x6004002c2050, c_lruhead = 0x60100001f5a0, c_lrutail = 0x60100001a320, 
    c_mutex = 0x601e001112e0, c_emutexalloc_mutex = 0x601e001111f0}, 
  inst_nextid_mutex = 0x601e00110c50, inst_nextid = 10, inst_indexer_cv = 0x600c0014e700, 
  inst_indexer_tid = 0x0, inst_cache_hits = 0, inst_cache_misses = 0, 
  inst_dataversion = 0x0, import_env = 0x0, require_index = 0, inst_dncache = {
    c_maxsize = 10485760, c_cursize = 0x6004002c2030, c_maxentries = -1, c_curentries = 2, 
    c_dntable = 0x0, c_idtable = 0x7fffe6de9800, c_hits = 0x6004002c2010, 
    c_tries = 0x6004002c1ff0, c_lruhead = 0x600c001a9240, c_lrutail = 0x600c00197c00, 
    c_mutex = 0x601e00111100, c_emutexalloc_mutex = 0x601e00111010}}
(gdb) print attr_name
$2 = 0x60060085ad40 "nsslapd-cachememsize"
(gdb) print ldbm_instance_config
$4 = {{config_name = 0x7fffea18abe0 "nsslapd-cachesize", config_type = 4, 
    config_default_value = 0x7fffea18ac20 "-1", 
    config_get_fn = 0x7fffea0edb30 <ldbm_instance_config_cachesize_get>, 
    config_set_fn = 0x7fffea0edb00 <ldbm_instance_config_cachesize_set>, config_flags = 7}, 
  {config_name = 0x7fffea18ac60 "nsslapd-cachememsize", config_type = 6, 
    config_default_value = 0x7fffea18aca0 "10485760", 
    config_get_fn = 0x7fffea0ed9b0 <ldbm_instance_config_cachememsize_get>, 
    config_set_fn = 0x7fffea0ee250 <ldbm_instance_config_cachememsize_set>, 
    config_flags = 7}, {config_name = 0x7fffea18ace0 "nsslapd-readonly", config_type = 1, 
    config_default_value = 0x7fffea18ad20 "off", 
    config_get_fn = 0x7fffea0ed870 <ldbm_instance_config_readonly_get>, 
    config_set_fn = 0x7fffea0ed9d0 <ldbm_instance_config_readonly_set>, config_flags = 7}, {
    config_name = 0x7fffea18ad60 "nsslapd-require-index", config_type = 1, 
    config_default_value = 0x7fffea18ad20 "off", 
    config_get_fn = 0x7fffea0ed8d0 <ldbm_instance_config_require_index_get>, 
    config_set_fn = 0x7fffea0ed910 <ldbm_instance_config_require_index_set>, 
    config_flags = 7}, {config_name = 0x7fffea18ada0 "nsslapd-directory", config_type = 2, 
    config_default_value = 0x0, 
    config_get_fn = 0x7fffea0ee5f0 <ldbm_instance_config_instance_dir_get>, 
    config_set_fn = 0x7fffea0ee3a0 <ldbm_instance_config_instance_dir_set>, 
    config_flags = 3}, {config_name = 0x7fffea18ade0 "nsslapd-dncachememsize", 
    config_type = 6, config_default_value = 0x7fffea18aca0 "10485760", 
    config_get_fn = 0x7fffea0ed990 <ldbm_instance_config_dncachememsize_get>, 
    config_set_fn = 0x7fffea0ee100 <ldbm_instance_config_dncachememsize_set>, 
    config_flags = 7}, {config_name = 0x0, config_type = 0, config_default_value = 0x0, 
    config_get_fn = 0x0, config_set_fn = 0x0, config_flags = 0}}
(gdb) print mods[i]->mod_bvalues[0]
Cannot access memory at address 0x0
(gdb) print mods[i]->mod_op
$1 = 129

This is specifically triggered if you attempt to MOD_DELETE on cachememsize.

Yep, this could easily crash the server. :(
$ ldapmodify -D 'cn=directory manager' ...
dn: cn=userRoot,cn=ldbm database,cn=plugins,cn=config
changetype: modify
delete: nsslapd-cachememsize

We certainly need to check mods[i]->mod_bvalues in ldbm_instance_modify_config_entry_callback... A nice finding!!

Comment by William:

I think the bigger concern would be other values that cause this to crash .... Should this cause us to write a "chaos-monkey" style tester that just deletes and trashes a DS install to see what it shakes out?

I agree. I would think backend config parameters cause the crash...

(Frontend ones are tested and supposed to fall back to the init value.)

Your fix looks good to me. But could you give us some more details about the "real fix" in this comment?
804 / This avoids the null pointer deref, but the real
805 * fix is in ldbm_config.c ldbm_config_set. This is where
806 * we check to make sure we aren't doing bad things with
807 * null values
808
/

I left the comment there thinking I would need to alter ldbm_config_set, turns out it already protected from NULL in mod[i]->bvalues. So I can clean up that comment.

commit 3c402a56982ca63595d4a2afca599926a279a791

Total 11 (delta 8), reused 0 (delta 0)
To ssh://git.fedorahosted.org/git/389/ds.git
415d855..9134b00 master -> master

Backport to 1.3.4 and 1.2.11

e6ba96d..2dd62a7 389-ds-base-1.3.4 -> 389-ds-base-1.3.4
commit 2dd62a7

7930571..fa54d0c 389-ds-base-1.2.11 -> 389-ds-base-1.2.11
commit fa54d0c
Author: William Brown firstyear@redhat.com
Date: Wed Mar 9 14:00:42 2016 +1000

To ssh://git.fedorahosted.org/git/389/ds.git
8a99552..9feca58 master -> master
commit 9feca58
Author: Simon Pichugin spichugi@redhat.com
Date: Tue Jan 10 13:55:30 2017 +0100

Metadata Update from @firstyear:
- Issue assigned to firstyear
- Issue set to the milestone: 1.2.11.33

2 years ago

Login to comment on this ticket.

Metadata