From: Eric Biggers <ebiggers@kernel.org> Date: 2021-07-02 06:54:52
This series makes the stat() family of syscalls start reporting the
correct size for encrypted symlinks.
See patch 1 for a detailed explanation of the problem and solution.
Patch 1 adds a helper function that computes the correct size for an
encrypted symlink. Patches 2-4 make the filesystems with fscrypt
support use it, and patch 5 updates the documentation.
This series applies to mainline commit 3dbdb38e2869.
Eric Biggers (5):
fscrypt: add fscrypt_symlink_getattr() for computing st_size
ext4: report correct st_size for encrypted symlinks
f2fs: report correct st_size for encrypted symlinks
ubifs: report correct st_size for encrypted symlinks
fscrypt: remove mention of symlink st_size quirk from documentation
Documentation/filesystems/fscrypt.rst | 5 ---
fs/crypto/hooks.c | 44 +++++++++++++++++++++++++++
fs/ext4/symlink.c | 12 +++++++-
fs/f2fs/namei.c | 12 +++++++-
fs/ubifs/file.c | 13 +++++++-
include/linux/fscrypt.h | 7 +++++
6 files changed, 85 insertions(+), 8 deletions(-)
base-commit: 3dbdb38e286903ec220aaf1fb29a8d94297da246
--
2.32.0
From: Eric Biggers <ebiggers@kernel.org> Date: 2021-07-02 06:54:54
From: Eric Biggers <redacted>
Add a helper function fscrypt_symlink_getattr() which will be called
from the various filesystems' ->getattr() methods to read and decrypt
the target of encrypted symlinks in order to report the correct st_size.
Detailed explanation:
As required by POSIX and as documented in various man pages, st_size for
a symlink is supposed to be the length of the symlink target.
Unfortunately, st_size has always been wrong for encrypted symlinks
because st_size is populated from i_size from disk, which intentionally
contains the length of the encrypted symlink target. That's slightly
greater than the length of the decrypted symlink target (which is the
symlink target that userspace usually sees), and usually won't match the
length of the no-key encoded symlink target either.
This hadn't been fixed yet because reporting the correct st_size would
require reading the symlink target from disk and decrypting or encoding
it, which historically has been considered too heavyweight to do in
->getattr(). Also historically, the wrong st_size had only broken a
test (LTP lstat03) and there were no known complaints from real users.
(This is probably because the st_size of symlinks isn't used too often,
and when it is, typically it's for a hint for what buffer size to pass
to readlink() -- which a slightly-too-large size still works for.)
However, a couple things have changed now. First, there have recently
been complaints about the current behavior from real users:
- Breakage in rpmbuild:
https://github.com/rpm-software-management/rpm/issues/1682https://github.com/google/fscrypt/issues/305
- Breakage in toybox cpio:
https://www.mail-archive.com/toybox@lists.landley.net/msg07193.html
- Breakage in libgit2: https://issuetracker.google.com/issues/189629152
(on Android public issue tracker, requires login)
Second, we now cache decrypted symlink targets in ->i_link. Therefore,
taking the performance hit of reading and decrypting the symlink target
in ->getattr() wouldn't be as big a deal as it used to be, since usually
it will just save having to do the same thing later.
Also note that eCryptfs ended up having to read and decrypt symlink
targets in ->getattr() as well, to fix this same issue; see
commit 3a60a1686f0d ("eCryptfs: Decrypt symlink target for stat size").
So, let's just bite the bullet, and read and decrypt the symlink target
in ->getattr() in order to report the correct st_size. Add a function
fscrypt_symlink_getattr() which the filesystems will call to do this.
(Alternatively, we could store the decrypted size of symlinks on-disk.
But there isn't a great place to do so, and encryption is meant to hide
the original size to some extent; that property would be lost.)
Cc: stable@vger.kernel.org
Signed-off-by: Eric Biggers <redacted>
---
fs/crypto/hooks.c | 44 +++++++++++++++++++++++++++++++++++++++++
include/linux/fscrypt.h | 7 +++++++
2 files changed, 51 insertions(+)
From: Eric Biggers <ebiggers@kernel.org> Date: 2021-07-02 06:54:57
From: Eric Biggers <redacted>
The stat() family of syscalls report the wrong size for encrypted
symlinks, which has caused breakage in several userspace programs.
Fix this by calling fscrypt_symlink_getattr() after f2fs_getattr() for
encrypted symlinks. This function computes the correct size by reading
and decrypting the symlink target (if it's not already cached).
For more details, see the commit which added fscrypt_symlink_getattr().
Fixes: cbaf042a3cc6 ("f2fs crypto: add symlink encryption")
Cc: stable@vger.kernel.org
Signed-off-by: Eric Biggers <redacted>
---
fs/f2fs/namei.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
From: Eric Biggers <ebiggers@kernel.org> Date: 2021-07-02 06:54:59
From: Eric Biggers <redacted>
The stat() family of syscalls report the wrong size for encrypted
symlinks, which has caused breakage in several userspace programs.
Fix this by calling fscrypt_symlink_getattr() after ext4_getattr() for
encrypted symlinks. This function computes the correct size by reading
and decrypting the symlink target (if it's not already cached).
For more details, see the commit which added fscrypt_symlink_getattr().
Fixes: f348c252320b ("ext4 crypto: add symlink encryption")
Cc: stable@vger.kernel.org
Signed-off-by: Eric Biggers <redacted>
---
fs/ext4/symlink.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
From: Eric Biggers <ebiggers@kernel.org> Date: 2021-07-02 06:55:03
From: Eric Biggers <redacted>
The stat() family of syscalls report the wrong size for encrypted
symlinks, which has caused breakage in several userspace programs.
Fix this by calling fscrypt_symlink_getattr() after ubifs_getattr() for
encrypted symlinks. This function computes the correct size by reading
and decrypting the symlink target (if it's not already cached).
For more details, see the commit which added fscrypt_symlink_getattr().
Fixes: ca7f85be8d6c ("ubifs: Add support for encrypted symlinks")
Cc: stable@vger.kernel.org
Signed-off-by: Eric Biggers <redacted>
---
fs/ubifs/file.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
From: Eric Biggers <ebiggers@kernel.org> Date: 2021-07-02 06:55:04
From: Eric Biggers <redacted>
Now that the correct st_size is reported for encrypted symlinks on all
filesystems, update the documentation accordingly.
Signed-off-by: Eric Biggers <redacted>
---
Documentation/filesystems/fscrypt.rst | 5 -----
1 file changed, 5 deletions(-)
@@ -1063,11 +1063,6 @@ astute users may notice some differences in behavior:- DAX (Direct Access) is not supported on encrypted files.-- The st_size of an encrypted symlink will not necessarily give the- length of the symlink target as required by POSIX. It will actually- give the length of the ciphertext, which will be slightly longer- than the plaintext due to NUL-padding and an extra 2-byte overhead.-- The maximum length of an encrypted symlink is 2 bytes shorter than the maximum length of an unencrypted symlink. For example, on an EXT4 filesystem with a 4K block size, unencrypted symlinks can be up
From: Eric Biggers <ebiggers@kernel.org> Date: 2021-07-26 03:58:37
On Thu, Jul 01, 2021 at 11:53:45PM -0700, Eric Biggers wrote:
This series makes the stat() family of syscalls start reporting the
correct size for encrypted symlinks.
See patch 1 for a detailed explanation of the problem and solution.
Patch 1 adds a helper function that computes the correct size for an
encrypted symlink. Patches 2-4 make the filesystems with fscrypt
support use it, and patch 5 updates the documentation.
This series applies to mainline commit 3dbdb38e2869.
Eric Biggers (5):
fscrypt: add fscrypt_symlink_getattr() for computing st_size
ext4: report correct st_size for encrypted symlinks
f2fs: report correct st_size for encrypted symlinks
ubifs: report correct st_size for encrypted symlinks
fscrypt: remove mention of symlink st_size quirk from documentation
Documentation/filesystems/fscrypt.rst | 5 ---
fs/crypto/hooks.c | 44 +++++++++++++++++++++++++++
fs/ext4/symlink.c | 12 +++++++-
fs/f2fs/namei.c | 12 +++++++-
fs/ubifs/file.c | 13 +++++++-
include/linux/fscrypt.h | 7 +++++
6 files changed, 85 insertions(+), 8 deletions(-)
base-commit: 3dbdb38e286903ec220aaf1fb29a8d94297da246
All applied to fscrypt.git#master for 5.15.
- Eric