lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <1360667.1731086590@warthog.procyon.org.uk>
Date: Fri, 08 Nov 2024 17:23:10 +0000
From: David Howells <dhowells@...hat.com>
To: Christian Brauner <christian@...uner.io>,
    Steve French <smfrench@...il.com>,
    Matthew Wilcox <willy@...radead.org>
Cc: dhowells@...hat.com, Jeff Layton <jlayton@...nel.org>,
    Gao Xiang <hsiangkao@...ux.alibaba.com>,
    Dominique Martinet <asmadeus@...ewreck.org>,
    Marc Dionne <marc.dionne@...istor.com>,
    Paulo Alcantara <pc@...guebit.com>,
    Shyam Prasad N <sprasad@...rosoft.com>, Tom Talpey <tom@...pey.com>,
    Eric Van Hensbergen <ericvh@...nel.org>,
    Ilya Dryomov <idryomov@...il.com>, netfs@...ts.linux.dev,
    linux-afs@...ts.infradead.org, linux-cifs@...r.kernel.org,
    linux-nfs@...r.kernel.org, ceph-devel@...r.kernel.org,
    v9fs@...ts.linux.dev, linux-erofs@...ts.ozlabs.org,
    linux-fsdevel@...r.kernel.org, linux-mm@...ck.org,
    netdev@...r.kernel.org, linux-kernel@...r.kernel.org
Subject: Re: [PATCH v3 23/33] afs: Use netfslib for directories

The attached fix needs folding in across this patch (23), patch 24, patch
29 and patch 31.

David
---
commit 9d4429bc7bb3f2b518d6decd1ca0e99e4d80d58e
Author: David Howells <dhowells@...hat.com>
Date:   Thu Nov 7 23:46:48 2024 +0000

    afs: Fix handling of signals during readdir
    
    When a directory is being read, whether or not the dvnode->directory buffer
    pointer is NULL is used to track whether we've checked fscache yet.
    However, if a signal occurs after the buffer being allocated but whilst
    we're doing the read, we may end up in an invalid state with ->directory
    set but no data in the buffer.
    
    In this state, afs_readdir(), afs_lookup() and afs_d_revalidate() see
    corrupt directory contents leading to a variety of malfunctions.
    
    Fix this by providing a specific flag to record whether or not we've
    performed a read yet - and, incidentally, sampled fscache - rather than
    using the value in ->directory instead.
    
    Signed-off-by: David Howells <dhowells@...hat.com>
    cc: Marc Dionne <marc.dionne@...istor.com>
    cc: linux-afs@...ts.infradead.org

diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index 663a212964d8..b6a202fd9926 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -323,7 +323,7 @@ ssize_t afs_read_dir(struct afs_vnode *dvnode, struct file *file)
 	 * haven't read it yet.
 	 */
 	if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) &&
-	    dvnode->directory) {
+	    test_bit(AFS_VNODE_DIR_READ, &dvnode->flags)) {
 		ret = i_size;
 		goto valid;
 	}
@@ -336,7 +336,7 @@ ssize_t afs_read_dir(struct afs_vnode *dvnode, struct file *file)
 		afs_invalidate_cache(dvnode, 0);
 
 	if (!test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) ||
-	    !dvnode->directory) {
+	    !test_bit(AFS_VNODE_DIR_READ, &dvnode->flags)) {
 		trace_afs_reload_dir(dvnode);
 		ret = afs_read_single(dvnode, file);
 		if (ret < 0)
@@ -345,6 +345,7 @@ ssize_t afs_read_dir(struct afs_vnode *dvnode, struct file *file)
 		// TODO: Trim excess pages
 
 		set_bit(AFS_VNODE_DIR_VALID, &dvnode->flags);
+		set_bit(AFS_VNODE_DIR_READ, &dvnode->flags);
 	} else {
 		ret = i_size;
 	}
diff --git a/fs/afs/dir_edit.c b/fs/afs/dir_edit.c
index f6f4b1adc8dc..60a549f1d9c5 100644
--- a/fs/afs/dir_edit.c
+++ b/fs/afs/dir_edit.c
@@ -644,4 +644,5 @@ void afs_mkdir_init_dir(struct afs_vnode *dvnode, struct afs_vnode *parent_dvnod
 
 	netfs_single_mark_inode_dirty(&dvnode->netfs.inode);
 	set_bit(AFS_VNODE_DIR_VALID, &dvnode->flags);
+	set_bit(AFS_VNODE_DIR_READ, &dvnode->flags);
 }
diff --git a/fs/afs/inode.c b/fs/afs/inode.c
index f5618564b3fc..e9538e91f848 100644
--- a/fs/afs/inode.c
+++ b/fs/afs/inode.c
@@ -39,6 +39,7 @@ void afs_init_new_symlink(struct afs_vnode *vnode, struct afs_operation *op)
 	p = kmap_local_folio(folioq_folio(vnode->directory, 0), 0);
 	memcpy(p, op->create.symlink, size);
 	kunmap_local(p);
+	set_bit(AFS_VNODE_DIR_READ, &vnode->flags);
 	netfs_single_mark_inode_dirty(&vnode->netfs.inode);
 }
 
@@ -60,12 +61,12 @@ const char *afs_get_link(struct dentry *dentry, struct inode *inode,
 
 	if (!dentry) {
 		/* RCU pathwalk. */
-		if (!vnode->directory || !afs_check_validity(vnode))
+		if (!test_bit(AFS_VNODE_DIR_READ, &vnode->flags) || !afs_check_validity(vnode))
 			return ERR_PTR(-ECHILD);
 		goto good;
 	}
 
-	if (!vnode->directory)
+	if (test_bit(AFS_VNODE_DIR_READ, &vnode->flags))
 		goto fetch;
 
 	ret = afs_validate(vnode, NULL);
@@ -73,13 +74,14 @@ const char *afs_get_link(struct dentry *dentry, struct inode *inode,
 		return ERR_PTR(ret);
 
 	if (!test_and_clear_bit(AFS_VNODE_ZAP_DATA, &vnode->flags) &&
-	    vnode->directory)
+	    test_bit(AFS_VNODE_DIR_READ, &vnode->flags))
 		goto good;
 
 fetch:
 	ret = afs_read_single(vnode, NULL);
 	if (ret < 0)
 		return ERR_PTR(ret);
+	set_bit(AFS_VNODE_DIR_READ, &vnode->flags);
 
 good:
 	folio = folioq_folio(vnode->directory, 0);
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index a5da0dd8e9cc..90f407774a9a 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -705,6 +705,7 @@ struct afs_vnode {
 #define AFS_VNODE_NEW_CONTENT	8		/* Set if file has new content (create/trunc-0) */
 #define AFS_VNODE_SILLY_DELETED	9		/* Set if file has been silly-deleted */
 #define AFS_VNODE_MODIFYING	10		/* Set if we're performing a modification op */
+#define AFS_VNODE_DIR_READ	11		/* Set if we've read a dir's contents */
 
 	struct folio_queue	*directory;	/* Directory contents */
 	struct list_head	wb_keys;	/* List of keys available for writeback */


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