* [pseudo] [PATCH] pseudo_client: Fix xattr/rename handling with empty paths @ 2026-10-14 19:38 Richard Purdie 2026-10-15 13:38 ` [yocto-patches] " Mathieu Dubois-Briand 0 siblings, 1 reply; 6+ messages in thread From: Richard Purdie @ 2026-10-14 19:38 UTC (permalink / raw) To: yocto-patches; +Cc: seebs, mark.hatle On Fedora45, we can end up in a situation where path_extra_1 (for xattr/rename ops) but path is of zero length. The path_extra_1 codepath does not handle this well and corrupts memory. The issue is "partial_len = pathlen - 1 - strip_slash" when pathlen is 0 (and hence strip_slash is also 0). This leads to invalid memory writes and if those happen to access off the end of a mapped segment, the program segfaults. Fix the code to handle the pathlen=0 case. Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org> --- pseudo_client.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/pseudo_client.c b/pseudo_client.c index 23d7b0f..002de30 100644 --- a/pseudo_client.c +++ b/pseudo_client.c @@ -1789,7 +1789,7 @@ pseudo_client_op(pseudo_op_t op, int access, int fd, int dirfd, const char *path */ if (path_extra_1) { size_t full_len = path_extra_1len + 1 + pathlen - strip_slash; - size_t partial_len = pathlen - 1 - strip_slash; + size_t partial_len = pathlen - strip_slash; if (path_extra_2) { full_len += path_extra_2len + 1; } @@ -1804,12 +1804,17 @@ pseudo_client_op(pseudo_op_t op, int access, int fd, int dirfd, const char *path return 0; } } - memcpy(alloced_path, path, partial_len); - alloced_path[partial_len] = '\0'; - memcpy(alloced_path + partial_len + 1, path_extra_1, path_extra_1len); - alloced_path[partial_len + path_extra_1len + 1] = '\0'; + if (pathlen) { + memcpy(alloced_path, path, partial_len - 1); + alloced_path[partial_len - 1] = '\0'; + } else { + alloced_path[0] = '\0'; + partial_len = 1; + } + memcpy(alloced_path + partial_len, path_extra_1, path_extra_1len); + alloced_path[partial_len + path_extra_1len] = '\0'; if (path_extra_2) { - memcpy(alloced_path + partial_len + path_extra_1len + 2, path_extra_2, path_extra_2len); + memcpy(alloced_path + partial_len + path_extra_1len + 1, path_extra_2, path_extra_2len); } alloced_path[full_len - 1] = '\0'; path = alloced_path; ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [yocto-patches] [pseudo] [PATCH] pseudo_client: Fix xattr/rename handling with empty paths 2026-10-14 19:38 [pseudo] [PATCH] pseudo_client: Fix xattr/rename handling with empty paths Richard Purdie @ 2026-10-15 13:38 ` Mathieu Dubois-Briand 2026-10-15 14:25 ` Richard Purdie 0 siblings, 1 reply; 6+ messages in thread From: Mathieu Dubois-Briand @ 2026-10-15 13:38 UTC (permalink / raw) To: yocto-patches; +Cc: seebs, mark.hatle On Wed Oct 14, 2026 at 9:38 PM CEST, Richard Purdie via lists.yoctoproject.org wrote: > On Fedora45, we can end up in a situation where path_extra_1 (for xattr/rename ops) > but path is of zero length. The path_extra_1 codepath does not handle this well and > corrupts memory. > > The issue is "partial_len = pathlen - 1 - strip_slash" when pathlen is 0 (and > hence strip_slash is also 0). This leads to invalid memory writes and if those > happen to access off the end of a mapped segment, the program segfaults. > > Fix the code to handle the pathlen=0 case. > > Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org> > --- > pseudo_client.c | 17 +++++++++++------ > 1 file changed, 11 insertions(+), 6 deletions(-) > > diff --git a/pseudo_client.c b/pseudo_client.c > index 23d7b0f..002de30 100644 > --- a/pseudo_client.c > +++ b/pseudo_client.c > @@ -1789,7 +1789,7 @@ pseudo_client_op(pseudo_op_t op, int access, int fd, int dirfd, const char *path > */ > if (path_extra_1) { > size_t full_len = path_extra_1len + 1 + pathlen - strip_slash; > - size_t partial_len = pathlen - 1 - strip_slash; > + size_t partial_len = pathlen - strip_slash; > if (path_extra_2) { > full_len += path_extra_2len + 1; > } > @@ -1804,12 +1804,17 @@ pseudo_client_op(pseudo_op_t op, int access, int fd, int dirfd, const char *path > return 0; > } > } > - memcpy(alloced_path, path, partial_len); > - alloced_path[partial_len] = '\0'; > - memcpy(alloced_path + partial_len + 1, path_extra_1, path_extra_1len); > - alloced_path[partial_len + path_extra_1len + 1] = '\0'; > + if (pathlen) { > + memcpy(alloced_path, path, partial_len - 1); > + alloced_path[partial_len - 1] = '\0'; > + } else { > + alloced_path[0] = '\0'; > + partial_len = 1; Err, I have a doubt here. Setting partial_len to 1 looks correct, but it was previously used to compute full_len, that is used to check the if buffer is big enough (full_len > alloced_len). So if pathlen is 0, the buffer can be 1 byte too short, right? Just incrementing partial_len a bit before should fix that. Thanks, Mathieu -- Mathieu Dubois-Briand, Bootlin Embedded Linux and Kernel engineering https://bootlin.com ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [yocto-patches] [pseudo] [PATCH] pseudo_client: Fix xattr/rename handling with empty paths 2026-10-15 13:38 ` [yocto-patches] " Mathieu Dubois-Briand @ 2026-10-15 14:25 ` Richard Purdie 2026-10-15 15:43 ` Mathieu Dubois-Briand 0 siblings, 1 reply; 6+ messages in thread From: Richard Purdie @ 2026-10-15 14:25 UTC (permalink / raw) To: yocto-patches; +Cc: seebs, mark.hatle On Thu, 2026-10-15 at 15:38 +0200, Mathieu Dubois-Briand via lists.yoctoproject.org wrote: > On Wed Oct 14, 2026 at 9:38 PM CEST, Richard Purdie via lists.yoctoproject.org wrote: > > On Fedora45, we can end up in a situation where path_extra_1 (for xattr/rename ops) > > but path is of zero length. The path_extra_1 codepath does not handle this well and > > corrupts memory. > > > > The issue is "partial_len = pathlen - 1 - strip_slash" when pathlen is 0 (and > > hence strip_slash is also 0). This leads to invalid memory writes and if those > > happen to access off the end of a mapped segment, the program segfaults. > > > > Fix the code to handle the pathlen=0 case. > > > > Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org> > > --- > > pseudo_client.c | 17 +++++++++++------ > > 1 file changed, 11 insertions(+), 6 deletions(-) > > > > diff --git a/pseudo_client.c b/pseudo_client.c > > index 23d7b0f..002de30 100644 > > --- a/pseudo_client.c > > +++ b/pseudo_client.c > > @@ -1789,7 +1789,7 @@ pseudo_client_op(pseudo_op_t op, int access, int fd, int dirfd, const char *path > > */ > > if (path_extra_1) { > > size_t full_len = path_extra_1len + 1 + pathlen - strip_slash; > > - size_t partial_len = pathlen - 1 - strip_slash; > > + size_t partial_len = pathlen - strip_slash; > > if (path_extra_2) { > > full_len += path_extra_2len + 1; > > } > > @@ -1804,12 +1804,17 @@ pseudo_client_op(pseudo_op_t op, int access, int fd, int dirfd, const char *path > > return 0; > > } > > } > > - memcpy(alloced_path, path, partial_len); > > - alloced_path[partial_len] = '\0'; > > - memcpy(alloced_path + partial_len + 1, path_extra_1, path_extra_1len); > > - alloced_path[partial_len + path_extra_1len + 1] = '\0'; > > + if (pathlen) { > > + memcpy(alloced_path, path, partial_len - 1); > > + alloced_path[partial_len - 1] = '\0'; > > + } else { > > + alloced_path[0] = '\0'; > > + partial_len = 1; > > Err, I have a doubt here. > > Setting partial_len to 1 looks correct, but it was previously used to > compute full_len, that is used to check the if buffer is big enough > (full_len > alloced_len). > > So if pathlen is 0, the buffer can be 1 byte too short, right? Just > incrementing partial_len a bit before should fix that. I can't see where partial_len is used in the computation for full_len ? size_t full_len = path_extra_1len + 1 + pathlen - strip_slash; size_t partial_len = pathlen - strip_slash; if (path_extra_2) { full_len += path_extra_2len + 1; } if (full_len > alloced_len) { <realloc code> } Cheers, Richard ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [yocto-patches] [pseudo] [PATCH] pseudo_client: Fix xattr/rename handling with empty paths 2026-10-15 14:25 ` Richard Purdie @ 2026-10-15 15:43 ` Mathieu Dubois-Briand 2026-10-15 21:54 ` Richard Purdie 0 siblings, 1 reply; 6+ messages in thread From: Mathieu Dubois-Briand @ 2026-10-15 15:43 UTC (permalink / raw) To: yocto-patches; +Cc: seebs, mark.hatle On Thu Oct 15, 2026 at 4:25 PM CEST, Richard Purdie via lists.yoctoproject.org wrote: > On Thu, 2026-10-15 at 15:38 +0200, Mathieu Dubois-Briand via lists.yoctoproject.org wrote: >> On Wed Oct 14, 2026 at 9:38 PM CEST, Richard Purdie via lists.yoctoproject.org wrote: >> > On Fedora45, we can end up in a situation where path_extra_1 (for xattr/rename ops) >> > but path is of zero length. The path_extra_1 codepath does not handle this well and >> > corrupts memory. >> > >> > The issue is "partial_len = pathlen - 1 - strip_slash" when pathlen is 0 (and >> > hence strip_slash is also 0). This leads to invalid memory writes and if those >> > happen to access off the end of a mapped segment, the program segfaults. >> > >> > Fix the code to handle the pathlen=0 case. >> > >> > Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org> >> > --- >> > pseudo_client.c | 17 +++++++++++------ >> > 1 file changed, 11 insertions(+), 6 deletions(-) >> > >> > diff --git a/pseudo_client.c b/pseudo_client.c >> > index 23d7b0f..002de30 100644 >> > --- a/pseudo_client.c >> > +++ b/pseudo_client.c >> > @@ -1789,7 +1789,7 @@ pseudo_client_op(pseudo_op_t op, int access, int fd, int dirfd, const char *path >> > */ >> > if (path_extra_1) { >> > size_t full_len = path_extra_1len + 1 + pathlen - strip_slash; >> > - size_t partial_len = pathlen - 1 - strip_slash; >> > + size_t partial_len = pathlen - strip_slash; >> > if (path_extra_2) { >> > full_len += path_extra_2len + 1; >> > } >> > @@ -1804,12 +1804,17 @@ pseudo_client_op(pseudo_op_t op, int access, int fd, int dirfd, const char *path >> > return 0; >> > } >> > } >> > - memcpy(alloced_path, path, partial_len); >> > - alloced_path[partial_len] = '\0'; >> > - memcpy(alloced_path + partial_len + 1, path_extra_1, path_extra_1len); >> > - alloced_path[partial_len + path_extra_1len + 1] = '\0'; >> > + if (pathlen) { >> > + memcpy(alloced_path, path, partial_len - 1); >> > + alloced_path[partial_len - 1] = '\0'; >> > + } else { >> > + alloced_path[0] = '\0'; >> > + partial_len = 1; >> >> Err, I have a doubt here. >> >> Setting partial_len to 1 looks correct, but it was previously used to >> compute full_len, that is used to check the if buffer is big enough >> (full_len > alloced_len). >> >> So if pathlen is 0, the buffer can be 1 byte too short, right? Just >> incrementing partial_len a bit before should fix that. > > I can't see where partial_len is used in the computation for full_len ? > > size_t full_len = path_extra_1len + 1 + pathlen - strip_slash; > size_t partial_len = pathlen - strip_slash; > if (path_extra_2) { > full_len += path_extra_2len + 1; > } > if (full_len > alloced_len) { > <realloc code> > } > > Cheers, > > Richard > Yes, sorry, my previous mail does not make any sense. Let's try that again. So my point is, if pathlen is 0, we have: > size_t full_len = path_extra_1len + 1 + pathlen - strip_slash; So full_len is going to be: path_extra_1len + 1 + 0 (pathlen) - strip_slash So it will be at most: path_extra_1len + 1 > size_t partial_len = pathlen - strip_slash; > if (path_extra_2) { > full_len += path_extra_2len + 1; > } > if (full_len > alloced_len) { > free(alloced_path); > alloced_path = malloc(full_len); > alloced_len = full_len; > if (!alloced_path) { > pseudo_diag("Can't allocate space for paths for a rename operation. Sorry.\n"); > alloced_len = 0; > pseudo_magic(); > return 0; > } So buffer size is at most `path_extra_1len + 1` > } > if (pathlen) { > memcpy(alloced_path, path, partial_len - 1); > alloced_path[partial_len - 1] = '\0'; > } else { > alloced_path[0] = '\0'; > partial_len = 1; OK, partial_len is 1 > } > memcpy(alloced_path + partial_len, path_extra_1, path_extra_1len); > alloced_path[partial_len + path_extra_1len] = '\0'; Then here we write at offset `1 + path_extra_1len`. So buffer size should be at least `1 + path_extra_1len + 1` > if (path_extra_2) { > memcpy(alloced_path + partial_len + path_extra_1len + 1, path_extra_2, path_extra_2len); > } > alloced_path[full_len - 1] = '\0'; > path = alloced_path; > pathlen = full_len; > pseudo_debug_call(PDBGF_IPC | PDBGF_VERBOSE, pseudo_dump_data, "combined path buffer", path, pathlen); Hopefully this makes a bit more sense now :) Thanks, Mathieu -- Mathieu Dubois-Briand, Bootlin Embedded Linux and Kernel engineering https://bootlin.com ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [yocto-patches] [pseudo] [PATCH] pseudo_client: Fix xattr/rename handling with empty paths 2026-10-15 15:43 ` Mathieu Dubois-Briand @ 2026-10-15 21:54 ` Richard Purdie 0 siblings, 0 replies; 6+ messages in thread From: Richard Purdie @ 2026-10-15 21:54 UTC (permalink / raw) To: yocto-patches; +Cc: seebs, mark.hatle On Thu, 2026-10-15 at 17:43 +0200, Mathieu Dubois-Briand via lists.yoctoproject.org wrote: > So my point is, if pathlen is 0, we have: > > > size_t full_len = path_extra_1len + 1 + pathlen - strip_slash; > > So full_len is going to be: > path_extra_1len + 1 + 0 (pathlen) - strip_slash > So it will be at most: > path_extra_1len + 1 > > > size_t partial_len = pathlen - strip_slash; > > if (path_extra_2) { > > full_len += path_extra_2len + 1; > > } > > if (full_len > alloced_len) { > > free(alloced_path); > > alloced_path = malloc(full_len); > > alloced_len = full_len; > > if (!alloced_path) { > > pseudo_diag("Can't allocate space for paths for a rename operation. Sorry.\n"); > > alloced_len = 0; > > pseudo_magic(); > > return 0; > > } > > So buffer size is at most `path_extra_1len + 1` > > > } > > if (pathlen) { > > memcpy(alloced_path, path, partial_len - 1); > > alloced_path[partial_len - 1] = '\0'; > > } else { > > alloced_path[0] = '\0'; > > partial_len = 1; > > OK, partial_len is 1 > > > } > > memcpy(alloced_path + partial_len, path_extra_1, path_extra_1len); > > alloced_path[partial_len + path_extra_1len] = '\0'; > > Then here we write at offset `1 + path_extra_1len`. > So buffer size should be at least `1 + path_extra_1len + 1` > > > if (path_extra_2) { > > memcpy(alloced_path + partial_len + path_extra_1len + 1, path_extra_2, path_extra_2len); > > } > > alloced_path[full_len - 1] = '\0'; > > path = alloced_path; > > pathlen = full_len; > > pseudo_debug_call(PDBGF_IPC | PDBGF_VERBOSE, pseudo_dump_data, "combined path buffer", path, pathlen); > > Hopefully this makes a bit more sense now :) Yes, I think you're right. I'll add an extra 1 unconditionally to full_len to cover all the options... Thanks, Richard ^ permalink raw reply [flat|nested] 6+ messages in thread
[parent not found: <18DE7C971DAD1AD4.2478941@lists.yoctoproject.org>]
* Re: [yocto-patches] [pseudo] [PATCH] pseudo_client: Fix xattr/rename handling with empty paths [not found] <18DE7C971DAD1AD4.2478941@lists.yoctoproject.org> @ 2026-10-15 11:44 ` Richard Purdie 0 siblings, 0 replies; 6+ messages in thread From: Richard Purdie @ 2026-10-15 11:44 UTC (permalink / raw) To: yocto-patches; +Cc: seebs, mark.hatle On Wed, 2026-10-14 at 20:38 +0100, Richard Purdie via lists.yoctoproject.org wrote: > On Fedora45, we can end up in a situation where path_extra_1 (for xattr/rename ops) > but path is of zero length. The path_extra_1 codepath does not handle this well and > corrupts memory. > > The issue is "partial_len = pathlen - 1 - strip_slash" when pathlen is 0 (and > hence strip_slash is also 0). This leads to invalid memory writes and if those > happen to access off the end of a mapped segment, the program segfaults. > > Fix the code to handle the pathlen=0 case. > > Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org> > --- > pseudo_client.c | 17 +++++++++++------ > 1 file changed, 11 insertions(+), 6 deletions(-) I had wondered why we had something with a file descriptor which has no path, I was worried we were not tracking some kind of fd creation we should be. The answer is it is a unix domain socket. It therefore does have a path we could track but we'd not be able to do much with it anyway so it doesn't really matter. The reproducer is therefore calling fgetxattr() on a domain socket which glibc does for nameserver type operations. Cheers, Richard ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-10-15 21:54 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-14 19:38 [pseudo] [PATCH] pseudo_client: Fix xattr/rename handling with empty paths Richard Purdie
2026-10-15 13:38 ` [yocto-patches] " Mathieu Dubois-Briand
2026-10-15 14:25 ` Richard Purdie
2026-10-15 15:43 ` Mathieu Dubois-Briand
2026-10-15 21:54 ` Richard Purdie
[not found] <18DE7C971DAD1AD4.2478941@lists.yoctoproject.org>
2026-10-15 11:44 ` Richard Purdie
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.