linux-block.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] blk-throttle: verify format of bandwidth limit and detect overflows
@ 2019-02-27  8:05 Konstantin Khlebnikov
  2019-03-05 15:56 ` Tejun Heo
  0 siblings, 1 reply; 3+ messages in thread
From: Konstantin Khlebnikov @ 2019-02-27  8:05 UTC (permalink / raw)
  To: Jens Axboe, linux-kernel, linux-block, Li Zefan, Johannes Weiner,
	Tejun Heo, cgroups

Unlike to memory cgroup blkio throttler does not support value suffixes.

It silently ignores everything after last digit. For example this command
will set rate limit 1 byte per second rather than 1 megabyte per second:

# echo "7:0 1M" > blkio.throttle.read_bps_device
# cat blkio.throttle.read_bps_device
7:0 1

Cgroup2 interface has the same flaw:

# echo "7:0 rbps=1M" > io.max
# cat io.max
7:0 rbps=1 wbps=max riops=max wiops=max

Also sscanf does not care much about overflows.

This patch uses modern function kstrtou64 for parsing.
It rejects trailing garbage and detects integer overflows.

Also this patch handles iops limit overflows for cgroup-v1 in the same as
cgroup-v2: limits >= UINT_MAX becomes unlimited.

Fixes: 2ee867dcfa2e ("blkcg: implement interface for the unified hierarchy")
Signed-off-by: Konstantin Khlebnikov <khlebnikov@yandex-team.ru>
---
 block/blk-throttle.c |   40 ++++++++++++++++++++++++----------------
 1 file changed, 24 insertions(+), 16 deletions(-)

diff --git a/block/blk-throttle.c b/block/blk-throttle.c
index 1b97a73d2fb1..ce00060b3a48 100644
--- a/block/blk-throttle.c
+++ b/block/blk-throttle.c
@@ -1433,8 +1433,10 @@ static ssize_t tg_set_conf(struct kernfs_open_file *of,
 	if (ret)
 		return ret;
 
-	ret = -EINVAL;
-	if (sscanf(ctx.body, "%llu", &v) != 1)
+	/* remove trailing spaces, kstrto* are strict about them */
+	ctx.body = strim(ctx.body);
+	ret = kstrtou64(ctx.body, 10, &v);
+	if (ret)
 		goto out_finish;
 	if (!v)
 		v = U64_MAX;
@@ -1444,7 +1446,8 @@ static ssize_t tg_set_conf(struct kernfs_open_file *of,
 	if (is_u64)
 		*(u64 *)((void *)tg + of_cft(of)->private) = v;
 	else
-		*(unsigned int *)((void *)tg + of_cft(of)->private) = v;
+		*(unsigned int *)((void *)tg + of_cft(of)->private) =
+							min_t(u64, v, UINT_MAX);
 
 	tg_conf_updated(tg, false);
 	ret = 0;
@@ -1609,23 +1612,25 @@ static ssize_t tg_set_limit(struct kernfs_open_file *of,
 	idle_time = tg->idletime_threshold_conf;
 	latency_time = tg->latency_target_conf;
 	while (true) {
-		char tok[27];	/* wiops=18446744073709551616 */
-		char *p;
-		u64 val = U64_MAX;
-		int len;
-
-		if (sscanf(ctx.body, "%26s%n", tok, &len) != 1)
-			break;
-		if (tok[0] == '\0')
-			break;
-		ctx.body += len;
+		char tok[8];	/* "latency" */
+		char buf[21];	/* U64_MAX */
+		int end;
+		u64 val;
 
 		ret = -EINVAL;
-		p = tok;
-		strsep(&p, "=");
-		if (!p || (sscanf(p, "%llu", &val) != 1 && strcmp(p, "max")))
+		if (sscanf(ctx.body, "%7[^=]=%20s %n", tok, buf, &end) != 2)
 			goto out_finish;
 
+		/* skip this field and trailing spaces */
+		ctx.body += end;
+
+		ret = kstrtou64(buf, 10, &val);
+		if (ret) {
+			if (strcmp(buf, "max"))
+				goto out_finish;
+			val = U64_MAX;
+		}
+
 		ret = -ERANGE;
 		if (!val)
 			goto out_finish;
@@ -1645,6 +1650,9 @@ static ssize_t tg_set_limit(struct kernfs_open_file *of,
 			latency_time = val;
 		else
 			goto out_finish;
+
+		if (!*ctx.body)
+			break;
 	}
 
 	tg->bps_conf[READ][index] = v[0];


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] blk-throttle: verify format of bandwidth limit and detect overflows
  2019-02-27  8:05 [PATCH] blk-throttle: verify format of bandwidth limit and detect overflows Konstantin Khlebnikov
@ 2019-03-05 15:56 ` Tejun Heo
  2019-03-05 17:27   ` Konstantin Khlebnikov
  0 siblings, 1 reply; 3+ messages in thread
From: Tejun Heo @ 2019-03-05 15:56 UTC (permalink / raw)
  To: Konstantin Khlebnikov
  Cc: Jens Axboe, linux-kernel, linux-block, Li Zefan, Johannes Weiner,
	cgroups

Hello, Konstantin.

On Wed, Feb 27, 2019 at 11:05:44AM +0300, Konstantin Khlebnikov wrote:
> Unlike to memory cgroup blkio throttler does not support value suffixes.
> 
> It silently ignores everything after last digit. For example this command
> will set rate limit 1 byte per second rather than 1 megabyte per second:
> 
> # echo "7:0 1M" > blkio.throttle.read_bps_device
> # cat blkio.throttle.read_bps_device
> 7:0 1
> 
> Cgroup2 interface has the same flaw:
> 
> # echo "7:0 rbps=1M" > io.max
> # cat io.max
> 7:0 rbps=1 wbps=max riops=max wiops=max
> 
> Also sscanf does not care much about overflows.
> 
> This patch uses modern function kstrtou64 for parsing.
> It rejects trailing garbage and detects integer overflows.
> 
> Also this patch handles iops limit overflows for cgroup-v1 in the same as
> cgroup-v2: limits >= UINT_MAX becomes unlimited.
> 
> Fixes: 2ee867dcfa2e ("blkcg: implement interface for the unified hierarchy")
> Signed-off-by: Konstantin Khlebnikov <khlebnikov@yandex-team.ru>

So, I'd much rather keep the parsing implementations simple.  Unless
there's a correctness problem (you mentioned overflowing, how would
that happen?), the simpler the better.  I don't think the kernel needs
to be in the business of strict input verification here.

Thanks.

-- 
tejun

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] blk-throttle: verify format of bandwidth limit and detect overflows
  2019-03-05 15:56 ` Tejun Heo
