s3-parm: clean up defaults when removing global parameters
authorAlexander Bokovoy <ab@samba.org>
Fri, 22 Jan 2016 09:44:03 +0000 (11:44 +0200)
committerUri Simchoni <uri@samba.org>
Mon, 25 Jan 2016 22:58:41 +0000 (23:58 +0100)
BUG: https://bugzilla.samba.org/show_bug.cgi?id=11693

When globals are re-initialized, they are cleared and globals' talloc
context is freed. However, parm_table still contains a reference to the
global value in the defaults. This confuses lpcfg_string_free() after
commit 795c543d858b2452f062a02846c2f908fe4cffe4 because it tries to
free already freed pointer which is passed by lp_save_defaults():

....
    case P_STRING:
    case P_USTRING:
                  lpcfg_string_set(Globals.ctx,
                                   &parm_table[i].def.svalue,
                                   *(char **)lp_parm_ptr(NULL, &parm_table[i]));
....

here &parm_table[i].def.svalue is passed to lpcfg_string_free() but it
is a pointer to a value allocated with previous Globals.ctx which
already was freed.

This specifically affects registry backend of smb.conf in lp_load_ex()
where init_globals() called explicitly to re-init globals after
lp_save_defaults() if we have registry backend defined.

Reviewed-by: Uri Simchoni <uri@samba.org>
Signed-off-by: Alexander Bokovoy <ab@samba.org>
Autobuild-User(master): Uri Simchoni <uri@samba.org>
Autobuild-Date(master): Mon Jan 25 23:58:42 CET 2016 on sn-devel-144

source3/param/loadparm.c

index 9f4a2b406401580805a21b1e3ec2078757524a30..f8ecab716b44252a550e397c5a2d9afd9fdb4620 100644 (file)
@@ -399,8 +399,25 @@ static void free_parameters_by_snum(int snum)
  */
 static void free_global_parameters(void)
 {
+       uint32_t i;
+       struct parm_struct *parm;
+
        free_param_opts(&Globals.param_opt);
        free_parameters_by_snum(GLOBAL_SECTION_SNUM);
+
+       /* Reset references in the defaults because the context is going to be freed */
+       for (i=0; parm_table[i].label; i++) {
+               parm = &parm_table[i];
+               if ((parm->type == P_STRING) ||
+                   (parm->type == P_USTRING)) {
+                       if ((parm->def.svalue != NULL) &&
+                           (*(parm->def.svalue) != '\0')) {
+                               if (talloc_parent(parm->def.svalue) == Globals.ctx) {
+                                       parm->def.svalue = NULL;
+                               }
+                       }
+               }
+       }
        TALLOC_FREE(Globals.ctx);
 }