Live data from Hacker News

The trouble with symbolic links

lwn.net

1–10 of 126 posts

Re: The trouble with symbolic links

#3
post #2

There doesn't seem to be a way to batch together operations that involve walking through directories and symlinks to do something to a file. This seems to be a major source of complexity.

Could you elaborate? Seems like there’s a bunch of things that can’t be batched together on an ordinary file, without involving symlinks.

Re: The trouble with symbolic links

#4
IMO the article's conclusion is backwards. There's nothing wrong with symlinks when files are opened with openat(), since in principal the program (or controlling program) should always be in control of the filesystem layout. It's open() that causes problems, and complex interactions with symlinks in attacker-controlled directories are just one of them.

The POSIX file API was designed before the concept of capability passing (arguably, before the concept of computer security in general). A modern replacement would look more like Fuchsia, where child processes are provided file access scoped to their parent process's authority. This same scoping can also be used within a process, for example to implement a server that can "self-chroot".

  > So, more functions following the pattern of openat() had to be created
  > [...]
  > Some are still missing, like getxattrat() and setxattrat().
The functions to get/set xattrs on a file descriptor (rather than a path) are fgetxattr() and fsetxattr(). They're not usable for the specific case of a file descriptor opened with O_PATH, but that restriction is both documented and reasonable -- O_PATH doesn't allow operations that inspect the state of the file itself, such as reading/writing.

A better example might have been listxattr() vs flistxattr(), because the former works on a file without read permissions, but the latter fails on a descriptor opened with O_PATH.

  listxattr("xattr-chmod000.txt", NULL, 0)         = 14
  listxattr("xattr-chmod000.txt", "user.testattr\0", 14) = 14
  getxattr("xattr-chmod000.txt", "user.testattr", NULL, 0) = -1 EACCES (Permission denied)
vs

  openat(AT_FDCWD, "xattr-chmod000.txt", O_RDONLY|O_PATH) = 3
  flistxattr(3, NULL, 0)                  = -1 EBADF (Bad file descriptor)

Re: The trouble with symbolic links

#5
Interestingly, Windows actually did exactly what's proposed at the end when MS added them in Vista. To minimize the security issues with symlinks, you had to elevate to admin to create them.

It was only during the life of Windows 10 that they even added the option to not have to elevate to create them. It was done specifically because symlinks are often shared across systems since they end up in places like git repos and npm packages: https://blogs.windows.com/windowsdeveloper/2016/12/02/symlin...

Re: The trouble with symbolic links

#6
post #2

There doesn't seem to be a way to batch together operations that involve walking through directories and symlinks to do something to a file. This seems to be a major source of complexity.

I always thought Unix v7+ should have added some kind way to do atomic groups of syscalls, eg:

  begin_transaction ();
  lstat ("/path", ...);
  lstat ("/path/foo", ...);
  commit ();
In Unix v7 mkdir was not a system call. It was a setuid program implemented using mknod + link. That was racy so the mkdir(2) system call was added. But it could have been solved more generally (and more elegantly) by adding transactions.

It could also solve the whole thing with ending up with zero-length files because you didn't use the right incantation to update a file atomically on ext4 (https://thunk.org/tytso/blog/2009/03/12/delayed-allocation-a...).

Re: The trouble with symbolic links

#7
"X is fundamentally broken" is a tired trope. To me, something is broken if it is no longer working as intended. It used to work, but now it does not - it is broken.

If something works as intended, but its utility is limited, and it can be improved, it is not broken.

Re: The trouble with symbolic links

#8
post #7

"X is fundamentally broken" is a tired trope. To me, something is broken if it is no longer working as intended. It used to work, but now it does not - it is broken. If something works as intended, but its utility is limited, and it can be improved, it is not broken.

Symlinks work as intended, but they cause a lot of unintended security vulnerabilities, i.e. they break lots of otherwise-functioning code.

You can play with your words and redefine their meanings, but the vulnerabilities remain.

Re: The trouble with symbolic links

#9
post #7

"X is fundamentally broken" is a tired trope. To me, something is broken if it is no longer working as intended. It used to work, but now it does not - it is broken. If something works as intended, but its utility is limited, and it can be improved, it is not broken.

That “X − designed in the 70s when we had no idea of anything regarding computers − is fundamentally broken” isn't so surprising after all.

In fact, computers are probably the only place in the entire technology landscape where we keep using almost unmodified stuff from the 70s and decided we cannot change it because there's too much things relying on it.

I don't like breaking everything all the time more than anyone, but maybe one time every 20 or 30 years is OK…

Re: The trouble with symbolic links

#10
post #8
post #7

"X is fundamentally broken" is a tired trope. To me, something is broken if it is no longer working as intended. It used to work, but now it does not - it is broken. If something works as intended, but its utility is limited, and it can be improved, it is not broken.

Symlinks work as intended, but they cause a lot of unintended security vulnerabilities, i.e. they break lots of otherwise-functioning code. You can play with your words and redefine their meanings, but the vulnerabilities remain.

They have been around for 40+ years, they don't break code unless we are talking about code predating their introduction. It is not me playing with words, I am just pointing out a tired trope.
Post reply on HN