* [PATCH 1/2] affs: generate OFS sequence numbers starting at 1
@ 2025-02-20 8:14 Simon Tatham
2025-02-20 8:14 ` [PATCH 2/2] affs: don't write overlarge OFS data block size fields Simon Tatham
2025-02-26 14:31 ` [PATCH 1/2] affs: generate OFS sequence numbers starting at 1 David Sterba
0 siblings, 2 replies; 3+ messages in thread
From: Simon Tatham @ 2025-02-20 8:14 UTC (permalink / raw)
To: David Sterba, linux-fsdevel, linux-kernel; +Cc: Simon Tatham
If I write a file to an OFS floppy image, and try to read it back on
an emulated Amiga running Workbench 1.3, the Amiga reports a disk
error trying to read the file. (That is, it's unable to read it _at
all_, even to copy it to the NIL: device. It isn't a matter of getting
the wrong data and being unable to parse the file format.)
This is because the 'sequence number' field in the OFS data block
header is supposed to be based at 1, but affs writes it based at 0.
All three locations changed by this patch were setting the sequence
number to a variable 'bidx' which was previously obtained by dividing
a file position by bsize, so bidx will naturally use 0 for the first
block. Therefore all three should add 1 to that value before writing
it into the sequence number field.
With this change, the Amiga successfully reads the file.
Signed-off-by: Simon Tatham <anakin@pobox.com>
---
fs/affs/file.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/fs/affs/file.c b/fs/affs/file.c
index a5a861dd5223..226308f8627e 100644
--- a/fs/affs/file.c
+++ b/fs/affs/file.c
@@ -596,7 +596,7 @@ affs_extent_file_ofs(struct inode *inode, u32 newsize)
BUG_ON(tmp > bsize);
AFFS_DATA_HEAD(bh)->ptype = cpu_to_be32(T_DATA);
AFFS_DATA_HEAD(bh)->key = cpu_to_be32(inode->i_ino);
- AFFS_DATA_HEAD(bh)->sequence = cpu_to_be32(bidx);
+ AFFS_DATA_HEAD(bh)->sequence = cpu_to_be32(bidx + 1);
AFFS_DATA_HEAD(bh)->size = cpu_to_be32(tmp);
affs_fix_checksum(sb, bh);
bh->b_state &= ~(1UL << BH_New);
@@ -746,7 +746,7 @@ static int affs_write_end_ofs(struct file *file, struct address_space *mapping,
if (buffer_new(bh)) {
AFFS_DATA_HEAD(bh)->ptype = cpu_to_be32(T_DATA);
AFFS_DATA_HEAD(bh)->key = cpu_to_be32(inode->i_ino);
- AFFS_DATA_HEAD(bh)->sequence = cpu_to_be32(bidx);
+ AFFS_DATA_HEAD(bh)->sequence = cpu_to_be32(bidx + 1);
AFFS_DATA_HEAD(bh)->size = cpu_to_be32(bsize);
AFFS_DATA_HEAD(bh)->next = 0;
bh->b_state &= ~(1UL << BH_New);
@@ -780,7 +780,7 @@ static int affs_write_end_ofs(struct file *file, struct address_space *mapping,
if (buffer_new(bh)) {
AFFS_DATA_HEAD(bh)->ptype = cpu_to_be32(T_DATA);
AFFS_DATA_HEAD(bh)->key = cpu_to_be32(inode->i_ino);
- AFFS_DATA_HEAD(bh)->sequence = cpu_to_be32(bidx);
+ AFFS_DATA_HEAD(bh)->sequence = cpu_to_be32(bidx + 1);
AFFS_DATA_HEAD(bh)->size = cpu_to_be32(tmp);
AFFS_DATA_HEAD(bh)->next = 0;
bh->b_state &= ~(1UL << BH_New);
--
2.43.0
^ permalink raw reply related [flat|nested] 3+ messages in thread* [PATCH 2/2] affs: don't write overlarge OFS data block size fields
2025-02-20 8:14 [PATCH 1/2] affs: generate OFS sequence numbers starting at 1 Simon Tatham
@ 2025-02-20 8:14 ` Simon Tatham
2025-02-26 14:31 ` [PATCH 1/2] affs: generate OFS sequence numbers starting at 1 David Sterba
1 sibling, 0 replies; 3+ messages in thread
From: Simon Tatham @ 2025-02-20 8:14 UTC (permalink / raw)
To: David Sterba, linux-fsdevel, linux-kernel; +Cc: Simon Tatham
If a data sector on an OFS floppy contains a value > 0x1e8 (the
largest amount of data that fits in the sector after its header), then
an Amiga reading the file can return corrupt data, by taking the
overlarge size at its word and reading past the end of the buffer it
read the disk sector into!
The cause: when affs_write_end_ofs() writes data to an OFS filesystem,
the new size field for a data block was computed by adding the amount
of data currently being written (into the block) to the existing value
of the size field. This is correct if you're extending the file at the
end, but if you seek backwards in the file and overwrite _existing_
data, it can lead to the size field being larger than the maximum
legal value.
This commit changes the calculation so that it sets the size field to
the max of its previous size and the position within the block that we
just wrote up to.
Signed-off-by: Simon Tatham <anakin@pobox.com>
---
fs/affs/file.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/fs/affs/file.c b/fs/affs/file.c
index 226308f8627e..7a71018e3f67 100644
--- a/fs/affs/file.c
+++ b/fs/affs/file.c
@@ -724,7 +724,8 @@ static int affs_write_end_ofs(struct file *file, struct address_space *mapping,
tmp = min(bsize - boff, to - from);
BUG_ON(boff + tmp > bsize || tmp > bsize);
memcpy(AFFS_DATA(bh) + boff, data + from, tmp);
- be32_add_cpu(&AFFS_DATA_HEAD(bh)->size, tmp);
+ AFFS_DATA_HEAD(bh)->size = cpu_to_be32(
+ max(boff + tmp, be32_to_cpu(AFFS_DATA_HEAD(bh)->size)));
affs_fix_checksum(sb, bh);
mark_buffer_dirty_inode(bh, inode);
written += tmp;
--
2.43.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH 1/2] affs: generate OFS sequence numbers starting at 1
2025-02-20 8:14 [PATCH 1/2] affs: generate OFS sequence numbers starting at 1 Simon Tatham
2025-02-20 8:14 ` [PATCH 2/2] affs: don't write overlarge OFS data block size fields Simon Tatham
@ 2025-02-26 14:31 ` David Sterba
1 sibling, 0 replies; 3+ messages in thread
From: David Sterba @ 2025-02-26 14:31 UTC (permalink / raw)
To: Simon Tatham; +Cc: David Sterba, linux-fsdevel, linux-kernel
On Thu, Feb 20, 2025 at 08:14:43AM +0000, Simon Tatham wrote:
> If I write a file to an OFS floppy image, and try to read it back on
> an emulated Amiga running Workbench 1.3, the Amiga reports a disk
> error trying to read the file. (That is, it's unable to read it _at
> all_, even to copy it to the NIL: device. It isn't a matter of getting
> the wrong data and being unable to parse the file format.)
>
> This is because the 'sequence number' field in the OFS data block
> header is supposed to be based at 1, but affs writes it based at 0.
> All three locations changed by this patch were setting the sequence
> number to a variable 'bidx' which was previously obtained by dividing
> a file position by bsize, so bidx will naturally use 0 for the first
> block. Therefore all three should add 1 to that value before writing
> it into the sequence number field.
>
> With this change, the Amiga successfully reads the file.
>
> Signed-off-by: Simon Tatham <anakin@pobox.com>
Thanks for the fixes, I'll send them for merge soon and to stable as
well as they're both real fixes. I found the sequence documented at
https://wiki.osdev.org/FFS_(Amiga) so I added the reference to the
changelog.
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2025-02-26 14:31 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-02-20 8:14 [PATCH 1/2] affs: generate OFS sequence numbers starting at 1 Simon Tatham
2025-02-20 8:14 ` [PATCH 2/2] affs: don't write overlarge OFS data block size fields Simon Tatham
2025-02-26 14:31 ` [PATCH 1/2] affs: generate OFS sequence numbers starting at 1 David Sterba
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox