Skip to content

Translate fcntl flock l_type between Linux and macOS#80

Merged
jserv merged 1 commit into
sysprog21:mainfrom
Max042004:fix-fcntl-flock-ltype
Jun 6, 2026
Merged

Translate fcntl flock l_type between Linux and macOS#80
jserv merged 1 commit into
sysprog21:mainfrom
Max042004:fix-fcntl-flock-ltype

Conversation

@Max042004
Copy link
Copy Markdown
Collaborator

@Max042004 Max042004 commented Jun 6, 2026

Problem

The F_GETLK/F_SETLK/F_SETLKW handler in src/syscall/fs.c copied the
guest's l_type field straight into the host struct flock, on the
assumption (stated in a comment) that the lock-type constants match. They do
not:

constant Linux aarch64 macOS / BSD
F_RDLCK 0 1
F_WRLCK 1 3
F_UNLCK 2 2

A Linux F_RDLCK (0) is not a valid lock type on macOS, so the host
fcntl() rejects it with EINVAL. POSIX-locking databases take a shared
read lock first, so this breaks them. Concretely, SQLite fails to open any
on-disk database
with disk I/O error (10): its initial F_RDLCK on the
1 GiB "pending byte" never succeeds. In-memory databases are unaffected,
which is what made this easy to miss.

Trace from a failing sqlite3 file.db "CREATE TABLE ..." under --verbose:

syscall 25@... (0x3, 0x6, 0x7ffc490, ...)   # fcntl(fd=3, F_SETLK=6, &flock)
  -> -22 (EINVAL)

Fix

Map l_type Linux→macOS on input for all three commands, and map it back
macOS→Linux when writing the F_GETLK result. Unknown types are rejected
with EINVAL rather than passed through.

Test

Adds tests/test-flock.c (registered in manifest.txt under "Syscall
coverage tests"), which exercises F_SETLK/F_SETLKW/F_GETLK around the
same 1 GiB pending-byte offsets SQLite uses. It fails with errno 22
before this change and passes after
— verified by reverting the fix.

Validation

  • make check: all 97 tests pass (including the new test-flock).
  • Local CI replication: check-newline, check-format (clang-format 22),
    check-security, cppcheck, syscall-dispatch consistency, and
    make lint all clean; make elfuse builds and codesigns.
  • End-to-end with a statically cross-compiled aarch64 SQLite 3.47.2: on-disk
    CRUD, transactions, JSON1 function indexes, FTS5, WAL + wal_checkpoint,
    a 50k-row transaction, and .dump/.read round-trips all succeed; the
    resulting file is readable by the host sqlite3.

Summary by cubic

Fixes fcntl lock-type translation between Linux guests and macOS hosts to prevent EINVAL on valid read locks. Restores on-disk SQLite and other POSIX-locking apps by correctly mapping l_type for F_GETLK, F_SETLK, and F_SETLKW.

  • Bug Fixes
    • Map l_type Linux→macOS on input and macOS→Linux on F_GETLK output; reject unknown types with EINVAL.
    • Add tests/test-flock.c (registered in tests/manifest.txt) to cover SQLite’s pending-byte lock pattern; failed before, passes now.

Written for commit 63e7a93. Summary will update on new commits.

Review in cubic

The F_GETLK/F_SETLK/F_SETLKW handler copied the guest's l_type field
straight into the host struct flock, on the assumption (stated in a
comment) that the lock-type constants match. They do not:

  Linux aarch64: F_RDLCK=0, F_WRLCK=1, F_UNLCK=2
  macOS/BSD:     F_RDLCK=1, F_UNLCK=2, F_WRLCK=3

A Linux F_RDLCK (0) is not a valid type on macOS, so the host fcntl()
rejected it with EINVAL. POSIX-locking databases take a shared read
lock first -- SQLite, for example, fails to open any on-disk database
with "disk I/O error" because its initial F_RDLCK on the pending byte
never succeeds.

Map l_type Linux->macOS on input for all three commands, and map it
back macOS->Linux when writing the F_GETLK result, rejecting unknown
types with EINVAL.

Add test-flock, which locks around SQLite's 1GiB pending-byte offsets;
it fails with errno 22 before this change and passes after.
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 3 files

Re-trigger cubic

@jserv jserv merged commit 99fe7ed into sysprog21:main Jun 6, 2026
5 checks passed
@jserv
Copy link
Copy Markdown
Contributor

jserv commented Jun 6, 2026

Thank @Max042004 for contributing!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants