]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
vfs_recycle: fix memory hierarchy
authorStefan Metzmacher <metze@samba.org>
Fri, 14 Jun 2024 08:07:02 +0000 (10:07 +0200)
committerStefan Metzmacher <metze@samba.org>
Wed, 19 Jun 2024 09:07:36 +0000 (09:07 +0000)
If the configuration is reloaded strings and string lists
in recycle_config_data could become stale pointers
leading to segmentation faults...

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15659

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Martin Schwenke <martin@meltin.net>
Reviewed-by: Noel Power <noel.power@suse.com>
Reviewed-by: Volker Lendecke <vl@samba.org>
selftest/knownfail.d/samba3.blackbox.recycle [deleted file]
source3/modules/vfs_recycle.c

diff --git a/selftest/knownfail.d/samba3.blackbox.recycle b/selftest/knownfail.d/samba3.blackbox.recycle
deleted file mode 100644 (file)
index bae7f71..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-^samba3.blackbox.recycle.recycle.fileserver
-^samba3.blackbox.recycle.check_panic.fileserver
index 2293185a5aff7166ee1d65ea4053091863259f70..f318e0ab1db0ec8e647c2bb0ea2a352560fbc75b 100644 (file)
@@ -58,7 +58,8 @@ static int vfs_recycle_connect(struct vfs_handle_struct *handle,
        struct recycle_config_data *config = NULL;
        int ret;
        int t;
-       const char *buff;
+       const char *buff = NULL;
+       const char **tmplist = NULL;
 
        ret = SMB_VFS_NEXT_CONNECT(handle, service, user);
        if (ret < 0) {
@@ -75,10 +76,17 @@ static int vfs_recycle_connect(struct vfs_handle_struct *handle,
                errno = ENOMEM;
                return -1;
        }
-       config->repository = lp_parm_const_string(SNUM(handle->conn),
-                                                 "recycle",
-                                                 "repository",
-                                                 ".recycle");
+       buff = lp_parm_const_string(SNUM(handle->conn),
+                                   "recycle",
+                                   "repository",
+                                   ".recycle");
+       config->repository = talloc_strdup(config, buff);
+       if (config->repository == NULL) {
+               DBG_ERR("talloc_strdup(%s) failed\n", buff);
+               TALLOC_FREE(config);
+               errno = ENOMEM;
+               return -1;
+       }
        config->keeptree = lp_parm_bool(SNUM(handle->conn),
                                        "recycle",
                                        "keeptree",
@@ -95,18 +103,48 @@ static int vfs_recycle_connect(struct vfs_handle_struct *handle,
                                           "recycle",
                                           "touch_mtime",
                                           False);
-       config->exclude = lp_parm_string_list(SNUM(handle->conn),
-                                             "recycle",
-                                             "exclude",
-                                             NULL);
-       config->exclude_dir = lp_parm_string_list(SNUM(handle->conn),
-                                                 "recycle",
-                                                 "exclude_dir",
-                                                 NULL);
-       config->noversions = lp_parm_string_list(SNUM(handle->conn),
-                                                "recycle",
-                                                "noversions",
-                                                NULL);
+       tmplist = lp_parm_string_list(SNUM(handle->conn),
+                                     "recycle",
+                                     "exclude",
+                                     NULL);
+       if (tmplist != NULL) {
+               char **tmpcpy = str_list_copy(config, tmplist);
+               if (tmpcpy == NULL) {
+                       DBG_ERR("str_list_copy() failed\n");
+                       TALLOC_FREE(config);
+                       errno = ENOMEM;
+                       return -1;
+               }
+               config->exclude = discard_const_p(const char *, tmpcpy);
+       }
+       tmplist = lp_parm_string_list(SNUM(handle->conn),
+                                     "recycle",
+                                     "exclude_dir",
+                                     NULL);
+       if (tmplist != NULL) {
+               char **tmpcpy = str_list_copy(config, tmplist);
+               if (tmpcpy == NULL) {
+                       DBG_ERR("str_list_copy() failed\n");
+                       TALLOC_FREE(config);
+                       errno = ENOMEM;
+                       return -1;
+               }
+               config->exclude_dir = discard_const_p(const char *, tmpcpy);
+       }
+       tmplist = lp_parm_string_list(SNUM(handle->conn),
+                                     "recycle",
+                                     "noversions",
+                                     NULL);
+       if (tmplist != NULL) {
+               char **tmpcpy = str_list_copy(config, tmplist);
+               if (tmpcpy == NULL) {
+                       DBG_ERR("str_list_copy() failed\n");
+                       TALLOC_FREE(config);
+                       errno = ENOMEM;
+                       return -1;
+               }
+               config->noversions = discard_const_p(const char *, tmpcpy);
+       }
        config->minsize = conv_str_size(lp_parm_const_string(
                SNUM(handle->conn), "recycle", "minsize", NULL));
        config->maxsize = conv_str_size(lp_parm_const_string(