<feed xmlns='http://www.w3.org/2005/Atom'>
<title>fscrypt.git/actions/recovery.go, branch master</title>
<subtitle>Go tool for managing Linux filesystem encryption
</subtitle>
<link rel='alternate' type='text/html' href='https://git.hodgden.net/cgit.cgi/fscrypt.git/'/>
<entry>
<title>recovery: add O_NOFOLLOW|O_EXCL to prevent symlink-following in recovery file creation</title>
<updated>2026-04-15T06:30:23+00:00</updated>
<author>
<name>Karan Kurani</name>
<email>karankurani3k@gmail.com</email>
</author>
<published>2026-04-13T18:02:12+00:00</published>
<link rel='alternate' type='text/html' href='https://git.hodgden.net/cgit.cgi/fscrypt.git/commit/?id=2dee71cdc2a7bccead530a42dfd10736e8de45a9'/>
<id>2dee71cdc2a7bccead530a42dfd10736e8de45a9</id>
<content type='text'>
WriteRecoveryInstructions() opens the recovery README with os.OpenFile
using O_WRONLY|O_CREATE without O_NOFOLLOW. When fscrypt encrypt runs
as root, this allows a local attacker to place a symlink at the recovery
file path, causing root to write through the symlink and then fchown the
target file to the attacker. Adding O_EXCL|O_NOFOLLOW aligns with the
existing security pattern in filesystem.go:608 and filesystem.go:747.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
WriteRecoveryInstructions() opens the recovery README with os.OpenFile
using O_WRONLY|O_CREATE without O_NOFOLLOW. When fscrypt encrypt runs
as root, this allows a local attacker to place a symlink at the recovery
file path, causing root to write through the symlink and then fchown the
target file to the attacker. Adding O_EXCL|O_NOFOLLOW aligns with the
existing security pattern in filesystem.go:608 and filesystem.go:747.
</pre>
</div>
</content>
</entry>
<entry>
<title>Switch to google.golang.org/protobuf/proto</title>
<updated>2022-04-09T06:38:01+00:00</updated>
<author>
<name>Eric Biggers</name>
<email>ebiggers@google.com</email>
</author>
<published>2022-04-09T06:16:59+00:00</published>
<link rel='alternate' type='text/html' href='https://git.hodgden.net/cgit.cgi/fscrypt.git/commit/?id=ca7a84b8aea203025acbda193f78ea98946236b5'/>
<id>ca7a84b8aea203025acbda193f78ea98946236b5</id>
<content type='text'>
github.com/golang/protobuf/proto has been deprecated in favor of
google.golang.org/protobuf/proto, so migrate to the non-deprecated one.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
github.com/golang/protobuf/proto has been deprecated in favor of
google.golang.org/protobuf/proto, so migrate to the non-deprecated one.
</pre>
</div>
</content>
</entry>
<entry>
<title>Make all new metadata files owned by user when needed</title>
<updated>2022-02-23T20:35:04+00:00</updated>
<author>
<name>Eric Biggers</name>
<email>ebiggers@google.com</email>
</author>
<published>2022-02-23T20:35:04+00:00</published>
<link rel='alternate' type='text/html' href='https://git.hodgden.net/cgit.cgi/fscrypt.git/commit/?id=d4ce0b892cbe68db9f90f4015342e6a9069b079c'/>
<id>d4ce0b892cbe68db9f90f4015342e6a9069b079c</id>
<content type='text'>
Since commit 4c7c6631cc5a ("Set owner of login protectors to correct
user"), login protectors are made owned by the user when root creates
one on a user's behalf.  That's good, but the same isn't true of other
files that get created at the same time:

- The policy protecting the directory
- The protector link file, if the policy is on a different filesystem
- The recovery protector, if the policy is on a different filesystem
- The recovery instructions file

In preparation for setting all metadata files to mode 0600, start making
all these files owned by the user in this scenario as well.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Since commit 4c7c6631cc5a ("Set owner of login protectors to correct
user"), login protectors are made owned by the user when root creates
one on a user's behalf.  That's good, but the same isn't true of other
files that get created at the same time:

- The policy protecting the directory
- The protector link file, if the policy is on a different filesystem
- The recovery protector, if the policy is on a different filesystem
- The recovery instructions file

In preparation for setting all metadata files to mode 0600, start making
all these files owned by the user in this scenario as well.
</pre>
</div>
</content>
</entry>
<entry>
<title>Adjust recovery passphrase generation</title>
<updated>2021-10-05T22:30:30+00:00</updated>
<author>
<name>Eric Biggers</name>
<email>ebiggers@google.com</email>
</author>
<published>2021-09-14T21:12:39+00:00</published>
<link rel='alternate' type='text/html' href='https://git.hodgden.net/cgit.cgi/fscrypt.git/commit/?id=7fed63a84963cbd790e86a0e59ff14724bcf33c4'/>
<id>7fed63a84963cbd790e86a0e59ff14724bcf33c4</id>
<content type='text'>
As per the feedback at https://github.com/google/fscrypt/issues/115
where users didn't understand that the recovery passphrase is important,
restore the original behavior where recovery passphrase generation
happens automatically without a prompt.  This applies to the case where
'fscrypt encrypt' is using a login protector on a non-root filesystem.

However, leave the --no-recovery option so that the recovery passphrase
can still be disabled if the user really wants to.  Also, clarify the
information provided about the recovery passphrase.

Update https://github.com/google/fscrypt/issues/115
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
As per the feedback at https://github.com/google/fscrypt/issues/115
where users didn't understand that the recovery passphrase is important,
restore the original behavior where recovery passphrase generation
happens automatically without a prompt.  This applies to the case where
'fscrypt encrypt' is using a login protector on a non-root filesystem.

However, leave the --no-recovery option so that the recovery passphrase
can still be disabled if the user really wants to.  Also, clarify the
information provided about the recovery passphrase.

Update https://github.com/google/fscrypt/issues/115
</pre>
</div>
</content>
</entry>
<entry>
<title>actions/protector: improve errors</title>
<updated>2020-05-09T22:21:31+00:00</updated>
<author>
<name>Eric Biggers</name>
<email>ebiggers@google.com</email>
</author>
<published>2020-05-09T21:52:07+00:00</published>
<link rel='alternate' type='text/html' href='https://git.hodgden.net/cgit.cgi/fscrypt.git/commit/?id=37457cce5b0436493dba7cdac6e1af5f51d25f47'/>
<id>37457cce5b0436493dba7cdac6e1af5f51d25f47</id>
<content type='text'>
ErrProtectorName:
	Rename to ErrLoginProtectorName for clarity, and include the
	name and user.

ErrMissingProtectorName:
	Include the correct protector source.

ErrDuplicateName:
	Rename to ErrProtectorNameExists for clarity, and remove a level
	of wrapping by including the name directly.

ErrDuplicateUID:
	Rename to ErrLoginProtectorExists for clarity, and remove a
	level of wrapping by including the user directly.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
ErrProtectorName:
	Rename to ErrLoginProtectorName for clarity, and include the
	name and user.

ErrMissingProtectorName:
	Include the correct protector source.

ErrDuplicateName:
	Rename to ErrProtectorNameExists for clarity, and remove a level
	of wrapping by including the name directly.

ErrDuplicateUID:
	Rename to ErrLoginProtectorExists for clarity, and remove a
	level of wrapping by including the user directly.
</pre>
</div>
</content>
</entry>
<entry>
<title>actions/recovery: revert protector if it can't be added to policy</title>
<updated>2020-01-28T18:45:52+00:00</updated>
<author>
<name>Eric Biggers</name>
<email>ebiggers@google.com</email>
</author>
<published>2020-01-28T04:16:35+00:00</published>
<link rel='alternate' type='text/html' href='https://git.hodgden.net/cgit.cgi/fscrypt.git/commit/?id=4e0230bdbc9cf893099919170a10e44f84422747'/>
<id>4e0230bdbc9cf893099919170a10e44f84422747</id>
<content type='text'>
Ensure that a failed AddRecoveryPassphrase() doesn't leave around an
unneeded protector file.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Ensure that a failed AddRecoveryPassphrase() doesn't leave around an
unneeded protector file.
</pre>
</div>
</content>
</entry>
<entry>
<title>actions/recovery: ensure recovery passphrase is really custom_passphrase</title>
<updated>2020-01-28T03:24:30+00:00</updated>
<author>
<name>Eric Biggers</name>
<email>ebiggers@google.com</email>
</author>
<published>2020-01-28T03:24:30+00:00</published>
<link rel='alternate' type='text/html' href='https://git.hodgden.net/cgit.cgi/fscrypt.git/commit/?id=d5b8bdcfba528c0c0e9f8052a705e454b26cb28f'/>
<id>d5b8bdcfba528c0c0e9f8052a705e454b26cb28f</id>
<content type='text'>
If the login protector was just created by the same 'fscrypt encrypt'
command, then policy.Context.Config.Source will be pam_passphrase.  This
needs to be overridden to custom_passphrase when creating the protector
for the recovery passphrase.

This fixes the following error:

    fscrypt encrypt: login protectors do not need a name

Resolves https://github.com/google/fscrypt/issues/187
Update https://github.com/google/fscrypt/issues/186
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
If the login protector was just created by the same 'fscrypt encrypt'
command, then policy.Context.Config.Source will be pam_passphrase.  This
needs to be overridden to custom_passphrase when creating the protector
for the recovery passphrase.

This fixes the following error:

    fscrypt encrypt: login protectors do not need a name

Resolves https://github.com/google/fscrypt/issues/187
Update https://github.com/google/fscrypt/issues/186
</pre>
</div>
</content>
</entry>
<entry>
<title>Automatically generate recovery passphrase when useful</title>
<updated>2020-01-23T03:05:06+00:00</updated>
<author>
<name>Eric Biggers</name>
<email>ebiggers@google.com</email>
</author>
<published>2019-11-27T20:04:13+00:00</published>
<link rel='alternate' type='text/html' href='https://git.hodgden.net/cgit.cgi/fscrypt.git/commit/?id=8cd1b3ba2e7a12cd68e2dfd0cbb5ec09ff92783b'/>
<id>8cd1b3ba2e7a12cd68e2dfd0cbb5ec09ff92783b</id>
<content type='text'>
If a user re-installs their system (or otherwise loses the /.fscrypt
directory on the root filesystem) they also lose access to any login
passphrase-protected directories on other filesystems, unless additional
protectors were manually added.  This can be unexpected, as it may be
expected that the old login passphrase would still work.

We can't really fix this by storing a login protector on every
filesystem because:

- If a user were to have N login protectors, it would take them N times
  longer to log in, as every login protector would need to be unlocked.

- If a user were to change their login passphrase while any external
  volumes were unmounted, login protectors would get out of sync.

- It's preferable that an external volume isn't unlockable by itself
  using only a login passphrase, as login passphrases are often weak.

Instead, generate a recovery passphrase when creating a login
passphrase-protected directory on a non-root filesystem.

The recovery passphrase is added as a custom_passphrase protector, thus
giving the policy two protectors: one pam_passphrase and one
custom_passphrase.  Then this passphrase is written to a file in the new
encrypted directory.  Writing the passphrase to a file here is okay
since it's encrypted, but it's obviously useless by itself; it's up to
the user to store this passphrase somewhere else if they need it.

Use a recovery passphrase instead of a "recovery code" that encodes the
policy key directly because a passphrase is more user-friendly: it can
safely be made much shorter than a key, and it works just like any other
fscrypt protector.  Also, it's not as critical to allow recovery when
the .fscrypt directory on the *same* filesystem is deleted.

Resolves https://github.com/google/fscrypt/issues/164
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
If a user re-installs their system (or otherwise loses the /.fscrypt
directory on the root filesystem) they also lose access to any login
passphrase-protected directories on other filesystems, unless additional
protectors were manually added.  This can be unexpected, as it may be
expected that the old login passphrase would still work.

We can't really fix this by storing a login protector on every
filesystem because:

- If a user were to have N login protectors, it would take them N times
  longer to log in, as every login protector would need to be unlocked.

- If a user were to change their login passphrase while any external
  volumes were unmounted, login protectors would get out of sync.

- It's preferable that an external volume isn't unlockable by itself
  using only a login passphrase, as login passphrases are often weak.

Instead, generate a recovery passphrase when creating a login
passphrase-protected directory on a non-root filesystem.

The recovery passphrase is added as a custom_passphrase protector, thus
giving the policy two protectors: one pam_passphrase and one
custom_passphrase.  Then this passphrase is written to a file in the new
encrypted directory.  Writing the passphrase to a file here is okay
since it's encrypted, but it's obviously useless by itself; it's up to
the user to store this passphrase somewhere else if they need it.

Use a recovery passphrase instead of a "recovery code" that encodes the
policy key directly because a passphrase is more user-friendly: it can
safely be made much shorter than a key, and it works just like any other
fscrypt protector.  Also, it's not as critical to allow recovery when
the .fscrypt directory on the *same* filesystem is deleted.

Resolves https://github.com/google/fscrypt/issues/164
</pre>
</div>
</content>
</entry>
</feed>
