softoken sdb_init() fails to create key4.db/cert9.db on CIFS/SMB shares because the network-FS-type check runs after the initial schema CREATE TABLE
Categories
(NSS :: Libraries, defect, P3)
Tracking
(Not tracked)
People
(Reporter: rautyrauty, Unassigned)
Details
Steps to reproduce:
In lib/softoken/sdb.c::sdb_init(), the statfs() check that
enables cache-mode for network filesystems (added in bug 1456888,
fixed in NSS 3.38) runs after the initial BEGIN transaction
and the schema-creating CREATE TABLE / CREATE INDEX statements.
For an existing softoken DB this is harmless. For the very first
creation on a CIFS share the schema statements never reach the
network-FS branch: they take a SQLite reserved lock on the real
file, CIFS returns it as conflicting and never releasing, the
SDB_SQLITE_BUSY_TIMEOUT/SDB_MAX_BUSY_RETRIES loop exhausts, and
sdb_init exits with SDB_BUSY. key4.db and cert9.db never
come into existence and any NSS consumer silently loses access to
saved secrets.
Steps to reproduce
- Linux client. Mount a Samba share with default cifs-utils
options (cache=strict, brl on):
mount -t cifs //server/share /mnt/x -o guest,uid=$UID - Run Thunderbird (or any softoken consumer) against an empty
profile on the share:
thunderbird --profile /mnt/x/profile --no-remote - Configure any email account.
- Inspect the profile - pkcs11.txt is written, but key4.db
and cert9.db are missing. The password is not persisted; on
the next start the account is not activated.
Minimal reproducer without NSS, on the same mount:
sqlite3 /mnt/x/t.db "CREATE TABLE t(id); INSERT INTO t VALUES(1);"
=> Error: stepping, database is locked (5)
With mount -o cache=none,nobrl the same command succeeds, NSS
init succeeds, and TB account setup works end to end.
Cause
In lib/softoken/sdb.c::sdb_init() (NSS 3.124, sdb.c lines
~2076-2300) the order is:
line 2110: sdb_openDB(dbname, ...) // open
line 2128: sqlite3_exec(sqlDB, BEGIN_CMD, ...) // takes lock
line 2135+: sqlite3_exec(sqlDB, CREATE TABLE/INDEX) // first writes
line 2278: statfs(dbname) and switch (f_type) on // bug 1456888
SMB_SUPER_MAGIC / 0xff534d42 (CIFS) /
NFS_SUPER_MAGIC -> enableCache = PR_TRUE
line 2324: if (enableCache) -> set up cache backing in /tmp
Steps BEGIN_CMD and CREATE TABLE operate on the real file on
the share. On CIFS the kernel returns the POSIX advisory lock
SQLite requests as a conflict that never resolves, so the
SDB_SQLITE_BUSY_TIMEOUT = 1s + SDB_MAX_BUSY_RETRIES = 30 retry
loop (designed for transient busy from another local process)
cannot win - the lock is not transient. The cache-mode branch
introduced by bug 1456888 is correctly enabled for slow/network
filesystems, but its enableCache = PR_TRUE runs strictly after
the statements that need it most.
Suggestion
Move the statfs() FS-type detection above sdb_openDB() /
BEGIN_CMD, and for the network-FS branch take a different path
during initial creation, for example:
- create the schema in the cache backing (temp store) first,
then transfer it atomically onto the share with the existing
cache-flush logic; or - open the DB for the schema-init phase with ?nolock=1 in the
URI when the file is known to not exist yet (no other process
can hold a lock on a file we are about to create), then close
and re-open through the regular cache path; or - if neither is acceptable, add a distinct error code (e.g. a new
SEC_ERROR_* value mapping to CKR_TOKEN_NOT_RECOGNIZED) so
callers can present a meaningful "profile is on an unsupported
filesystem" message instead of a silent half-init.
nolock=1 is unsafe for shared concurrent use - but during the
initial create the file demonstrably has no other holders. The
mode would only be active for the schema-init phase.
References
- Bug 1456888 - added the statfs() FS-type detection (NFS, SMB,
CIFS, AFS) and the cache-mode plumbing this report builds on. - Bug 1444943 - companion Firefox-side change setting
NSS_SDB_USE_CACHE=yes for NFS-mounted profiles. - Bug 1568253 - related class of issue (slow Thunderbird on NFS,
cache not auto-enabled), still open. Different from this report:
that bug is about steady-state performance on NFS; this one is
about first-time creation failure on CIFS.
Downstream impact
Thunderbird 145+ relies on NSS-encrypted secrets through its new
Rust login storage. With a profile on a CIFS share and default
mount options, NSS init failure silently leaves Thunderbird's
password manager half-initialized: the new account survives in
prefs.js so the setup wizard refuses to re-add it ("already
exists"), but it never appears in the folder pane because there
is no credential to authenticate with. Reported in ALT Linux as
https://bugzilla.altlinux.org/57835. Current workaround for
users is mount.cifs -o cache=none,nobrl, which fully restores
both NSS init and the rest of Thunderbird's behaviour on the
share.
Actual results:
softoken init fails. NSS callers see a generic token
init failure (e.g. SEC_ERROR_LIBRARY_FAILURE downstream) with
no indication that the cause is the filesystem.
Expected results:
Either the open succeeds via the cache path that
bug 1456888 already wired up, or NSS fails fast with a distinct
error that callers can surface as "profile is on an unsupported
filesystem".
Updated•3 months ago
|
Description
•