mail archive of the barebox mailing list
 help / color / mirror / Atom feed
From: Andrey Smirnov <andrew.smirnov@gmail.com>
To: barebox@lists.infradead.org
Cc: Andrey Smirnov <andrew.smirnov@gmail.com>
Subject: [PATCH 6/7] fs: Add support for files larger than MAX_LFS_FILESIZE
Date: Tue, 22 Jan 2019 17:13:37 -0800	[thread overview]
Message-ID: <20190123011338.32517-7-andrew.smirnov@gmail.com> (raw)
In-Reply-To: <20190123011338.32517-1-andrew.smirnov@gmail.com>

On 64-bit platforms /dev/mem exceeds the size supported by loff_t and
needs special treatment within the rest of FS API. Specifically
lseek() needs to be modified to make sure it does the right thing.

Prievious attempt at fixing this issue by using IS_ERR_VALUE()

e10efc5080 ("fs: fix memory access via /dev/mem for MIPS64")

doesn't really work 100% on 64-bit platforms, becuase it still leaves
out a number of perfectly valid offsets (e.g. "md 0xffffffffffffff00"
doesn't work) . Moreso it breaks lseek() on 32-bit platforms, since
IS_ERR_VALUE will retrurn true for any offset that is >= (unsigned
long) -MAX_ERRNO.

In order to fix this issue on both 32 and 64 bit platforms, introduce
DEVFS_UNBOUNDED flag that cdevs can use to denote that they span all
64-bit address space and effectively have not limits. To propagate
that info to FS layer, add "unbounded" boolean to FILE. As a last step
modify lseek() to be aware of that field and do the right checks in
that case.

Note, that since loff_t has no problem covering all of address space
on 32-bit platforms, DEVFS_UNBOUNDED is defined to expand into 0 and
not be settable there.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 drivers/misc/mem.c |  1 +
 fs/devfs.c         |  2 ++
 fs/fs.c            | 29 +++++++++++++++++++++++++----
 include/driver.h   |  1 +
 include/fs.h       |  1 +
 5 files changed, 30 insertions(+), 4 deletions(-)

diff --git a/drivers/misc/mem.c b/drivers/misc/mem.c
index d829af724..b27865b9e 100644
--- a/drivers/misc/mem.c
+++ b/drivers/misc/mem.c
@@ -21,6 +21,7 @@ static int mem_probe(struct device_d *dev)
 	cdev = xzalloc(sizeof (*cdev));
 	dev->priv = cdev;
 
+	cdev->flags = DEVFS_UNBOUNDED;
 	cdev->name = (char*)dev->resource[0].name;
 	cdev->size = min_t(unsigned long long, resource_size(&dev->resource[0]),
 			   S64_MAX);
diff --git a/fs/devfs.c b/fs/devfs.c
index 81ae2c25a..68a5b7f23 100644
--- a/fs/devfs.c
+++ b/fs/devfs.c
@@ -120,6 +120,8 @@ static int devfs_open(struct device_d *_dev, FILE *f, const char *filename)
 	struct cdev *cdev = node->cdev;
 	int ret;
 
+
+	f->unbounded = cdev->flags & DEVFS_UNBOUNDED;
 	f->size = cdev->flags & DEVFS_IS_CHARACTER_DEV ?
 			FILE_SIZE_STREAM : cdev->size;
 	f->priv = cdev;
diff --git a/fs/fs.c b/fs/fs.c
index 9372b9981..48ca382df 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -422,20 +422,41 @@ loff_t lseek(int fildes, loff_t offset, int whence)
 	switch (whence) {
 	case SEEK_SET:
 		pos = offset;
+		if (unlikely(f->unbounded))
+			break;
 		if (f->size != FILE_SIZE_STREAM && offset > f->size)
 			goto out;
-		if (IS_ERR_VALUE(offset))
+		if (offset < 0)
 			goto out;
 		break;
 	case SEEK_CUR:
 		pos = f->pos + offset;
+		if (unlikely(f->unbounded)) {
+			/*
+			 * Check that we won't wrap around when
+			 * seeking
+			 */
+			u64 p, o;
+
+			p = f->pos;
+			o = offset;
+
+			if (p > U64_MAX - o)
+				goto out;
+			break;
+		}
+
 		if (f->size != FILE_SIZE_STREAM && pos > f->size)
 			goto out;
 		break;
 	case SEEK_END:
-		pos = f->size + offset;
-		if (offset > 0)
-			goto out;
+		if (unlikely(f->unbounded)) {
+			pos = U64_MAX - (u64)offset;
+		} else {
+			pos = f->size + offset;
+			if (offset > 0)
+				goto out;
+		}
 		break;
 	default:
 		goto out;
diff --git a/include/driver.h b/include/driver.h
index 3d9970df5..39bce0414 100644
--- a/include/driver.h
+++ b/include/driver.h
@@ -501,6 +501,7 @@ int cdev_erase(struct cdev *cdev, loff_t count, loff_t offset);
 #define DEVFS_PARTITION_READONLY	(1U << 1)
 #define DEVFS_IS_CHARACTER_DEV		(1 << 3)
 #define DEVFS_PARTITION_FROM_TABLE	(1 << 4)
+#define DEVFS_UNBOUNDED			(IS_ENABLED(CONFIG_CPU_64) << 5)
 
 struct cdev *devfs_add_partition(const char *devname, loff_t offset,
 		loff_t size, unsigned int flags, const char *name);
diff --git a/include/fs.h b/include/fs.h
index f1514afa9..5d1510838 100644
--- a/include/fs.h
+++ b/include/fs.h
@@ -31,6 +31,7 @@ typedef struct filep {
 	/* private fields. Mapping between FILE and filedescriptor number     */
 	int no;
 	char in_use;
+	bool unbounded;
 
 	struct inode *f_inode;
 	struct dentry *dentry;
-- 
2.20.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

  parent reply	other threads:[~2019-01-23  1:14 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-01-23  1:13 [PATCH 0/7] 32-bit lseek and /dev/mem fixes/improvements Andrey Smirnov
2019-01-23  1:13 ` [PATCH 1/7] commands: Move mem_parse_options() to lib/misc.c Andrey Smirnov
2019-01-23  1:13 ` [PATCH 2/7] commands: Get rid of mem_rw_buf Andrey Smirnov
2019-01-23  1:13 ` [PATCH 3/7] commands: Move /dev/mem driver to drivers/misc Andrey Smirnov
2019-01-23  1:13 ` [PATCH 4/7] fs: Change error checking logic for fsdrv->lseek() call Andrey Smirnov
2019-01-24  7:44   ` Sascha Hauer
2019-01-24 19:19     ` Andrey Smirnov
2019-01-23  1:13 ` [PATCH 5/7] fs: Calculate new position before validtiy check in lseek() Andrey Smirnov
2019-01-24  7:52   ` Sascha Hauer
2019-01-24 19:37     ` Andrey Smirnov
2019-01-23  1:13 ` Andrey Smirnov [this message]
2019-01-24  8:48   ` [PATCH 6/7] fs: Add support for files larger than MAX_LFS_FILESIZE Sascha Hauer
2019-01-24 19:43     ` Andrey Smirnov
2019-01-23  1:13 ` [PATCH 7/7] misc: mem: Set correct size for /dev/mem Andrey Smirnov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190123011338.32517-7-andrew.smirnov@gmail.com \
    --to=andrew.smirnov@gmail.com \
    --cc=barebox@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox