aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorAlan Somers <asomers@FreeBSD.org>2026-05-04 19:35:11 +0000
committerMark Johnston <markj@FreeBSD.org>2026-05-20 02:17:57 +0000
commit6a299460f159e4ed7e7ffa1e717fc2f473ea9e79 (patch)
tree73ccfe863d94ab273f9b1040e9ccc9f1efc43c9a /sys
parent8d8694c224e2ddc632583c9327415b4c15a1a52a (diff)
Diffstat (limited to 'sys')
-rw-r--r--sys/fs/fuse/fuse_ipc.h1
-rw-r--r--sys/fs/fuse/fuse_vnops.c17
2 files changed, 12 insertions, 6 deletions
diff --git a/sys/fs/fuse/fuse_ipc.h b/sys/fs/fuse/fuse_ipc.h
index 3bfc859dbac9..ca70177d049a 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_READLINK_EMBEDDED_NUL 0x1000000 /* corrupt READLINK output */
#define FSESS_WARN_DOT_LOOKUP 0x2000000 /* Inconsistent . LOOKUP response */
#define FSESS_WARN_INODE_MISMATCH 0x4000000 /* ino != nodeid */
+#define FSESS_WARN_LSEXTATTR_NUL 0x20000000 /* Non nul-terminated xattr list */
#define FSESS_MNTOPTS_MASK ( \
FSESS_DAEMON_CAN_SPY | FSESS_PUSH_SYMLINKS_IN | \
FSESS_DEFAULT_PERMISSIONS | FSESS_INTR)
diff --git a/sys/fs/fuse/fuse_vnops.c b/sys/fs/fuse/fuse_vnops.c
index e400d02887fd..ba72a21c8efe 100644
--- a/sys/fs/fuse/fuse_vnops.c
+++ b/sys/fs/fuse/fuse_vnops.c
@@ -2794,8 +2794,8 @@ out:
* bsd_list, bsd_list_len - output list compatible with bsd vfs
*/
static int
-fuse_xattrlist_convert(char *prefix, const char *list, int list_len,
- char *bsd_list, int *bsd_list_len)
+fuse_xattrlist_convert(struct fuse_data *data, char *prefix, const char *list,
+ int list_len, char *bsd_list, int *bsd_list_len)
{
int len, pos, dist_to_next, prefix_len;
@@ -2804,7 +2804,13 @@ fuse_xattrlist_convert(char *prefix, const char *list, int list_len,
prefix_len = strlen(prefix);
while (pos < list_len && list[pos] != '\0') {
- dist_to_next = strlen(&list[pos]) + 1;
+ dist_to_next = strnlen(&list[pos], list_len - pos - 1) + 1;
+ if (list[pos + dist_to_next - 1] != '\0') {
+ fuse_warn(data, FSESS_WARN_LSEXTATTR_NUL,
+ "The FUSE server returned a non nul-terminated "
+ "LISTXATTR response.");
+ return (EIO);
+ }
if (bcmp(&list[pos], prefix, prefix_len) == 0 &&
list[pos + prefix_len] == extattr_namespace_separator) {
len = dist_to_next -
@@ -2860,6 +2866,7 @@ fuse_vnop_listextattr(struct vop_listextattr_args *ap)
struct fuse_listxattr_in *list_xattr_in;
struct fuse_listxattr_out *list_xattr_out;
struct mount *mp = vnode_mount(vp);
+ struct fuse_data *data = fuse_get_mpdata(mp);
struct thread *td = ap->a_td;
struct ucred *cred = ap->a_cred;
char *prefix;
@@ -2937,8 +2944,6 @@ fuse_vnop_listextattr(struct vop_listextattr_args *ap)
linux_list = fdi.answ;
/* FUSE doesn't allow the server to return more data than requested */
if (fdi.iosize > linux_list_len) {
- struct fuse_data *data = fuse_get_mpdata(mp);
-
fuse_warn(data, FSESS_WARN_LSEXTATTR_LONG,
"server returned "
"more extended attribute data than requested; "
@@ -2955,7 +2960,7 @@ fuse_vnop_listextattr(struct vop_listextattr_args *ap)
* FreeBSD's format before giving it to the user.
*/
bsd_list = malloc(linux_list_len, M_TEMP, M_WAITOK);
- err = fuse_xattrlist_convert(prefix, linux_list, linux_list_len,
+ err = fuse_xattrlist_convert(data, prefix, linux_list, linux_list_len,
bsd_list, &bsd_list_len);
if (err != 0)
goto out;