summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2016-01-26 19:02:12 +0100
committerLennart Poettering <lennart@poettering.net>2016-01-27 02:21:28 +0100
commita90fb858ac91de4c14c9b68da6060731954515b7 (patch)
tree3e458d4a53d309c5cec38c16e9457f3969cf8ab2
parent05e8f270a9ca97e1014184df113494b143639fb8 (diff)
machined: add early checks for unrealistically large image/pool sizes
-rw-r--r--src/basic/btrfs-util.c5
-rw-r--r--src/basic/io-util.h18
-rw-r--r--src/machine/image-dbus.c3
-rw-r--r--src/machine/machined-dbus.c3
4 files changed, 29 insertions, 0 deletions
diff --git a/src/basic/btrfs-util.c b/src/basic/btrfs-util.c
index d07d1df5a8..03c7609c92 100644
--- a/src/basic/btrfs-util.c
+++ b/src/basic/btrfs-util.c
@@ -43,6 +43,7 @@
#include "copy.h"
#include "fd-util.h"
#include "fileio.h"
+#include "io-util.h"
#include "macro.h"
#include "missing.h"
#include "path-util.h"
@@ -913,6 +914,10 @@ int btrfs_resize_loopback_fd(int fd, uint64_t new_size, bool grow_only) {
dev_t dev = 0;
int r;
+ /* In contrast to btrfs quota ioctls ftruncate() cannot make sense of "infinity" or file sizes > 2^31 */
+ if (!FILE_SIZE_VALID(new_size))
+ return -EINVAL;
+
/* btrfs cannot handle file systems < 16M, hence use this as minimum */
if (new_size < 16*1024*1024)
new_size = 16*1024*1024;
diff --git a/src/basic/io-util.h b/src/basic/io-util.h
index 5f77a556c0..7d0d2bd810 100644
--- a/src/basic/io-util.h
+++ b/src/basic/io-util.h
@@ -77,3 +77,21 @@ static inline size_t IOVEC_INCREMENT(struct iovec *i, unsigned n, size_t k) {
return k;
}
+
+static inline bool FILE_SIZE_VALID(uint64_t l) {
+ /* ftruncate() and friends take an unsigned file size, but actually cannot deal with file sizes larger than
+ * 2^63 since the kernel internally handles it as signed value. This call allows checking for this early. */
+
+ return (l >> 63) == 0;
+}
+
+static inline bool FILE_SIZE_VALID_OR_INFINITY(uint64_t l) {
+
+ /* Same as above, but allows one extra value: -1 as indication for infinity. */
+
+ if (l == (uint64_t) -1)
+ return true;
+
+ return FILE_SIZE_VALID(l);
+
+}
diff --git a/src/machine/image-dbus.c b/src/machine/image-dbus.c
index 4ec1766033..19388b016a 100644
--- a/src/machine/image-dbus.c
+++ b/src/machine/image-dbus.c
@@ -23,6 +23,7 @@
#include "bus-label.h"
#include "bus-util.h"
#include "image-dbus.h"
+#include "io-util.h"
#include "machine-image.h"
#include "strv.h"
#include "user-util.h"
@@ -195,6 +196,8 @@ int bus_image_method_set_limit(
r = sd_bus_message_read(message, "t", &limit);
if (r < 0)
return r;
+ if (!FILE_SIZE_VALID_OR_INFINITY(limit))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "New limit out of range");
r = bus_verify_polkit_async(
message,
diff --git a/src/machine/machined-dbus.c b/src/machine/machined-dbus.c
index 521043f6a3..6cb70af3aa 100644
--- a/src/machine/machined-dbus.c
+++ b/src/machine/machined-dbus.c
@@ -34,6 +34,7 @@
#include "formats-util.h"
#include "hostname-util.h"
#include "image-dbus.h"
+#include "io-util.h"
#include "machine-dbus.h"
#include "machine-image.h"
#include "machine-pool.h"
@@ -813,6 +814,8 @@ static int method_set_pool_limit(sd_bus_message *message, void *userdata, sd_bus
r = sd_bus_message_read(message, "t", &limit);
if (r < 0)
return r;
+ if (!FILE_SIZE_VALID_OR_INFINITY(limit))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "New limit out of range");
r = bus_verify_polkit_async(
message,