aboutsummaryrefslogtreecommitdiff
path: root/sys/fs
diff options
context:
space:
mode:
authorAlan Somers <asomers@FreeBSD.org>2022-05-04 23:36:17 +0000
committerAlan Somers <asomers@FreeBSD.org>2022-05-12 20:32:26 +0000
commit0bef4927ea858bb18b6f679bc0a36cff264dc842 (patch)
treecfec5e4bcaab80a4c7a629d44777d125ea9cea0e /sys/fs
parent8b582b16402102df10a715c626e212bbbc8e9d7c (diff)
downloadsrc-0bef4927ea858bb18b6f679bc0a36cff264dc842.tar.gz
src-0bef4927ea858bb18b6f679bc0a36cff264dc842.zip
Diffstat (limited to 'sys/fs')
-rw-r--r--sys/fs/fuse/fuse_ipc.h1
-rw-r--r--sys/fs/fuse/fuse_node.c6
-rw-r--r--sys/fs/fuse/fuse_vnops.c27
3 files changed, 31 insertions, 3 deletions
diff --git a/sys/fs/fuse/fuse_ipc.h b/sys/fs/fuse/fuse_ipc.h
index fe616b3639a7..31e8b41b6ca3 100644
--- a/sys/fs/fuse/fuse_ipc.h
+++ b/sys/fs/fuse/fuse_ipc.h
@@ -240,6 +240,7 @@ struct fuse_data {
#define FSESS_WARN_LSEXTATTR_LONG 0x100000 /* Returned too many extattrs */
#define FSESS_WARN_CACHE_INCOHERENT 0x200000 /* Read cache incoherent */
#define FSESS_WARN_WB_CACHE_INCOHERENT 0x400000 /* WB cache incoherent */
+#define FSESS_WARN_ILLEGAL_INODE 0x800000 /* Illegal inode for new file */
#define FSESS_MNTOPTS_MASK ( \
FSESS_DAEMON_CAN_SPY | FSESS_PUSH_SYMLINKS_IN | \
FSESS_DEFAULT_PERMISSIONS | FSESS_INTR)
diff --git a/sys/fs/fuse/fuse_node.c b/sys/fs/fuse/fuse_node.c
index ca20c71eeae3..4d207f9c1365 100644
--- a/sys/fs/fuse/fuse_node.c
+++ b/sys/fs/fuse/fuse_node.c
@@ -298,6 +298,12 @@ fuse_vnode_get(struct mount *mp,
uint64_t generation = feo ? feo->generation : 0;
int err = 0;
+ if (dvp != NULL && VTOFUD(dvp)->nid == nodeid) {
+ fuse_warn(fuse_get_mpdata(mp), FSESS_WARN_ILLEGAL_INODE,
+ "Assigned same inode to both parent and child.");
+ return EIO;
+ }
+
err = fuse_vnode_alloc(mp, td, nodeid, vtyp, vpp);
if (err) {
return err;
diff --git a/sys/fs/fuse/fuse_vnops.c b/sys/fs/fuse/fuse_vnops.c
index 9ffc8f32c048..845ea04eca93 100644
--- a/sys/fs/fuse/fuse_vnops.c
+++ b/sys/fs/fuse/fuse_vnops.c
@@ -1327,6 +1327,16 @@ fuse_vnop_link(struct vop_link_args *ap)
}
feo = fdi.answ;
+ if (fli.oldnodeid != feo->nodeid) {
+ struct fuse_data *data = fuse_get_mpdata(vnode_mount(vp));
+ fuse_warn(data, FSESS_WARN_ILLEGAL_INODE,
+ "Assigned wrong inode for a hard link.");
+ fuse_vnode_clear_attr_cache(vp);
+ fuse_vnode_clear_attr_cache(tdvp);
+ err = EIO;
+ goto out;
+ }
+
err = fuse_internal_checkentry(feo, vnode_vtype(vp));
if (!err) {
/*
@@ -1386,6 +1396,7 @@ fuse_vnop_lookup(struct vop_lookup_args *ap)
struct mount *mp = vnode_mount(dvp);
struct fuse_data *data = fuse_get_mpdata(mp);
int default_permissions = data->dataflags & FSESS_DEFAULT_PERMISSIONS;
+ bool is_dot;
int err = 0;
int lookup_err = 0;
@@ -1413,6 +1424,7 @@ fuse_vnop_lookup(struct vop_lookup_args *ap)
else if ((err = fuse_internal_access(dvp, VEXEC, td, cred)))
return err;
+ is_dot = cnp->cn_namelen == 1 && *(cnp->cn_nameptr) == '.';
if ((flags & ISDOTDOT) && !(data->dataflags & FSESS_EXPORT_SUPPORT))
{
if (!(VTOFUD(dvp)->flag & FN_PARENT_NID)) {
@@ -1427,7 +1439,7 @@ fuse_vnop_lookup(struct vop_lookup_args *ap)
return ENOENT;
/* .. is obviously a directory */
vtyp = VDIR;
- } else if (cnp->cn_namelen == 1 && *(cnp->cn_nameptr) == '.') {
+ } else if (is_dot) {
nid = VTOI(dvp);
/* . is obviously a directory */
vtyp = VDIR;
@@ -1546,8 +1558,17 @@ fuse_vnop_lookup(struct vop_lookup_args *ap)
&vp);
*vpp = vp;
} else if (nid == VTOI(dvp)) {
- vref(dvp);
- *vpp = dvp;
+ if (is_dot) {
+ vref(dvp);
+ *vpp = dvp;
+ } else {
+ fuse_warn(fuse_get_mpdata(mp),
+ FSESS_WARN_ILLEGAL_INODE,
+ "Assigned same inode to both parent and "
+ "child.");
+ err = EIO;
+ }
+
} else {
struct fuse_vnode_data *fvdat;