From patchwork Thu Feb 20 08:14:43 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Tatham X-Patchwork-Id: 13983485 Received: from thyestes.tartarus.org (thyestes.tartarus.org [5.196.91.86]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 230471E9B16; Thu, 20 Feb 2025 08:42:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=5.196.91.86 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740040928; cv=none; b=ZCkGaM5K8NIKQHyPsYXkfK0r0oU7AqkQn1OD8+/FdASN5w97YhN3h+26BrgAF6prY8WP7TuOZ8hH5xICeNj6uORaxQN7qXAOe2IKXz8BjZQiFNRhl7MgS7S/cqK7j6+0Wx0TQlU91B+RVKhzDCDHlChfPRWi22dUnAUKbzBErZA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740040928; c=relaxed/simple; bh=oOY9pUPRU/LFLiFkT35A2NYgJ2ZtjzVml5WcxCpqw6E=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=YR0lRnO629Lk2Ll2VNru3pe4U7YYRTGahfxJFUv8+Ol9DXiqInmm/yscdk09ZFPqnKlSYDfkAI1rbwm+6kChSVYjAfuDuRYmI57G0yOt9bIgxC1S18wcmcmuomV6/CgX/zhrEyVcUfORw+CHTwKmGwALDd0DNyQQhSDG973mKbw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=pobox.com; spf=pass smtp.mailfrom=thyestes.tartarus.org; arc=none smtp.client-ip=5.196.91.86 Authentication-Results: smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=pobox.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=thyestes.tartarus.org Received: from simon by thyestes.tartarus.org with local (Exim 4.92) (envelope-from ) id 1tl1i6-0006oS-4s; Thu, 20 Feb 2025 08:15:06 +0000 From: Simon Tatham To: David Sterba , linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Simon Tatham Subject: [PATCH 1/2] affs: generate OFS sequence numbers starting at 1 Date: Thu, 20 Feb 2025 08:14:43 +0000 Message-ID: <20250220081444.3625446-1-anakin@pobox.com> X-Mailer: git-send-email 2.43.0 Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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 --- 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); From patchwork Thu Feb 20 08:14:44 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Tatham X-Patchwork-Id: 13983484 Received: from thyestes.tartarus.org (thyestes.tartarus.org [5.196.91.86]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 534841E571F; Thu, 20 Feb 2025 08:41:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=5.196.91.86 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740040915; cv=none; b=brtbo+DyfiaAy4fLZIDJRT6TB8gTuUbBFWhpLmSebuFUSFWsAbg5rRwTf9Wq75kTrs9krflt5J5l+mTLRdaFY4mXIES5rEfs8YXbi6U0XXc4YpNdRyVLNpAG408QvgFBsZIrnCvEpF3tUNNy6gnhK+Qm36h91Ni2ce9d7g9w5vs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740040915; c=relaxed/simple; bh=Aj+eHx0bj6t0Rq60hDFoNIBUfkKnLnCg3JxcsFiljsU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=sQ+mswKm4oW168F9fO5Dy3rBatX30bV8v2AS8nSbO/ol0C48oNmgV43vP+M8Na3we2V52ToQPrYxV8WGeVLXbBBtD9gZwuwdLtoxDuHxWaRJTaXI8nvBSaHW2tP/iDGmp9XHI3wp4T/+xJYcW7tgfKN7KunlB2UL/2kvSIcytGM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=pobox.com; spf=pass smtp.mailfrom=thyestes.tartarus.org; arc=none smtp.client-ip=5.196.91.86 Authentication-Results: smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=pobox.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=thyestes.tartarus.org Received: from simon by thyestes.tartarus.org with local (Exim 4.92) (envelope-from ) id 1tl1iA-0006rl-D8; Thu, 20 Feb 2025 08:15:10 +0000 From: Simon Tatham To: David Sterba , linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Simon Tatham Subject: [PATCH 2/2] affs: don't write overlarge OFS data block size fields Date: Thu, 20 Feb 2025 08:14:44 +0000 Message-ID: <20250220081444.3625446-2-anakin@pobox.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250220081444.3625446-1-anakin@pobox.com> References: <20250220081444.3625446-1-anakin@pobox.com> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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 --- 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;