summaryrefslogtreecommitdiffstats
path: root/kernel/power
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2023-05-31 14:55:32 +0200
committerJens Axboe <axboe@kernel.dk>2023-06-05 18:57:40 +0200
commit1e8c813b083c4122dfeaa5c3b11028331026e85d (patch)
treee62db6fd88c822c00cd4e7cc38ec715b1b0bdce6 /kernel/power
parentdm: only call early_lookup_bdev from early boot context (diff)
downloadlinux-1e8c813b083c4122dfeaa5c3b11028331026e85d.tar.xz
linux-1e8c813b083c4122dfeaa5c3b11028331026e85d.zip
PM: hibernate: don't use early_lookup_bdev in resume_store
resume_store is a sysfs attribute written during normal kernel runtime, and it should not use the early_lookup_bdev API that bypasses all normal path based permission checking, and might cause problems with certain container environments renaming devices. Switch to lookup_bdev, which does a normal path lookup instead, and fall back to trying to parse a numeric dev_t just like early_lookup_bdev did. Note that this strictly speaking changes the kernel ABI as the PARTUUID= and PARTLABEL= style syntax is now not available during a running systems. They never were intended for that, but this breaks things we'll have to figure out a way to make them available again. But if avoidable in any way I'd rather avoid that. Fixes: 421a5fa1a6cf ("PM / hibernate: use name_to_dev_t to parse resume") Signed-off-by: Christoph Hellwig <hch@lst.de> Acked-by: Rafael J. Wysocki <rafael@kernel.org> Link: https://lore.kernel.org/r/20230531125535.676098-22-hch@lst.de Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'kernel/power')
-rw-r--r--kernel/power/hibernate.c18
1 files changed, 17 insertions, 1 deletions
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
index c52dedb9f7c8..7ae95ec72f99 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -1178,7 +1178,23 @@ static ssize_t resume_store(struct kobject *kobj, struct kobj_attribute *attr,
if (!name)
return -ENOMEM;
- error = early_lookup_bdev(name, &dev);
+ error = lookup_bdev(name, &dev);
+ if (error) {
+ unsigned maj, min, offset;
+ char *p, dummy;
+
+ if (sscanf(name, "%u:%u%c", &maj, &min, &dummy) == 2 ||
+ sscanf(name, "%u:%u:%u:%c", &maj, &min, &offset,
+ &dummy) == 3) {
+ dev = MKDEV(maj, min);
+ if (maj != MAJOR(dev) || min != MINOR(dev))
+ error = -EINVAL;
+ } else {
+ dev = new_decode_dev(simple_strtoul(name, &p, 16));
+ if (*p)
+ error = -EINVAL;
+ }
+ }
kfree(name);
if (error)
return error;