google / fscrypt

Go tool for managing Linux filesystem encryption

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How to unlock encrypted regular files located in an unencrypted directory?

maxnikulin opened this issue · comments

It seems a directory may contain files encrypted by different protectors. Is it possible to find how to access file content by its path?

$ grep '' not-encrypted/*
grep: not-encrypted/file-a: Required key not available
grep: not-encrypted/file-b: Required key not available
not-encrypted/file-not:Not encrypted

$ fscrypt unlock crypt-a
Enter custom passphrase for protector "a": 
"crypt-a" is now unlocked and ready for use.

$ grep '' not-encrypted/*
not-encrypted/file-a:this is a
grep: not-encrypted/file-b: Required key not available
not-encrypted/file-not:Not encrypted

How to determine that namely the crypt-a directory should be unlocked to read not-encrypted/file-a?

Accidentally I moved a file outside of encrypted directory. It resembles a feature requested in #373. Commands to reproduce output given above:

$ mkdir not-encrypted crypt-a crypt-b
$ fscrypt encrypt crypt-a
The following protector sources are available:
1 - Your login passphrase (pam_passphrase)
2 - A custom passphrase (custom_passphrase)
3 - A raw 256-bit key (raw_key)
Enter the source number for the new protector [2 - custom_passphrase]: 2
Enter a name for the new protector: a
Enter custom passphrase for protector "a": 
Confirm passphrase: 
"crypt-a" is now encrypted, unlocked, and ready for use.

$ echo "this is a" >crypt-a/file-a
$ mv -iv crypt-a/file-a not-encrypted/
renamed 'crypt-a/file-a' -> 'not-encrypted/file-a'
$ fscrypt lock crypt-a
"crypt-a" is now locked.

$ fscrypt encrypt crypt-b
Should we create a new protector? [y/N] y
The following protector sources are available:
1 - Your login passphrase (pam_passphrase)
2 - A custom passphrase (custom_passphrase)
3 - A raw 256-bit key (raw_key)
Enter the source number for the new protector [2 - custom_passphrase]: 2
Enter a name for the new protector: b
Enter custom passphrase for protector "b": 
Confirm passphrase: 
"crypt-b" is now encrypted, unlocked, and ready for use.

$ echo "this is b" >crypt-b/file-b
$ mv -iv crypt-b/file-b not-encrypted/
renamed 'crypt-b/file-b' -> 'not-encrypted/file-b'
$ fscrypt lock crypt-b
"crypt-b" is now locked.

$ echo "Not encrypted" >not-encrypted/file-not

I expected that it is possible to obtain some info from extended attributes of the files, but the following command results in empty output

$ attr -l not-encrypted/file-a

https://www.kernel.org/doc/html/latest/filesystems/fscrypt.html#encryption-context confirms that attributes are hidden.

README.md describes that moving file into an encrypted directory works more like a copy. Moving file outside of an encrypted directory looks like an unexpected feature.

Debian 12 bookworm, Linux kernel 6.1.55-1, fscrypt 0.3.3-1+b6.

The kernel does allow encrypted regular files to be moved into an unencrypted directory, but it's an edge case that's not well supported. You essentially still need a directory if you want to unlock such files. fscrypt unlock is explicitly documented to take a directory.

You essentially still need a directory if you want to unlock such files. fscrypt unlock is explicitly documented to take a directory.

I see that I need a directory argument of fscrypt unlock. The question is which directory I should specify to get access to a particular file. The real life case that I moved a file not expecting such effect. I was really surprised when I realized that I can not access a file outside any encrypted directory. Fortunately this case there was just a few encrypted directories and I have a guess concerning origin of the file. My opinion is that such case should be either prevented (in kernel?) or user-space utilities should have a way to associate a file and a protector.

The question is which directory I should specify to get access to a particular file.

The one that the files were moved out of originally.

There's no way to query the policy from loose files like this. This is a kernel limitation, so there's nothing that the fscrypt program can do to make this better. Again, this is an edge case this is not really supported. I recommend not leaving loose encrypted files around like this --- they should all be kept in encrypted directories.

There's no way to query the policy from loose files like this. This is a kernel limitation, so there's nothing that the fscrypt program can do to make this better.

Thank you for clarification. I had a hope, there is a way to find association with original directories.

I recommend not leaving loose encrypted files around like this --- they should all be kept in encrypted directories.

That case it was not intentional. I am afraid it may happen in future.

In the README file I have noticed that moving file into an encrypted directory actually works as copy and unlink. I expected it may be reciprocal with moving files in the opposite direction. I am realizing that it is a question related to kernel. I have not figured out what is the appropriate place to ask it. My expectation is that developers created a quite specific user-space tool may be familiar with kernel internals as well. On the other hand just a few kernel developers may be familiar with the feature.

I see that nothing better than adding an extra warning to the README file may be done. Thank you again.

Yes, it may be worth a subsection in Troubleshooting in the README.

The proper place to ask questions about the kernel side of filesystem encryption is on the mailing list linux-fscrypt@vger.kernel.org. I maintain the kernel side too, so it may still be me responding to any questions there. But it's the correct place, especially considering that the fscrypt userspace tool (this project) is just one of several users of the kernel's filesystem encryption support.

The ability to move encrypted files into an unencrypted directory existed in the original version of ext4 encryption which was merged into the kernel in 2015. That predates me getting involved. I'd guess that this behavior was a result of it being desirable to support moving encrypted directories into unencrypted directories. If regular files aren't treated any differently, that results in the behavior in question. Note that changing this would break any users who are relying on the current behavior. So, it's not clear that it would even be possible to change it. The Linux kernel provides strong backwards compatibility guarantees.

Thank you for the address of the kernel mailing list.

Moving encrypted subdirectories makes sense. I see no issues with encrypted files appeared outside of original directory this way. status, unlock, and lock works in this case.

I see that a file may be passed to fscrypt status instead of a directory. It works perfectly when the parent directory is unlocked or a file is not encrypted. However the following error may be reported:

fscrypt status not-encrypted/file-a
[ERROR] fscrypt status: open not-encrypted/file-a: required key not available

It may happen even if the file is not moved outside of the original directory.

This error might be handled to report that the file is encrypted. If the directory is not encrypted then a warning may be added that such case is not supported. Perhaps the error happens at

file, err := os.Open(path)

It is just an idea. I would not mind if you discard it as adding more code complexity than real value.

#396 improves the error message.

Thank you, @ebiggers. I have not try the change in action, however the code looks like a clear improvement of error handling.

I was considered calling GetPolicy(filepath.Dir(path)) in response to ENOKEY, however some complications may arise. path may be a symlink, so it is necessary to get real path first. Since an encrypted file may reside in an unencrypted directory, I am unsure if in an encrypted directory may contain files created with different policies.

So I agree that it is fine to stop with the current error message. Attempts of further improvements may introduce new kind of confusion.