From: Yadavendra Yadav Date: Wed, 7 Jul 2021 16:32:36 +0000 (-0400) Subject: LINUX: defer afs_remunlink when current->fs==NULL X-Git-Url: https://git.openafs.org/?p=openafs.git;a=commitdiff_plain;h=9e043e1a0cdca7624de3e27872273263c57027ed;hp=9656a6b92b86849aa964529947bacb5aea4d83eb LINUX: defer afs_remunlink when current->fs==NULL afs_remunlink is called to delete a file on the fileserver after it has been silly-renamed (due to being unlinked while the file is open). Sometimes current->fs is NULL when this happens, typically when the process is shutting down, after current->fs has been freed and file handles are getting released. During afs_remunlink, we need to interact with our cache files, and so we call dentry_open, which calls security_file_open, which calls into the configured LSM for security checks. Certain LSMs (e.g. Crowdstrike Falcon) will panic the kernel in this situation if current->fs is NULL. There's no way to skip the LSM hooks, or to flag to the LSM that we're making an in-kernel VFS call, so the only way to avoid these panics is to do our I/O in another thread. Fortunately, we already have a way to defer afs_remunlink calls to a background daemon (CUnlinkedDel), since we already do this in some cases (when someone else is holding afs_xvcache or afs_xdcache). So, to avoid the panic in the above scenario, defer calls to afs_remunlink to a background daemon using CUnlinkedDel when current->fs is NULL, and we're using a disk cache. More details on this issue is discussed at following thread: https://lists.openafs.org/pipermail/openafs-info/2021-March/043073.html Change-Id: I1ee83d088a9b661d2974ce24b36bfd9f6ea4e7e9 Reviewed-on: https://gerrit.openafs.org/14691 Tested-by: BuildBot Tested-by: Jonathan Billings Reviewed-by: Benjamin Kaduk Reviewed-by: Andrew Deason --- diff --git a/src/afs/LINUX/osi_vcache.c b/src/afs/LINUX/osi_vcache.c index 0d810b1..478602b 100644 --- a/src/afs/LINUX/osi_vcache.c +++ b/src/afs/LINUX/osi_vcache.c @@ -251,3 +251,32 @@ osi_vnhold(struct vcache *avc) VN_HOLD(AFSTOV(avc)); return 0; } + +/** + * Should we defer calling afs_remunlink(avc) to a background daemon, or can we + * call it in the current process? + * + * @param[in] avc The vcache we're going to call afs_remunlink on + * + * @retval 0 call afs_remunlink in the current task + * @retval 1 call afs_remunlink in the background + */ +int +osi_ShouldDeferRemunlink(struct vcache *avc) +{ + if (cacheDiskType == AFS_FCACHE_TYPE_UFS && current->fs == NULL) { + /* + * If current->fs is NULL (which can happen when the current process is + * in the middle of exiting), then calling dentry_open can result in a + * kernel panic with certain LSMs (e.g. Crowdstrike Falcon). + * + * If we have a disk cache, calling afs_remunlink generally involves + * calling dentry_open, since we need to interact with the disk cache, + * and so calling afs_remunlink can cause a panic. So, make sure we + * defer afs_remunlink to a background daemon, where current->fs is not + * NULL, and so it won't panic the machine. + */ + return 1; + } + return 0; +} diff --git a/src/afs/afs_osi.h b/src/afs/afs_osi.h index 4dc6101..f8a6316 100644 --- a/src/afs/afs_osi.h +++ b/src/afs/afs_osi.h @@ -440,4 +440,10 @@ extern afs_ucred_t afs_osi_cred, *afs_osi_credp; #define AFS_NUMPAGGROUPS 2 #endif +#ifdef AFS_LINUX_ENV +extern int osi_ShouldDeferRemunlink(struct vcache *avc); +#else +# define osi_ShouldDeferRemunlink(avc) 0 +#endif + #endif /* _AFS_OSI_ */ diff --git a/src/afs/afs_vcache.c b/src/afs/afs_vcache.c index 80ddfb4..6ff81b9 100644 --- a/src/afs/afs_vcache.c +++ b/src/afs/afs_vcache.c @@ -322,7 +322,8 @@ afs_InactiveVCache(struct vcache *avc, afs_ucred_t *acred) avc->f.states &= ~CMAPPED; avc->f.states &= ~CDirty; /* Turn it off */ if (avc->f.states & CUnlinked) { - if (CheckLock(&afs_xvcache) || CheckLock(&afs_xdcache)) { + if (CheckLock(&afs_xvcache) || CheckLock(&afs_xdcache) || + osi_ShouldDeferRemunlink(avc)) { avc->f.states |= CUnlinkedDel; ReleaseWriteLock(&avc->lock); return;