@ 2019-03-05 17:27   ` Konstantin Khlebnikov
  0 siblings, 0 replies; 3+ messages in thread
From: Konstantin Khlebnikov @ 2019-03-05 17:27 UTC (permalink / raw)
  To: Tejun Heo
  Cc: Jens Axboe, linux-kernel, linux-block, Li Zefan, Johannes Weiner,
	cgroups

On 05.03.2019 18:56, Tejun Heo wrote:
> Hello, Konstantin.
> 
> On Wed, Feb 27, 2019 at 11:05:44AM +0300, Konstantin Khlebnikov wrote:
>> Unlike to memory cgroup blkio throttler does not support value suffixes.
>>
>> It silently ignores everything after last digit. For example this command
>> will set rate limit 1 byte per second rather than 1 megabyte per second:
>>
>> # echo "7:0 1M" > blkio.throttle.read_bps_device
>> # cat blkio.throttle.read_bps_device
>> 7:0 1
>>
>> Cgroup2 interface has the same flaw:
>>
>> # echo "7:0 rbps=1M" > io.max
>> # cat io.max
>> 7:0 rbps=1 wbps=max riops=max wiops=max
>>
>> Also sscanf does not care much about overflows.
>>
>> This patch uses modern function kstrtou64 for parsing.
>> It rejects trailing garbage and detects integer overflows.
>>
>> Also this patch handles iops limit overflows for cgroup-v1 in the same as
>> cgroup-v2: limits >= UINT_MAX becomes unlimited.
>>
>> Fixes: 2ee867dcfa2e ("blkcg: implement interface for the unified hierarchy")
>> Signed-off-by: Konstantin Khlebnikov <khlebnikov@yandex-team.ru>
> 
> So, I'd much rather keep the parsing implementations simple.  Unless
> there's a correctness problem (you mentioned overflowing, how would
> that happen?), the simpler the better.  I don't think the kernel needs
> to be in the business of strict input verification here.

This is inconsistency between controllers. IO controller should either
accept size suffixes or reject them. Ignoring garbage is not an option.
To be honest, I've successfully shot in the foot by bps limit "1M".

Integer overflows are happens when userspace software uses floats for data
representation and calculations. This way values bigger than 2^32-1 or
2^64-1 could appear easily in text representation.

Almost all integer knobs in sysctl and sysfs use modern kstrtoXX functions
with strict validation of format and overflows.

> 
> Thanks.
> 

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2019-03-05 17:27 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-02-27  8:05 [PATCH] blk-throttle: verify format of bandwidth limit and detect overflows Konstantin Khlebnikov
2019-03-05 15:56 ` Tejun Heo
2019-03-05 17:27   ` Konstantin Khlebnikov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).