From: Greg Kroah-Hartman Date: Mon, 4 Feb 2019 08:58:24 +0000 (+0100) Subject: 4.9-stable patches X-Git-Tag: v4.20.7~14 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=fe873e64a643190ec6bb79361f7844e5e4fe5b1d;p=thirdparty%2Fkernel%2Fstable-queue.git 4.9-stable patches added patches: cifs-always-resolve-hostname-before-reconnecting.patch drivers-core-remove-glue-dirs-from-sysfs-earlier.patch --- diff --git a/queue-4.9/cifs-always-resolve-hostname-before-reconnecting.patch b/queue-4.9/cifs-always-resolve-hostname-before-reconnecting.patch new file mode 100644 index 00000000000..f9ca45fd84e --- /dev/null +++ b/queue-4.9/cifs-always-resolve-hostname-before-reconnecting.patch @@ -0,0 +1,99 @@ +From 28eb24ff75c5ac130eb326b3b4d0dcecfc0f427d Mon Sep 17 00:00:00 2001 +From: Paulo Alcantara +Date: Tue, 20 Nov 2018 15:16:36 -0200 +Subject: cifs: Always resolve hostname before reconnecting + +From: Paulo Alcantara + +commit 28eb24ff75c5ac130eb326b3b4d0dcecfc0f427d upstream. + +In case a hostname resolves to a different IP address (e.g. long +running mounts), make sure to resolve it every time prior to calling +generic_ip_connect() in reconnect. + +Suggested-by: Steve French +Signed-off-by: Paulo Alcantara +Signed-off-by: Steve French +Signed-off-by: Pavel Shilovsky +Signed-off-by: Greg Kroah-Hartman + +--- + fs/cifs/connect.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 53 insertions(+) + +--- a/fs/cifs/connect.c ++++ b/fs/cifs/connect.c +@@ -48,6 +48,7 @@ + #include "cifs_unicode.h" + #include "cifs_debug.h" + #include "cifs_fs_sb.h" ++#include "dns_resolve.h" + #include "ntlmssp.h" + #include "nterr.h" + #include "rfc1002pdu.h" +@@ -307,6 +308,53 @@ static int cifs_setup_volume_info(struct + const char *devname); + + /* ++ * Resolve hostname and set ip addr in tcp ses. Useful for hostnames that may ++ * get their ip addresses changed at some point. ++ * ++ * This should be called with server->srv_mutex held. ++ */ ++#ifdef CONFIG_CIFS_DFS_UPCALL ++static int reconn_set_ipaddr(struct TCP_Server_Info *server) ++{ ++ int rc; ++ int len; ++ char *unc, *ipaddr = NULL; ++ ++ if (!server->hostname) ++ return -EINVAL; ++ ++ len = strlen(server->hostname) + 3; ++ ++ unc = kmalloc(len, GFP_KERNEL); ++ if (!unc) { ++ cifs_dbg(FYI, "%s: failed to create UNC path\n", __func__); ++ return -ENOMEM; ++ } ++ snprintf(unc, len, "\\\\%s", server->hostname); ++ ++ rc = dns_resolve_server_name_to_ip(unc, &ipaddr); ++ kfree(unc); ++ ++ if (rc < 0) { ++ cifs_dbg(FYI, "%s: failed to resolve server part of %s to IP: %d\n", ++ __func__, server->hostname, rc); ++ return rc; ++ } ++ ++ rc = cifs_convert_address((struct sockaddr *)&server->dstaddr, ipaddr, ++ strlen(ipaddr)); ++ kfree(ipaddr); ++ ++ return !rc ? -1 : 0; ++} ++#else ++static inline int reconn_set_ipaddr(struct TCP_Server_Info *server) ++{ ++ return 0; ++} ++#endif ++ ++/* + * cifs tcp session reconnection + * + * mark tcp session as reconnecting so temporarily locked +@@ -403,6 +451,11 @@ cifs_reconnect(struct TCP_Server_Info *s + rc = generic_ip_connect(server); + if (rc) { + cifs_dbg(FYI, "reconnect error %d\n", rc); ++ rc = reconn_set_ipaddr(server); ++ if (rc) { ++ cifs_dbg(FYI, "%s: failed to resolve hostname: %d\n", ++ __func__, rc); ++ } + mutex_unlock(&server->srv_mutex); + msleep(3000); + } else { diff --git a/queue-4.9/drivers-core-remove-glue-dirs-from-sysfs-earlier.patch b/queue-4.9/drivers-core-remove-glue-dirs-from-sysfs-earlier.patch new file mode 100644 index 00000000000..c06ee050435 --- /dev/null +++ b/queue-4.9/drivers-core-remove-glue-dirs-from-sysfs-earlier.patch @@ -0,0 +1,86 @@ +From 726e41097920a73e4c7c33385dcc0debb1281e18 Mon Sep 17 00:00:00 2001 +From: Benjamin Herrenschmidt +Date: Tue, 10 Jul 2018 10:29:10 +1000 +Subject: drivers: core: Remove glue dirs from sysfs earlier + +From: Benjamin Herrenschmidt + +commit 726e41097920a73e4c7c33385dcc0debb1281e18 upstream. + +For devices with a class, we create a "glue" directory between +the parent device and the new device with the class name. + +This directory is never "explicitely" removed when empty however, +this is left to the implicit sysfs removal done by kobject_release() +when the object loses its last reference via kobject_put(). + +This is problematic because as long as it's not been removed from +sysfs, it is still present in the class kset and in sysfs directory +structure. + +The presence in the class kset exposes a use after free bug fixed +by the previous patch, but the presence in sysfs means that until +the kobject is released, which can take a while (especially with +kobject debugging), any attempt at re-creating such as binding a +new device for that class/parent pair, will result in a sysfs +duplicate file name error. + +This fixes it by instead doing an explicit kobject_del() when +the glue dir is empty, by keeping track of the number of +child devices of the gluedir. + +This is made easy by the fact that all glue dir operations are +done with a global mutex, and there's already a function +(cleanup_glue_dir) called in all the right places taking that +mutex that can be enhanced for this. It appears that this was +in fact the intent of the function, but the implementation was +wrong. + +Signed-off-by: Benjamin Herrenschmidt +Acked-by: Linus Torvalds +Signed-off-by: Zubin Mithra +Cc: Guenter Roeck +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/base/core.c | 2 ++ + include/linux/kobject.h | 17 +++++++++++++++++ + 2 files changed, 19 insertions(+) + +--- a/drivers/base/core.c ++++ b/drivers/base/core.c +@@ -862,6 +862,8 @@ static void cleanup_glue_dir(struct devi + return; + + mutex_lock(&gdp_mutex); ++ if (!kobject_has_children(glue_dir)) ++ kobject_del(glue_dir); + kobject_put(glue_dir); + mutex_unlock(&gdp_mutex); + } +--- a/include/linux/kobject.h ++++ b/include/linux/kobject.h +@@ -113,6 +113,23 @@ extern void kobject_put(struct kobject * + extern const void *kobject_namespace(struct kobject *kobj); + extern char *kobject_get_path(struct kobject *kobj, gfp_t flag); + ++/** ++ * kobject_has_children - Returns whether a kobject has children. ++ * @kobj: the object to test ++ * ++ * This will return whether a kobject has other kobjects as children. ++ * ++ * It does NOT account for the presence of attribute files, only sub ++ * directories. It also assumes there is no concurrent addition or ++ * removal of such children, and thus relies on external locking. ++ */ ++static inline bool kobject_has_children(struct kobject *kobj) ++{ ++ WARN_ON_ONCE(atomic_read(&kobj->kref.refcount) == 0); ++ ++ return kobj->sd && kobj->sd->dir.subdirs; ++} ++ + struct kobj_type { + void (*release)(struct kobject *kobj); + const struct sysfs_ops *sysfs_ops; diff --git a/queue-4.9/series b/queue-4.9/series index 4fb9a238424..86c999d1cbd 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -24,3 +24,5 @@ kernel-exit.c-release-ptraced-tasks-before-zap_pid_ns_processes.patch mm-oom-fix-use-after-free-in-oom_kill_process.patch mm-hwpoison-use-do_send_sig_info-instead-of-force_sig.patch mm-migrate-don-t-rely-on-__pagemovable-of-newpage-after-unlocking-it.patch +cifs-always-resolve-hostname-before-reconnecting.patch +drivers-core-remove-glue-dirs-from-sysfs-earlier.patch