Yes, it would. Unless there is some case where dd is available but cat is, dd works.
Thanks for your help, Ethan On Tue, Mar 25, 2025 at 1:11 PM Pádraig Brady <p...@draigbrady.com> wrote: > > On 25/03/2025 14:19, Ethan Heilman wrote: > > Howdy coreutils, > > > > I would like to add a O_NOFOLLOW flag to cat so that users can specify > > if cat should follow a symlink at the final file in a path. This is > > motivated by the need to atomically read a file while ensuring it is > > not a symlink. This functionality is absent from coreutils, as far as > > I am aware. > > > > I’d be grateful for any feedback, criticism, ideas on this proposed > > change. Is this something coreutils would be interested in merging if > > I wrote code + tests. > > > > Rationale > > ==== > > > > Without this functionality in cat, users are likely to do the next > > easiest option which is to use two separate commands to first check if > > the file is a symlink and then read the file. This can be a source of > > bugs and harm security because using two commands introduces a TOCTOU > > (Time-of-Check to Time-of-Use) issue. This is because it is always > > possible after the symlink check has occurred, but before cat is run > > the file is replaced with symlink. Such race condition bugs are > > especially dangerous because the harmful behavior is triggered only in > > rare circumstances, allowing them to enter production and be hard to > > debug. > > > > When might one encounter this: > > > > 1. Having privileged services or sudoer commands where a symlink be > > might be maliciously or accidentally substituted as the final file in > > the path (often called the confused deputy problem[0]). > > > > `serviceuser ALL=(ALL) NOPASSWD: cat /home/[0-9a-z_-]/file123` > > > > 2. Different scripts or users reading and writing to a shared > > directory. This need not be a security issue. If files are being > > created and destroyed frequently, a user may just wish to ensure they > > don’t accidentally read from a symlink when they don’t expect the file > > to be a symlink. For instance ensuring that a read does not leave the > > current directory. > > > > This is not a problem for directories because one can check if a > > directory is a symlink safely with any later action because you can > > compare the expected file path after traversing into that directory > > but before taking the action. This is safe because someone can’t > > change the directory you are already in into a symlink after you have > > transverse it. Thus, this change would strictly maintain the behavior > > of the O_NOFOLLOW flag in following directory symlinks prior to the > > last part of a path. > > > > While this can be solved by creating a binary or using python, I > > believe enabling reads to be atomic with symlink checks is an > > important building block that should be available at the level of > > coreutils. Allowing cat to support O_NOFOLLOW via a flag would be a > > simple way to add this functionality. > > > > Thanks for taking the time to read this, > > Ethan > > > > [0]: https://en.wikipedia.org/wiki/Confused_deputy_problem > > > Would dd suffice for such fine grained control? > > $ dd iflag=nofollow if=symlink > dd: failed to open 'symlink': Too many levels of symbolic links > > cheers, > Pádraig