From: Greg Kroah-Hartman Date: Sat, 7 Dec 2019 12:16:10 +0000 (+0100) Subject: 4.4-stable patches X-Git-Tag: v5.4.3~69 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=39b92786390c1938e01f4858ff42aa6f6f095a78;p=thirdparty%2Fkernel%2Fstable-queue.git 4.4-stable patches added patches: fuse-verify-attributes.patch fuse-verify-nlink.patch sched-fair-scale-bandwidth-quota-and-period-without-losing-quota-period-ratio-precision.patch --- diff --git a/queue-4.4/fuse-verify-attributes.patch b/queue-4.4/fuse-verify-attributes.patch new file mode 100644 index 00000000000..85d6c09a1cb --- /dev/null +++ b/queue-4.4/fuse-verify-attributes.patch @@ -0,0 +1,121 @@ +From eb59bd17d2fa6e5e84fba61a5ebdea984222e6d5 Mon Sep 17 00:00:00 2001 +From: Miklos Szeredi +Date: Tue, 12 Nov 2019 11:49:04 +0100 +Subject: fuse: verify attributes + +From: Miklos Szeredi + +commit eb59bd17d2fa6e5e84fba61a5ebdea984222e6d5 upstream. + +If a filesystem returns negative inode sizes, future reads on the file were +causing the cpu to spin on truncate_pagecache. + +Create a helper to validate the attributes. This now does two things: + + - check the file mode + - check if the file size fits in i_size without overflowing + +Reported-by: Arijit Banerjee +Fixes: d8a5ba45457e ("[PATCH] FUSE - core") +Cc: # v2.6.14 +Signed-off-by: Miklos Szeredi +Signed-off-by: Greg Kroah-Hartman + +--- + fs/fuse/dir.c | 24 +++++++++++++++++------- + fs/fuse/fuse_i.h | 2 ++ + 2 files changed, 19 insertions(+), 7 deletions(-) + +--- a/fs/fuse/dir.c ++++ b/fs/fuse/dir.c +@@ -240,7 +240,8 @@ static int fuse_dentry_revalidate(struct + kfree(forget); + if (ret == -ENOMEM) + goto out; +- if (ret || (outarg.attr.mode ^ inode->i_mode) & S_IFMT) ++ if (ret || fuse_invalid_attr(&outarg.attr) || ++ (outarg.attr.mode ^ inode->i_mode) & S_IFMT) + goto invalid; + + fuse_change_attributes(inode, &outarg.attr, +@@ -282,6 +283,12 @@ int fuse_valid_type(int m) + S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m); + } + ++bool fuse_invalid_attr(struct fuse_attr *attr) ++{ ++ return !fuse_valid_type(attr->mode) || ++ attr->size > LLONG_MAX; ++} ++ + int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name, + struct fuse_entry_out *outarg, struct inode **inode) + { +@@ -313,7 +320,7 @@ int fuse_lookup_name(struct super_block + err = -EIO; + if (!outarg->nodeid) + goto out_put_forget; +- if (!fuse_valid_type(outarg->attr.mode)) ++ if (fuse_invalid_attr(&outarg->attr)) + goto out_put_forget; + + *inode = fuse_iget(sb, outarg->nodeid, outarg->generation, +@@ -433,7 +440,8 @@ static int fuse_create_open(struct inode + goto out_free_ff; + + err = -EIO; +- if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid)) ++ if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid) || ++ fuse_invalid_attr(&outentry.attr)) + goto out_free_ff; + + ff->fh = outopen.fh; +@@ -539,7 +547,7 @@ static int create_new_entry(struct fuse_ + goto out_put_forget_req; + + err = -EIO; +- if (invalid_nodeid(outarg.nodeid)) ++ if (invalid_nodeid(outarg.nodeid) || fuse_invalid_attr(&outarg.attr)) + goto out_put_forget_req; + + if ((outarg.attr.mode ^ mode) & S_IFMT) +@@ -893,7 +901,8 @@ static int fuse_do_getattr(struct inode + args.out.args[0].value = &outarg; + err = fuse_simple_request(fc, &args); + if (!err) { +- if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) { ++ if (fuse_invalid_attr(&outarg.attr) || ++ (inode->i_mode ^ outarg.attr.mode) & S_IFMT) { + make_bad_inode(inode); + err = -EIO; + } else { +@@ -1198,7 +1207,7 @@ static int fuse_direntplus_link(struct f + + if (invalid_nodeid(o->nodeid)) + return -EIO; +- if (!fuse_valid_type(o->attr.mode)) ++ if (fuse_invalid_attr(&o->attr)) + return -EIO; + + fc = get_fuse_conn(dir); +@@ -1670,7 +1679,8 @@ int fuse_do_setattr(struct inode *inode, + goto error; + } + +- if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) { ++ if (fuse_invalid_attr(&outarg.attr) || ++ (inode->i_mode ^ outarg.attr.mode) & S_IFMT) { + make_bad_inode(inode); + err = -EIO; + goto error; +--- a/fs/fuse/fuse_i.h ++++ b/fs/fuse/fuse_i.h +@@ -887,6 +887,8 @@ void fuse_ctl_remove_conn(struct fuse_co + */ + int fuse_valid_type(int m); + ++bool fuse_invalid_attr(struct fuse_attr *attr); ++ + /** + * Is current process allowed to perform filesystem operation? + */ diff --git a/queue-4.4/fuse-verify-nlink.patch b/queue-4.4/fuse-verify-nlink.patch new file mode 100644 index 00000000000..89cdaf119aa --- /dev/null +++ b/queue-4.4/fuse-verify-nlink.patch @@ -0,0 +1,32 @@ +From c634da718db9b2fac201df2ae1b1b095344ce5eb Mon Sep 17 00:00:00 2001 +From: Miklos Szeredi +Date: Tue, 12 Nov 2019 11:49:04 +0100 +Subject: fuse: verify nlink + +From: Miklos Szeredi + +commit c634da718db9b2fac201df2ae1b1b095344ce5eb upstream. + +When adding a new hard link, make sure that i_nlink doesn't overflow. + +Fixes: ac45d61357e8 ("fuse: fix nlink after unlink") +Cc: # v3.4 +Signed-off-by: Miklos Szeredi +Signed-off-by: Greg Kroah-Hartman + +--- + fs/fuse/dir.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/fs/fuse/dir.c ++++ b/fs/fuse/dir.c +@@ -812,7 +812,8 @@ static int fuse_link(struct dentry *entr + + spin_lock(&fc->lock); + fi->attr_version = ++fc->attr_version; +- inc_nlink(inode); ++ if (likely(inode->i_nlink < UINT_MAX)) ++ inc_nlink(inode); + spin_unlock(&fc->lock); + fuse_invalidate_attr(inode); + fuse_update_ctime(inode); diff --git a/queue-4.4/lockd-fix-decoding-of-test-results.patch b/queue-4.4/lockd-fix-decoding-of-test-results.patch deleted file mode 100644 index 0936302a344..00000000000 --- a/queue-4.4/lockd-fix-decoding-of-test-results.patch +++ /dev/null @@ -1,98 +0,0 @@ -From 66c45912a1133ed5483e1559bad8a5d6bd2f4275 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Mon, 26 Nov 2018 11:36:52 -0500 -Subject: lockd: fix decoding of TEST results - -From: J. Bruce Fields - -[ Upstream commit b8db159239b3f51e2b909859935cc25cb3ff3eed ] - -We fail to advance the read pointer when reading the stat.oh field that -identifies the lock-holder in a TEST result. - -This turns out not to matter if the server is knfsd, which always -returns a zero-length field. But other servers (Ganesha is an example) -may not do this. The result is bad values in fcntl F_GETLK results. - -Fix this. - -Signed-off-by: J. Bruce Fields -Signed-off-by: Sasha Levin ---- - fs/lockd/clnt4xdr.c | 22 ++++++---------------- - fs/lockd/clntxdr.c | 22 ++++++---------------- - 2 files changed, 12 insertions(+), 32 deletions(-) - -diff --git a/fs/lockd/clnt4xdr.c b/fs/lockd/clnt4xdr.c -index d3e40db289302..4fdf8dae0db28 100644 ---- a/fs/lockd/clnt4xdr.c -+++ b/fs/lockd/clnt4xdr.c -@@ -127,24 +127,14 @@ static void encode_netobj(struct xdr_stream *xdr, - static int decode_netobj(struct xdr_stream *xdr, - struct xdr_netobj *obj) - { -- u32 length; -- __be32 *p; -+ ssize_t ret; - -- p = xdr_inline_decode(xdr, 4); -- if (unlikely(p == NULL)) -- goto out_overflow; -- length = be32_to_cpup(p++); -- if (unlikely(length > XDR_MAX_NETOBJ)) -- goto out_size; -- obj->len = length; -- obj->data = (u8 *)p; -+ ret = xdr_stream_decode_opaque_inline(xdr, (void *)&obj->data, -+ XDR_MAX_NETOBJ); -+ if (unlikely(ret < 0)) -+ return -EIO; -+ obj->len = ret; - return 0; --out_size: -- dprintk("NFS: returned netobj was too long: %u\n", length); -- return -EIO; --out_overflow: -- print_overflow_msg(__func__, xdr); -- return -EIO; - } - - /* -diff --git a/fs/lockd/clntxdr.c b/fs/lockd/clntxdr.c -index 3e9f7874b9755..29392d66473c8 100644 ---- a/fs/lockd/clntxdr.c -+++ b/fs/lockd/clntxdr.c -@@ -124,24 +124,14 @@ static void encode_netobj(struct xdr_stream *xdr, - static int decode_netobj(struct xdr_stream *xdr, - struct xdr_netobj *obj) - { -- u32 length; -- __be32 *p; -+ ssize_t ret; - -- p = xdr_inline_decode(xdr, 4); -- if (unlikely(p == NULL)) -- goto out_overflow; -- length = be32_to_cpup(p++); -- if (unlikely(length > XDR_MAX_NETOBJ)) -- goto out_size; -- obj->len = length; -- obj->data = (u8 *)p; -+ ret = xdr_stream_decode_opaque_inline(xdr, (void *)&obj->data, -+ XDR_MAX_NETOBJ); -+ if (unlikely(ret < 0)) -+ return -EIO; -+ obj->len = ret; - return 0; --out_size: -- dprintk("NFS: returned netobj was too long: %u\n", length); -- return -EIO; --out_overflow: -- print_overflow_msg(__func__, xdr); -- return -EIO; - } - - /* --- -2.20.1 - diff --git a/queue-4.4/sched-fair-scale-bandwidth-quota-and-period-without-losing-quota-period-ratio-precision.patch b/queue-4.4/sched-fair-scale-bandwidth-quota-and-period-without-losing-quota-period-ratio-precision.patch new file mode 100644 index 00000000000..dca64044956 --- /dev/null +++ b/queue-4.4/sched-fair-scale-bandwidth-quota-and-period-without-losing-quota-period-ratio-precision.patch @@ -0,0 +1,107 @@ +From 4929a4e6faa0f13289a67cae98139e727f0d4a97 Mon Sep 17 00:00:00 2001 +From: Xuewei Zhang +Date: Thu, 3 Oct 2019 17:12:43 -0700 +Subject: sched/fair: Scale bandwidth quota and period without losing quota/period ratio precision + +From: Xuewei Zhang + +commit 4929a4e6faa0f13289a67cae98139e727f0d4a97 upstream. + +The quota/period ratio is used to ensure a child task group won't get +more bandwidth than the parent task group, and is calculated as: + + normalized_cfs_quota() = [(quota_us << 20) / period_us] + +If the quota/period ratio was changed during this scaling due to +precision loss, it will cause inconsistency between parent and child +task groups. + +See below example: + +A userspace container manager (kubelet) does three operations: + + 1) Create a parent cgroup, set quota to 1,000us and period to 10,000us. + 2) Create a few children cgroups. + 3) Set quota to 1,000us and period to 10,000us on a child cgroup. + +These operations are expected to succeed. However, if the scaling of +147/128 happens before step 3, quota and period of the parent cgroup +will be changed: + + new_quota: 1148437ns, 1148us + new_period: 11484375ns, 11484us + +And when step 3 comes in, the ratio of the child cgroup will be +104857, which will be larger than the parent cgroup ratio (104821), +and will fail. + +Scaling them by a factor of 2 will fix the problem. + +Tested-by: Phil Auld +Signed-off-by: Xuewei Zhang +Signed-off-by: Peter Zijlstra (Intel) +Acked-by: Phil Auld +Cc: Anton Blanchard +Cc: Ben Segall +Cc: Dietmar Eggemann +Cc: Juri Lelli +Cc: Linus Torvalds +Cc: Mel Gorman +Cc: Peter Zijlstra +Cc: Steven Rostedt +Cc: Thomas Gleixner +Cc: Vincent Guittot +Fixes: 2e8e19226398 ("sched/fair: Limit sched_cfs_period_timer() loop to avoid hard lockup") +Link: https://lkml.kernel.org/r/20191004001243.140897-1-xueweiz@google.com +Signed-off-by: Ingo Molnar +Signed-off-by: Greg Kroah-Hartman + + +--- + kernel/sched/fair.c | 34 +++++++++++++++++++++------------- + 1 file changed, 21 insertions(+), 13 deletions(-) + +--- a/kernel/sched/fair.c ++++ b/kernel/sched/fair.c +@@ -4055,20 +4055,28 @@ static enum hrtimer_restart sched_cfs_pe + if (++count > 3) { + u64 new, old = ktime_to_ns(cfs_b->period); + +- new = (old * 147) / 128; /* ~115% */ +- new = min(new, max_cfs_quota_period); ++ /* ++ * Grow period by a factor of 2 to avoid losing precision. ++ * Precision loss in the quota/period ratio can cause __cfs_schedulable ++ * to fail. ++ */ ++ new = old * 2; ++ if (new < max_cfs_quota_period) { ++ cfs_b->period = ns_to_ktime(new); ++ cfs_b->quota *= 2; + +- cfs_b->period = ns_to_ktime(new); +- +- /* since max is 1s, this is limited to 1e9^2, which fits in u64 */ +- cfs_b->quota *= new; +- cfs_b->quota = div64_u64(cfs_b->quota, old); +- +- pr_warn_ratelimited( +- "cfs_period_timer[cpu%d]: period too short, scaling up (new cfs_period_us %lld, cfs_quota_us = %lld)\n", +- smp_processor_id(), +- div_u64(new, NSEC_PER_USEC), +- div_u64(cfs_b->quota, NSEC_PER_USEC)); ++ pr_warn_ratelimited( ++ "cfs_period_timer[cpu%d]: period too short, scaling up (new cfs_period_us = %lld, cfs_quota_us = %lld)\n", ++ smp_processor_id(), ++ div_u64(new, NSEC_PER_USEC), ++ div_u64(cfs_b->quota, NSEC_PER_USEC)); ++ } else { ++ pr_warn_ratelimited( ++ "cfs_period_timer[cpu%d]: period too short, but cannot scale up without losing precision (cfs_period_us = %lld, cfs_quota_us = %lld)\n", ++ smp_processor_id(), ++ div_u64(old, NSEC_PER_USEC), ++ div_u64(cfs_b->quota, NSEC_PER_USEC)); ++ } + + /* reset count so we don't come right back in here */ + count = 0; diff --git a/queue-4.4/series b/queue-4.4/series index cad2ce50014..337c0395c6f 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -35,7 +35,6 @@ dma-mapping-fix-return-type-of-dma_set_max_seg_size.patch altera-stapl-check-for-a-null-key-before-strcasecmp-.patch serial-imx-fix-error-handling-in-console_setup.patch i2c-imx-don-t-print-error-message-on-probe-defer.patch -lockd-fix-decoding-of-test-results.patch dlm-null-check-before-kmem_cache_destroy-is-not-need.patch nfsd-fix-a-warning-in-__cld_pipe_upcall.patch arm-omap1-2-fix-soc-name-printing.patch @@ -52,3 +51,6 @@ mips-octeon-cvmx_pko_mem_debug8-use-oldest-forward-c.patch nfsd-return-eperm-not-eacces-in-some-setattr-cases.patch mlx4-use-snprintf-instead-of-complicated-strcpy.patch arm-dts-sunxi-fix-pmu-compatible-strings.patch +sched-fair-scale-bandwidth-quota-and-period-without-losing-quota-period-ratio-precision.patch +fuse-verify-nlink.patch +fuse-verify-attributes.patch