From bea68245ef5ccc6aef4c1a3abfe0c3600522e4ca Mon Sep 17 00:00:00 2001 From: Daniel Rosenberg Date: Tue, 15 Feb 2022 15:57:14 -0800 Subject: [PATCH] ANDROID: fuse-bpf: Fix filldir filldir used strcpy, potentially leading to writing the ending null past the current page. fuse_dirents are not null terminated, so we switch to using memcpy to avoid adding an extraneous null, which would be overwritten if the name was already byte aligned. Bug: 217570523 Test: generic/027 Signed-off-by: Daniel Rosenberg Change-Id: Ic5d1f1887a113e1a3319998bad47cfbac3d90baa --- fs/fuse/backing.c | 5 +++-- tools/testing/selftests/filesystems/fuse/fuse_test.c | 10 ++++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/fs/fuse/backing.c b/fs/fuse/backing.c index ae4eb9d66781..e2c31647307f 100644 --- a/fs/fuse/backing.c +++ b/fs/fuse/backing.c @@ -191,7 +191,8 @@ void *fuse_open_finalize(struct fuse_args *fa, struct fuse_file *ff = file->private_data; struct fuse_open_out *foo = fa->out_args[0].value; - ff->fh = foo->fh; + if (ff) + ff->fh = foo->fh; return 0; } @@ -1987,7 +1988,7 @@ static int filldir(struct dir_context *ctx, const char *name, int namelen, .type = d_type, }; - strcpy(fd->name, name); + memcpy(fd->name, name, namelen); ec->offset += FUSE_DIRENT_SIZE(fd); return 0; diff --git a/tools/testing/selftests/filesystems/fuse/fuse_test.c b/tools/testing/selftests/filesystems/fuse/fuse_test.c index 2f5c72d729d5..68a19808cbeb 100644 --- a/tools/testing/selftests/filesystems/fuse/fuse_test.c +++ b/tools/testing/selftests/filesystems/fuse/fuse_test.c @@ -524,12 +524,14 @@ static int bpf_test_redact_readdir(const char *mount_dir) bool is_dot; fuse_dirent_in = (struct fuse_dirent *) dirs_in; - is_dot = !strcmp(fuse_dirent_in->name, ".") || - !strcmp(fuse_dirent_in->name, ".."); + is_dot = (fuse_dirent_in->namelen == 1 && + !strncmp(fuse_dirent_in->name, ".", 1)) || + (fuse_dirent_in->namelen == 2 && + !strncmp(fuse_dirent_in->name, "..", 2)); dir_ent_len = FUSE_DIRENT_ALIGN( sizeof(*fuse_dirent_in) + - fuse_dirent_in->namelen + 1); + fuse_dirent_in->namelen); if (dirs_in + dir_ent_len < bytes_in + res) next = (struct fuse_dirent *) @@ -538,7 +540,7 @@ static int bpf_test_redact_readdir(const char *mount_dir) if (!skip || is_dot) { memcpy(dirs_out, fuse_dirent_in, sizeof(struct fuse_dirent) + - fuse_dirent_in->namelen + 1); + fuse_dirent_in->namelen); length_out += dir_ent_len; } again = ((skip && !is_dot) && next);