From: Greg Kroah-Hartman Date: Sat, 7 Dec 2019 12:24:51 +0000 (+0100) Subject: 4.19-stable patches X-Git-Tag: v5.4.3~65 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=c157ae82010f94b21a7b93db8d112d200f504f77;p=thirdparty%2Fkernel%2Fstable-queue.git 4.19-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.19/fuse-verify-attributes.patch b/queue-4.19/fuse-verify-attributes.patch new file mode 100644 index 00000000000..5b5a8f942dc --- /dev/null +++ b/queue-4.19/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 +@@ -234,7 +234,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; + + forget_all_cached_acls(inode); +@@ -297,6 +298,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, const struct qstr *name, + struct fuse_entry_out *outarg, struct inode **inode) + { +@@ -328,7 +335,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, +@@ -451,7 +458,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; +@@ -558,7 +566,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) +@@ -918,7 +926,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 { +@@ -1230,7 +1239,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); +@@ -1707,7 +1716,8 @@ int fuse_do_setattr(struct dentry *dentr + 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 +@@ -909,6 +909,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.19/fuse-verify-nlink.patch b/queue-4.19/fuse-verify-nlink.patch new file mode 100644 index 00000000000..51f4b9df163 --- /dev/null +++ b/queue-4.19/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 +@@ -837,7 +837,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.19/sched-fair-scale-bandwidth-quota-and-period-without-losing-quota-period-ratio-precision.patch b/queue-4.19/sched-fair-scale-bandwidth-quota-and-period-without-losing-quota-period-ratio-precision.patch new file mode 100644 index 00000000000..b0dcb2ffdf0 --- /dev/null +++ b/queue-4.19/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 +@@ -4868,20 +4868,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.19/series b/queue-4.19/series index 041740027df..0aa8f34e12b 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -203,3 +203,6 @@ arm-dts-sunxi-fix-pmu-compatible-strings.patch arm-dts-am335x-pdu001-fix-polarity-of-card-detection.patch media-vimc-fix-start-stream-when-link-is-disabled.patch net-aquantia-fix-rss-table-and-key-sizes.patch +sched-fair-scale-bandwidth-quota-and-period-without-losing-quota-period-ratio-precision.patch +fuse-verify-nlink.patch +fuse-verify-attributes.patch