Module Name: src Committed By: perseant Date: Mon Sep 9 05:01:57 UTC 2024
Modified Files: src/sys/fs/exfatfs [perseant-exfatfs]: exfatfs_inode.h exfatfs_vnops.c Log Message: Add a flag XI_DELETED to mark a directory deleted so that it is no longer accessible as "..", to pass t_vnops case dir_rmdirdotdot. Use genfs_can_chmod to test permissions for chmod, rather than genfs_can_chflags. Don't allow files to be removed from a read-only filesystem. Fix some integer width issues in debug printfs. To generate a diff of this commit: cvs rdiff -u -r1.1.2.4 -r1.1.2.5 src/sys/fs/exfatfs/exfatfs_inode.h cvs rdiff -u -r1.1.2.10 -r1.1.2.11 src/sys/fs/exfatfs/exfatfs_vnops.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/fs/exfatfs/exfatfs_inode.h diff -u src/sys/fs/exfatfs/exfatfs_inode.h:1.1.2.4 src/sys/fs/exfatfs/exfatfs_inode.h:1.1.2.5 --- src/sys/fs/exfatfs/exfatfs_inode.h:1.1.2.4 Fri Jul 19 16:19:15 2024 +++ src/sys/fs/exfatfs/exfatfs_inode.h Mon Sep 9 05:01:57 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: exfatfs_inode.h,v 1.1.2.4 2024/07/19 16:19:15 perseant Exp $ */ +/* $NetBSD: exfatfs_inode.h,v 1.1.2.5 2024/09/09 05:01:57 perseant Exp $ */ /*- * Copyright (c) 2022, 2024 The NetBSD Foundation, Inc. @@ -336,6 +336,7 @@ void exfatfs_check_fence(struct exfatfs #define XI_ACCESS 0x0004 /* Access time update */ #define XI_MODIFIED 0x0008 /* Xfinode has been modified. */ #define XI_RENAME 0x0010 /* Xfinode is being renamed */ +#define XI_DELETED 0x0020 /* Invalid, deleted */ #define EXFATFS_MAXNAMELEN 255 Index: src/sys/fs/exfatfs/exfatfs_vnops.c diff -u src/sys/fs/exfatfs/exfatfs_vnops.c:1.1.2.10 src/sys/fs/exfatfs/exfatfs_vnops.c:1.1.2.11 --- src/sys/fs/exfatfs/exfatfs_vnops.c:1.1.2.10 Wed Aug 14 15:37:49 2024 +++ src/sys/fs/exfatfs/exfatfs_vnops.c Mon Sep 9 05:01:57 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: exfatfs_vnops.c,v 1.1.2.10 2024/08/14 15:37:49 perseant Exp $ */ +/* $NetBSD: exfatfs_vnops.c,v 1.1.2.11 2024/09/09 05:01:57 perseant Exp $ */ /*- * Copyright (c) 2022 The NetBSD Foundation, Inc. @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: exfatfs_vnops.c,v 1.1.2.10 2024/08/14 15:37:49 perseant Exp $"); +__KERNEL_RCSID(0, "$NetBSD: exfatfs_vnops.c,v 1.1.2.11 2024/09/09 05:01:57 perseant Exp $"); #include <sys/buf.h> #include <sys/dirent.h> @@ -257,10 +257,8 @@ exfatfs_setattr(void *v) * Note we silently ignore uid or gid changes. */ if ((vap->va_type != VNON) || (vap->va_nlink != (nlink_t)VNOVAL) || -#if 0 (vap->va_uid != VNOVAL && vap->va_uid != fs->xf_uid) || (vap->va_gid != VNOVAL && vap->va_gid != fs->xf_gid) || -#endif /* 0 */ (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) || (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) || (vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) { @@ -313,8 +311,9 @@ exfatfs_setattr(void *v) error = EROFS; goto bad; } - error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_FLAGS, vp, - NULL, genfs_can_chflags(vp, cred, fs->xf_uid, false)); + error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_SECURITY, + vp, NULL, genfs_can_chmod(vp, cred, fs->xf_uid, + fs->xf_gid, false)); if (error) goto bad; /* We ignore the read and execute bits. */ @@ -732,6 +731,8 @@ exfatfs_remove(void *v) printf("remove 0x%x...\n", TRACE_INUM); #endif /* TRACE_INUM */ + if (vp->v_mount->mnt_flag & MNT_RDONLY) + return EROFS; if (vp->v_type == VDIR) return EISDIR; @@ -947,7 +948,7 @@ havespace: return error; DPRINTF(("new empty space at byte %lld (entry %u)\n", - (long long)r, (unsigned)EXFATFS_B2DIRENT(r))); + (long long)r, (unsigned)EXFATFS_B2DIRENT(fs, r))); /* * Assign disk addresses @@ -1180,7 +1181,7 @@ static unsigned first_valid_file(void *v ++*intp; DPRINTF(("found valid file ino 0x%lx with ET 0x%hhx\n", - INUM(xip), xip->xi_direntp[0]->xd_entryType)); + (unsigned long)INUM(xip), xip->xi_direntp[0]->xd_entryType)); return SCANDIR_STOP; } @@ -1258,6 +1259,10 @@ exfatfs_rmdir(void *v) new_key.dk_dirgen = xip; exfatfs_rekey(vp, &new_key); + /* Don't allow ".." to refer to this node anymore */ + DPRINTF(("exfatfs_rmdir(), mark vp/xip %p/%p DELETED\n", vp, xip)); + xip->xi_flag |= XI_DELETED; + /* * This is where we decrement the link count in the parent * directory. Since dos filesystems don't do this we just purge @@ -1423,6 +1428,12 @@ exfatfs_lookup(void *v) } } #endif /* TRACE_INUM */ + if (*vpp != NULLVP && (VTOXI(*vpp)->xi_flag & XI_DELETED)) { + DPRINTF(("exfatfs_lookup refusing deleted cached node\n")); + VOP_UNLOCK(*vpp); + vrele(*vpp); + return ENOENT; + } DPRINTF((" returning cached result\n")); return *vpp == NULLVP ? ENOENT : 0; } @@ -1450,6 +1461,13 @@ exfatfs_lookup(void *v) /* .., but not root's: we want parentvp. */ KASSERT(dxip->xi_parentvp != NULL); + DPRINTF(("exfatfs_lookup(), parent vp/xip %p/%p flags %x\n", + dxip->xi_parentvp, VTOXI(dxip->xi_parentvp), + (int)VTOXI(dxip->xi_parentvp)->xi_flag)); + if (VTOXI(dxip->xi_parentvp)->xi_flag & XI_DELETED) { + DPRINTF(("exfatfs_lookup refusing deleted ..\n")); + return ENOENT; + } *vpp = dxip->xi_parentvp; vref(*vpp); @@ -2569,7 +2587,8 @@ deextend(struct xfinode *xip, off_t byte if (pcn != opcn + 1 && IS_DSE_NOFATCHAIN(xip)) { DPRINTF(("inum 0x%lx not consecutive" " with 0x%x != 0x%x+1\n", - INUM(xip), pcn, opcn)); + (unsigned long)INUM(xip), + pcn, opcn)); CLR_DSE_NOFATCHAIN(xip); if ((error = rewrite_fat(xip, lcn, ioflags)) != 0) return error;