* EBADF returned from close() by FUSE @ 2024-04-18 22:10 The 8472 2024-04-19 3:30 ` Antonio SJ Musumeci 0 siblings, 1 reply; 15+ messages in thread From: The 8472 @ 2024-04-18 22:10 UTC (permalink / raw) To: linux-fsdevel Hello, first time mailing the kernel mailing lists here, I hope got the right one. I'm investigating a bug report against the Rust standard library about error handling when closing file descriptors[0]. Testing shows that a FUSE flush request can be answered with a EBADF error and this is surfaced to the close() call. I am asking if it is intended behavior that filesystems can pass arbitrary error codes. Specifically a EBADF returned from close() and other syscalls that only use that code to indicate that it's not an open FD number is concerning since attempting to use an incorrect FD number would normally indicate a double-drop or some other part of the program trampling over file descriptors it is not supposed to touch. But if FUSE or other filesystems can pass arbitrary error codes into syscall results then it becomes impossible to distinguish fatally broken invariants (file descriptor ownership within a program) from merely questionable fileystem behavior. Since file descriptors are densely allocated (no equivalent to ASLR or guard pages) there are very little guard rails against accidental ownership violations. - The 8472 [0] https://github.com/rust-lang/rust/issues/124105 ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: EBADF returned from close() by FUSE 2024-04-18 22:10 EBADF returned from close() by FUSE The 8472 @ 2024-04-19 3:30 ` Antonio SJ Musumeci 2024-04-19 6:55 ` The 8472 0 siblings, 1 reply; 15+ messages in thread From: Antonio SJ Musumeci @ 2024-04-19 3:30 UTC (permalink / raw) To: The 8472, linux-fsdevel On 4/18/24 17:10, The 8472 wrote: > Hello, first time mailing the kernel mailing lists here, I hope got the right one. > > I'm investigating a bug report against the Rust standard library about error handling > when closing file descriptors[0]. > Testing shows that a FUSE flush request can be answered with a EBADF error > and this is surfaced to the close() call. > > I am asking if it is intended behavior that filesystems can pass arbitrary error codes. > > Specifically a EBADF returned from close() and other syscalls that only use that code > to indicate that it's not an open FD number is concerning since attempting to use > an incorrect FD number would normally indicate a double-drop or some other part > of the program trampling over file descriptors it is not supposed to touch. > > But if FUSE or other filesystems can pass arbitrary error codes into syscall results > then it becomes impossible to distinguish fatally broken invariants (file descriptor ownership > within a program) from merely questionable fileystem behavior. > Since file descriptors are densely allocated (no equivalent to ASLR or guard pages) > there are very little guard rails against accidental ownership violations. > > > - The 8472 > > [0] https://github.com/rust-lang/rust/issues/124105 I can't see how the kernel could meaningfully know of or limit errors coming from the FUSE server without compromising the nature of the technology. So in that sense... yes, it is intentional. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: EBADF returned from close() by FUSE 2024-04-19 3:30 ` Antonio SJ Musumeci @ 2024-04-19 6:55 ` The 8472 [not found] ` <8c7552b1-f371-4a75-98cc-f2c89816becb@spawn.link> 0 siblings, 1 reply; 15+ messages in thread From: The 8472 @ 2024-04-19 6:55 UTC (permalink / raw) To: Antonio SJ Musumeci, The 8472, linux-fsdevel On 19-04-2024 05:30, Antonio SJ Musumeci wrote: > On 4/18/24 17:10, The 8472 wrote: >> Hello, first time mailing the kernel mailing lists here, I hope got the right one. >> >> I'm investigating a bug report against the Rust standard library about error handling >> when closing file descriptors[0]. >> Testing shows that a FUSE flush request can be answered with a EBADF error >> and this is surfaced to the close() call. >> >> I am asking if it is intended behavior that filesystems can pass arbitrary error codes. >> >> Specifically a EBADF returned from close() and other syscalls that only use that code >> to indicate that it's not an open FD number is concerning since attempting to use >> an incorrect FD number would normally indicate a double-drop or some other part >> of the program trampling over file descriptors it is not supposed to touch. >> >> But if FUSE or other filesystems can pass arbitrary error codes into syscall results >> then it becomes impossible to distinguish fatally broken invariants (file descriptor ownership >> within a program) from merely questionable fileystem behavior. >> Since file descriptors are densely allocated (no equivalent to ASLR or guard pages) >> there are very little guard rails against accidental ownership violations. >> >> >> - The 8472 >> >> [0] https://github.com/rust-lang/rust/issues/124105 > I can't see how the kernel could meaningfully know of or limit errors > coming from the FUSE server without compromising the nature of the > technology. So in that sense... yes, it is intentional. File descriptor numbers are not a FUSE-managed resource, so I was hoping it would reserve error codes that are documented to signal incorrect access to that resource and convert external errors to another code (e.g. EIO). This would then signal that the file descriptor itself was valid but the underlying resource encountered an error while performing the operation. ^ permalink raw reply [flat|nested] 15+ messages in thread
[parent not found: <8c7552b1-f371-4a75-98cc-f2c89816becb@spawn.link>]
* Re: EBADF returned from close() by FUSE [not found] ` <8c7552b1-f371-4a75-98cc-f2c89816becb@spawn.link> @ 2024-04-19 18:18 ` The 8472 2024-04-19 20:07 ` Antonio SJ Musumeci 0 siblings, 1 reply; 15+ messages in thread From: The 8472 @ 2024-04-19 18:18 UTC (permalink / raw) To: Antonio SJ Musumeci, The 8472, linux-fsdevel On 19-04-2024 13:42, Antonio SJ Musumeci wrote: > On 4/19/24 01:55, The 8472 wrote: >> On 19-04-2024 05:30, Antonio SJ Musumeci wrote: >>> I can't see how the kernel could meaningfully know of or limit errors >>> coming from the FUSE server without compromising the nature of the >>> technology. So in that sense... yes, it is intentional. >> File descriptor numbers are not a FUSE-managed resource, so I was hoping >> it would reserve error codes that are documented to signal incorrect >> access to that resource and convert external errors to another code (e.g. EIO). >> This would then signal that the file descriptor itself was valid but the underlying >> resource encountered an error while performing the operation. > Anything can be a FUSE managed resource by proxy. [...] I'm referring to the slots in the file descriptor table of a process (A) that is opening a file on a FUSE filesystem. Whether a slot (FD number) is occupied or not is between the kernel and that process, not the server (S). Imo the kernel should only return EBADF when the process accesses an FD that is not in its table, which tends to be a fatal error in multithreaded programs. If S internally accesses invalid file descriptors that has no bearing on the state of the FD table of A. From A's perspective some sort of IO error occurred in the underlying storage system while releasing the FD, but it did use a valid file descriptor. > [...] There are a number of > situations where FUSE itself return errors but the largest surface area > for errors are from the FUSE server. And the server needs the ability to > return nearly anything. I'm not talking about what the server is allowed to return. I'm referring to which errors from the server get bubbled up verbatim through syscalls on files that are a FUSE mount. Is it necessary to pass through arbitrary FUSE errors, especially EBADF, when a processes closes a file that's backed by fuse? This shouldn't happen: |openat(AT_FDCWD, "./fuse-test/foo", O_RDONLY|O_CLOEXEC) = 5 close(5) = -1 EBADF (Bad file descriptor)| > Errnos are not *really* standard. They vary by > kernel release, different OSes, different libcs, different filesystems, > etc. As I pointed out recently to someone the use of EPERM to mean a > filesystem doesn't support "link" is not defined everywhere. Including > POSIX IIRC. And given FUSE is a cross platform protocol it shouldn't, > within reason, be interpreting any errors sent from the server (IMO). FUSE can send any errnos it wants over its client-server protocol. But the kernel could still translate them to error codes that don't have a documented meaning for a specific syscall. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: EBADF returned from close() by FUSE 2024-04-19 18:18 ` The 8472 @ 2024-04-19 20:07 ` Antonio SJ Musumeci 2024-04-19 20:45 ` The 8472 0 siblings, 1 reply; 15+ messages in thread From: Antonio SJ Musumeci @ 2024-04-19 20:07 UTC (permalink / raw) To: The 8472, linux-fsdevel On 4/19/24 13:18, The 8472 wrote: >> Errnos are not *really* standard. They vary by >> kernel release, different OSes, different libcs, different filesystems, >> etc. As I pointed out recently to someone the use of EPERM to mean a >> filesystem doesn't support "link" is not defined everywhere. Including >> POSIX IIRC. And given FUSE is a cross platform protocol it shouldn't, >> within reason, be interpreting any errors sent from the server (IMO). > FUSE can send any errnos it wants over its client-server protocol. > But the kernel could still translate them to error codes that don't > have a documented meaning for a specific syscall. No one is talking about or cares about the protocol error handling. That is private to the protocol. What matters is what FUSE kernel side does. And I'd disagree with you because as I tried to point out that "documented meaning" is not set in stone. Things change over time. Different systems, different filesystems, etc. treat situations differently. Some platforms don't even have certain errno or conflate others. Aren't there even differences in errno across some Linux archs? This is just a fact of life. FUSE trying to make sense of that mess is just going to lead to more of a mess. IMO EIO is no better than EBADF. A lot of software don't handle handle EXDEV correctly let alone random other errnos. For years Apple's SMB server would return EIO for just about anything happening on the backend. If a FUSE server is sending back EBADF in flush then it is likely a bug or bad decision. Ask them to fix it. And really... what is this translation table going to look like? `errno --list | wc -l` returns 134. You going to have huge switch statements on every single one of the couple dozen FUSE functions? Some of those maybe with special checks against arguments for the function too since many errno's are used to indicate multiple, sometimes entirely different, errors? It'd be a mess. And as a cross platform technology you'd need to define it as part of the protocol effectively. And it'd be backwards incompatible therefore optional. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: EBADF returned from close() by FUSE 2024-04-19 20:07 ` Antonio SJ Musumeci @ 2024-04-19 20:45 ` The 8472 2024-04-19 21:29 ` Antonio SJ Musumeci 0 siblings, 1 reply; 15+ messages in thread From: The 8472 @ 2024-04-19 20:45 UTC (permalink / raw) To: Antonio SJ Musumeci, The 8472, linux-fsdevel On 19-04-2024 22:07, Antonio SJ Musumeci wrote: > And I'd disagree with you because as I tried to point out that > "documented meaning" is not set in stone. Things change over time. > Different systems, different filesystems, etc. treat situations > differently. Some platforms don't even have certain errno or conflate > others. Aren't there even differences in errno across some Linux archs? Syscalls have documentation. Errors and their semantics are part of the documentation. If the kernel cannot actually provide the documented semantics because it passes errors through without sanitizing them then this should at least be documented for each affected syscall. Proper API documentation and stability guarantees are important so we can write robust software against them. Note that write(2) documents Other errors may occur, depending on the object connected to fd. close(2) has no such note. > This is just a fact of life. FUSE trying to make sense of that mess is > just going to lead to more of a mess. IMO EIO is no better than EBADF. A > lot of software don't handle handle EXDEV correctly let alone random > other errnos. For years Apple's SMB server would return EIO for just > about anything happening on the backend. That does not mean userspace should be exposed to the entirety of the mess. And in my opinion EIO is better than EBADF because the former "merely" indicates that something went wrong relating to a particular file. EBADF indicates that the file descriptor table of the process may have been corrupted. > If a FUSE server is sending > back EBADF in flush then it is likely a bug or bad decision. Agreed. > Ask them to fix it. Will try. But the kernel should imo also do its part fulfilling its API contract. > And really... what is this translation table going to look like? `errno > --list | wc -l` returns 134. You going to have huge switch statements on > every single one of the couple dozen FUSE functions? Some of those > maybe with special checks against arguments for the function too since > many errno's are used to indicate multiple, sometimes entirely > different, errors? It'd be a mess. And as a cross platform technology > you'd need to define it as part of the protocol effectively. And it'd be > backwards incompatible therefore optional. That it requires perhaps some thought to do it properly does not seem sufficient to me to dismiss the request to provide a proper abstraction boundary with reliable semantics that match its documentation. Whitelisting or blacklisting errors that have guaranteed meanings in individual syscalls and mapping those to a catchall is one possible approach. But others are also thinkable. That some symbolic lookup tables would be needed for this does not seem insurmountable to me. We do something similar in the Rust standard library to map OS-specific errors to a portable abstraction. We do have a catch-all "Uncategorized" that's explicitly intended for currently-unrecognized codes that may be moved to more meaningful variants later. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: EBADF returned from close() by FUSE 2024-04-19 20:45 ` The 8472 @ 2024-04-19 21:29 ` Antonio SJ Musumeci 2024-04-19 22:04 ` The 8472 0 siblings, 1 reply; 15+ messages in thread From: Antonio SJ Musumeci @ 2024-04-19 21:29 UTC (permalink / raw) To: The 8472, linux-fsdevel On 4/19/24 15:45, The 8472 wrote: > Syscalls have documentation. Errors and their semantics are part > of the documentation. If the kernel cannot actually provide > the documented semantics because it passes errors through without > sanitizing them then this should at least be documented > for each affected syscall. And that documentation is *different* depending on the platform. The clean vision you seem to have about errnos is not real. There are conventions... not strong contracts. I had this exact debate days ago about `link`. The claim that if link isn't supported by the OS FUSE should return EPERM. But this just isn't standard the way people think it is. Not on paper. And if a FUSE server wants to return EPERM then it can. I don't see why the kernel needs to get in the business of reading the mind of the server author. > > Proper API documentation and stability guarantees are important > so we can write robust software against them. > > Note that write(2) documents > > Other errors may occur, depending on the object connected to fd. > > close(2) has no such note. Your idea is laudable but not realistic. errnos are not even fully consistent across devices or filesystem. Yes, there are norms and some standards but they are not enforced by some central arbiter across all forms of *nix. > That does not mean userspace should be exposed to the entirety > of the mess. And in my opinion EIO is better than EBADF because > the former "merely" indicates that something went wrong relating > to a particular file. EBADF indicates that the file descriptor > table of the process may have been corrupted. "should"... but it is exposed to it. *Most* software doesn't even attempt to handle errors intelligently and just return the error up the stack blindly. EIO is about as generic as can be and I've seen it used many times as the "catch all" error making it meaningless. Further incentivizing client software to behave as they do... not paying attention. I will again point out that I've seen EXDEV treated like any random other error several times in my career by important pieces of software made by major vendors. > Will try. But the kernel should imo also do its part fulfilling its API > contract. Then you are barking up the wrong tree. This isn't an issue unique to FUSE. FUSE just makes it more obvious to you because anyone can write a FUSE server and return (almost) anything they want. > That it requires perhaps some thought to do it properly does not seem > sufficient to me to dismiss the request to provide a proper > abstraction boundary with reliable semantics that match its documentation. I simply don't see what you could do to "do it properly." I am trying to argue there is no such thing. And again it would require breaking every single FUSE server. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: EBADF returned from close() by FUSE 2024-04-19 21:29 ` Antonio SJ Musumeci @ 2024-04-19 22:04 ` The 8472 2024-04-19 22:47 ` Antonio SJ Musumeci 0 siblings, 1 reply; 15+ messages in thread From: The 8472 @ 2024-04-19 22:04 UTC (permalink / raw) To: Antonio SJ Musumeci, The 8472, linux-fsdevel On 19-04-2024 23:29, Antonio SJ Musumeci wrote: >> Proper API documentation and stability guarantees are important >> so we can write robust software against them. >> >> Note that write(2) documents >> >> Other errors may occur, depending on the object connected to fd. >> >> close(2) has no such note. > Your idea is laudable but not realistic. errnos are not even fully > consistent across devices or filesystem. Yes, there are norms and some > standards but they are not enforced by some central arbiter across all > forms of *nix. I'm writing to a linux mailing list, am I not? And referring to linux-specific manpages, not the POSIX ones. The way the linux kernel chooses to pass what FUSE sends to userspace is under its control. I would like linux to adhere more closely to its own API contract or improve its documentation. >> That does not mean userspace should be exposed to the entirety >> of the mess. And in my opinion EIO is better than EBADF because >> the former "merely" indicates that something went wrong relating >> to a particular file. EBADF indicates that the file descriptor >> table of the process may have been corrupted. > "should"... but it is exposed to it. *Most* software doesn't even > attempt to handle errors intelligently and just return the error up the > stack blindly. EIO is about as generic as can be and I've seen it used > many times as the "catch all" error making it meaningless. Further > incentivizing client software to behave as they do... not paying > attention. I will again point out that I've seen EXDEV treated like any > random other error several times in my career by important pieces of > software made by major vendors. That seems hardly relevant to this case here. >> Will try. But the kernel should imo also do its part fulfilling its API >> contract. > Then you are barking up the wrong tree. This isn't an issue unique to > FUSE. FUSE just makes it more obvious to you because anyone can write a > FUSE server and return (almost) anything they want. If other things can cause this too, then yes of course, a more general solution would be fine too for my purposes. Should I have written to another list? Or filed a report on bugzilla instead? >> That it requires perhaps some thought to do it properly does not seem >> sufficient to me to dismiss the request to provide a proper >> abstraction boundary with reliable semantics that match its documentation. > I simply don't see what you could do to "do it properly." I am trying to > argue there is no such thing. And again it would require breaking every > single FUSE server. I don't understand what would be broken here. In a previous mail you agreed that FUSE servers have no business sending EBADF and should have a bug filed against them. If that's the case then sanitizing problematic cases should be ok. The libfuse documentation even notes that servers should not assume errors from flush get delivered to userspace. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: EBADF returned from close() by FUSE 2024-04-19 22:04 ` The 8472 @ 2024-04-19 22:47 ` Antonio SJ Musumeci 2024-04-19 23:04 ` The 8472 0 siblings, 1 reply; 15+ messages in thread From: Antonio SJ Musumeci @ 2024-04-19 22:47 UTC (permalink / raw) To: The 8472, linux-fsdevel On 4/19/24 17:04, The 8472 wrote: > I'm writing to a linux mailing list, am I not? And referring to linux-specific > manpages, not the POSIX ones. The way the linux kernel chooses to pass > what FUSE sends to userspace is under its control. > > I would like linux to adhere more closely to its own API contract or improve its > documentation. And you're talking about FUSE which is a cross platform (Linux, FreeBSD, MacOS, Windows) protocol. And that protocol defacto includes what happens when the FUSE server returns and error. If Linux suddenly changes what happens when the server returns an error it will affect everyone. > I don't understand what would be broken here. In a previous mail you agreed > that FUSE servers have no business sending EBADF and should have a > bug filed against them. If that's the case then sanitizing problematic cases > should be ok. I said: "it is likely a bug or bad decision" but I don't claim to know the mind of the author. I've seen FUSE filesystems designed for fuzzing apps via filesystem APIs and they by their nature desire to return all kinds of random errors. I've seen non-standard errors to indicate special edge cases or more accurately indicate the underlying resource's issue (like when interacting with remote system.) Or even uncommon values used to indicate something to software which was written to know it was dealing with a special filesystem. Filesystems are just not uniform in behavior generally let alone errors. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: EBADF returned from close() by FUSE 2024-04-19 22:47 ` Antonio SJ Musumeci @ 2024-04-19 23:04 ` The 8472 2024-04-23 12:46 ` Miklos Szeredi 0 siblings, 1 reply; 15+ messages in thread From: The 8472 @ 2024-04-19 23:04 UTC (permalink / raw) To: Antonio SJ Musumeci, The 8472, linux-fsdevel On 20-04-2024 00:47, Antonio SJ Musumeci wrote: > On 4/19/24 17:04, The 8472 wrote: >> I'm writing to a linux mailing list, am I not? And referring to linux-specific >> manpages, not the POSIX ones. The way the linux kernel chooses to pass >> what FUSE sends to userspace is under its control. >> >> I would like linux to adhere more closely to its own API contract or improve its >> documentation. > And you're talking about FUSE which is a cross platform (Linux, FreeBSD, > MacOS, Windows) protocol. And that protocol defacto includes what > happens when the FUSE server returns and error. If Linux suddenly > changes what happens when the server returns an error it will affect > everyone. If it is the official position that the whims of FUSE servers have primacy over current kernel API guarantees then please update the documentation of all affected syscalls and relax those guarantees, similar to the note on the write(2) manpage. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: EBADF returned from close() by FUSE 2024-04-19 23:04 ` The 8472 @ 2024-04-23 12:46 ` Miklos Szeredi 2024-04-23 13:24 ` Antonio SJ Musumeci 0 siblings, 1 reply; 15+ messages in thread From: Miklos Szeredi @ 2024-04-23 12:46 UTC (permalink / raw) To: The 8472; +Cc: Antonio SJ Musumeci, linux-fsdevel On Sat, 20 Apr 2024 at 01:04, The 8472 <kernel@infinite-source.de> wrote: > If it is the official position that the whims of FUSE servers have > primacy over current kernel API guarantees then please update > the documentation of all affected syscalls and relax those > guarantees, similar to the note on the write(2) manpage. Which note are you referring to? I can see some merit to both sides. If it's an issue that can be fixed in the fuse server ("Doctor, it hurts when I do this." "Then don't do that!”) adding complexity to the fuse client is not warranted. Obviously most fuse servers don't want to actively confuse caller, but if such behavior can be used to exploit a weakness in an application, then it becomes more than just a correctness issue. If you came up with such a scenario, then this would turn into a serious bug. Thanks, Miklos ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: EBADF returned from close() by FUSE 2024-04-23 12:46 ` Miklos Szeredi @ 2024-04-23 13:24 ` Antonio SJ Musumeci 2024-04-23 13:38 ` Miklos Szeredi 0 siblings, 1 reply; 15+ messages in thread From: Antonio SJ Musumeci @ 2024-04-23 13:24 UTC (permalink / raw) To: Miklos Szeredi, The 8472; +Cc: linux-fsdevel On 4/23/24 07:46, Miklos Szeredi wrote: > On Sat, 20 Apr 2024 at 01:04, The 8472 <kernel@infinite-source.de> wrote: > >> If it is the official position that the whims of FUSE servers have >> primacy over current kernel API guarantees then please update >> the documentation of all affected syscalls and relax those >> guarantees, similar to the note on the write(2) manpage. > Which note are you referring to? > > I can see some merit to both sides. > > If it's an issue that can be fixed in the fuse server ("Doctor, it > hurts when I do this." "Then don't do that!”) adding complexity to the > fuse client is not warranted. > > Obviously most fuse servers don't want to actively confuse caller, but > if such behavior can be used to exploit a weakness in an application, > then it becomes more than just a correctness issue. If you came up > with such a scenario, then this would turn into a serious bug. > > Thanks, > Miklos From the write(2) manpage (at least on Ubuntu): "Other errors may occur, depending on the object connected to fd." My argument has been that this note is defacto true generally. The specifics of this thread stem from close() returning EBADF to the client app while talking to a FUSE server after the open() succeeded and, from the point of view of the client app, returned a valid file descriptor. Sounds like a bug in the FUSE server rather than something FUSE itself needs to worry about. Besides removing some classes of usage of FUSE it would be rather complicated, if not impossible, to assume the meaning of returned errors from the server and translate them into "approved" values for the client. It will mask server bugs and/or confuse server authors at best IMO. Error handling in FUSE is already a bit difficult to manage. This is not unlike a recent complaint that when link() is not implemented libfuse returns ENOSYS rather than EPERM. As I pointed out in that situation EPERM is not universally defined as meaning "not implemented by filesystem" like used in Linux. Doesn't mean it isn't used (I didn't check) but it isn't defined as such in docs. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: EBADF returned from close() by FUSE 2024-04-23 13:24 ` Antonio SJ Musumeci @ 2024-04-23 13:38 ` Miklos Szeredi [not found] ` <692a9f0b-9c2b-4850-b8bc-48f09fe41762@infinite-source.de> 0 siblings, 1 reply; 15+ messages in thread From: Miklos Szeredi @ 2024-04-23 13:38 UTC (permalink / raw) To: Antonio SJ Musumeci; +Cc: The 8472, linux-fsdevel On Tue, 23 Apr 2024 at 15:24, Antonio SJ Musumeci <trapexit@spawn.link> wrote: > From the write(2) manpage (at least on Ubuntu): > > "Other errors may occur, depending on the object connected to fd." > > My argument has been that this note is defacto true generally. Yes. > > The specifics of this thread stem from close() returning EBADF to the > client app while talking to a FUSE server after the open() succeeded > and, from the point of view of the client app, returned a valid file > descriptor. Sounds like a bug in the FUSE server rather than something > FUSE itself needs to worry about. Return value from close is ignored in 99% of cases. It is quite hard to imagine this making real difference to an application. The basic philosophy of the linux kernel is pragmatism: if it matters in a real world use case, then we care, otherwise we don't. I don't think a server returning EBADF matters in real life, but if it is, then we do need to take care of it. > This is not unlike a recent complaint that when link() is not > implemented libfuse returns ENOSYS rather than EPERM. As I pointed out > in that situation EPERM is not universally defined as meaning "not > implemented by filesystem" like used in Linux. Doesn't mean it isn't > used (I didn't check) but it isn't defined as such in docs. ENOSYS is a good example where fuse does need to filter out errors, since applications do interpret ENOSYS as "kernel doesn't implement this syscall" and fuse actually uses ENOSYS for a different purpose. Thanks, Miklos ^ permalink raw reply [flat|nested] 15+ messages in thread
[parent not found: <692a9f0b-9c2b-4850-b8bc-48f09fe41762@infinite-source.de>]
* Re: EBADF returned from close() by FUSE [not found] ` <692a9f0b-9c2b-4850-b8bc-48f09fe41762@infinite-source.de> @ 2024-04-23 21:38 ` The 8472 2024-04-26 8:52 ` Miklos Szeredi 0 siblings, 1 reply; 15+ messages in thread From: The 8472 @ 2024-04-23 21:38 UTC (permalink / raw) To: The 8472, Miklos Szeredi, Antonio SJ Musumeci; +Cc: linux-fsdevel On 23-04-2024 15:38, Miklos Szeredi wrote: > On Tue, 23 Apr 2024 at 15:24, Antonio SJ Musumeci<trapexit@spawn.link> wrote: > >> From the write(2) manpage (at least on Ubuntu): >> >> "Other errors may occur, depending on the object connected to fd." >> >> My argument has been that this note is defacto true generally. > Yes. In some places we do rely on error codes having exactly the documented meaning and no other. E.g. fcntl(..., F_GETFD) failing with EBADF is treated as fatal, other codes are not. Or openat(..., O_NOFOLLOW | O_DIRECTORY) returning ENOTDIR is trusted to mean that the file is in fact not a directory and can be unlinked instead of rmdir'd >> The specifics of this thread stem from close() returning EBADF to the >> client app while talking to a FUSE server after the open() succeeded >> and, from the point of view of the client app, returned a valid file >> descriptor. Sounds like a bug in the FUSE server rather than something >> FUSE itself needs to worry about. > Return value from close is ignored in 99% of cases. It is quite hard > to imagine this making real difference to an application. The basic > philosophy of the linux kernel is pragmatism: if it matters in a real > world use case, then we care, otherwise we don't. I don't think a > server returning EBADF matters in real life, but if it is, then we do > need to take care of it. Current Rust versions unwind if closedir() is not successful since directories aren't writable and aren't expected to have writeback errors. That's what lead to this thread. If that had returned an EIO that would have been annoying but would clearly point at unreliable storage. If it returns EBADF that is more concerning because it could be a double-close or something similar within the process clobbering FDs. >> This is not unlike a recent complaint that when link() is not >> implemented libfuse returns ENOSYS rather than EPERM. As I pointed out >> in that situation EPERM is not universally defined as meaning "not >> implemented by filesystem" like used in Linux. Doesn't mean it isn't >> used (I didn't check) but it isn't defined as such in docs. > ENOSYS is a good example where fuse does need to filter out errors, > since applications do interpret ENOSYS as "kernel doesn't implement > this syscall" and fuse actually uses ENOSYS for a different purpose. Yes, we use ENOSYS a lot for feature detection. Bogus ones would result result in loss of performance and minor functionality. Due to old docker seccomp filters returning EPERM instead of ENOSYS on filtered syscalls we sometimes also have to treat EPERM like ENOSYS on syscalls where EPERM is not documented as one of the valid return codes. Also, "not universally defined" is not relevant, we consult a platform's manpages to understand platform-specific behavior, not just the posix ones. So if linux implements its fuse client in a way that propagates arbitrary error codes to syscalls for which the linux-specific documentation says that only a certain set of error codes with specific meanings would be returned then either the documentation is wrong or those errors should be mangled before they bubble up to the syscall. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: EBADF returned from close() by FUSE 2024-04-23 21:38 ` The 8472 @ 2024-04-26 8:52 ` Miklos Szeredi 0 siblings, 0 replies; 15+ messages in thread From: Miklos Szeredi @ 2024-04-26 8:52 UTC (permalink / raw) To: The 8472; +Cc: Antonio SJ Musumeci, linux-fsdevel On Tue, 23 Apr 2024 at 23:38, The 8472 <kernel@infinite-source.de> wrote: > In some places we do rely on error codes having exactly the documented meaning > and no other. E.g. fcntl(..., F_GETFD) failing with EBADF is treated as fatal, > other codes are not. > Or openat(..., O_NOFOLLOW | O_DIRECTORY) returning ENOTDIR is trusted to mean > that the file is in fact not a directory and can be unlinked instead of rmdir'd There are lot of assumptions from applications. Fuse won't and can't check them all. This applies to error codes as well. > Current Rust versions unwind if closedir() is not successful since > directories aren't writable and aren't expected to have writeback > errors. That's what lead to this thread. Is that bad? I mean can that lead to a security breach? If not, then it's not interesting, lets just fix the bad filesystem. > If that had returned an EIO that would have been annoying but > would clearly point at unreliable storage. If it returns > EBADF that is more concerning because it could be a double-close or > something similar within the process clobbering FDs. So the worst thing that can happen is that a bad fuse filesystem is able to confuse the user of an application, believing the application is at fault when in fact it's the filesystem that's acting up? > So if linux implements its fuse client in a way that propagates arbitrary > error codes to syscalls for which the linux-specific documentation says that only > a certain set of error codes with specific meanings would be returned then > either the documentation is wrong or those errors should be mangled before > they bubble up to the syscall. Man pages do not say that the error list is exhaustive. Other error codes are almost always possible even without fuse. Thanks, Miklos ^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2024-04-26 8:52 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-04-18 22:10 EBADF returned from close() by FUSE The 8472
2024-04-19 3:30 ` Antonio SJ Musumeci
2024-04-19 6:55 ` The 8472
[not found] ` <8c7552b1-f371-4a75-98cc-f2c89816becb@spawn.link>
2024-04-19 18:18 ` The 8472
2024-04-19 20:07 ` Antonio SJ Musumeci
2024-04-19 20:45 ` The 8472
2024-04-19 21:29 ` Antonio SJ Musumeci
2024-04-19 22:04 ` The 8472
2024-04-19 22:47 ` Antonio SJ Musumeci
2024-04-19 23:04 ` The 8472
2024-04-23 12:46 ` Miklos Szeredi
2024-04-23 13:24 ` Antonio SJ Musumeci
2024-04-23 13:38 ` Miklos Szeredi
[not found] ` <692a9f0b-9c2b-4850-b8bc-48f09fe41762@infinite-source.de>
2024-04-23 21:38 ` The 8472
2024-04-26 8:52 ` Miklos Szeredi
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).