Skip to content

SQL Server 2025 MCR container fails with "TLS error 4" on FIPS-enabled Linux hosts (APT package works fine) #958

@gjain-7

Description

@gjain-7

Description

The SQL Server 2025 MCR container image (mcr.microsoft.com/mssql/server:2025-CU3-ubuntu-24.04) crashes during TLS initialization on Linux hosts with FIPS enabled (/proc/sys/crypto/fips_enabled = 1).

The sqlservr binary from the APT package (mssql-server 17.0.4025.3-1, same CU3 version) starts successfully on the same FIPS host. Both binaries are the same size (7,029,328 bytes) but have different md5 hashes, suggesting different builds.

Error

2026-03-25 12:09:51.24 Server      Error: 49946, Severity: 16, State: 1.
2026-03-25 12:09:51.24 Server      Internal error occurred initializing the TLS configuration. Error code [4].
2026-03-25 12:09:51.25 Server      Error: 49947, Severity: 16, State: 1.
2026-03-25 12:09:51.25 Server      Unable to initialize the TLS configuration. The server is being shut down.

Reproduction

# On a Linux host with FIPS enabled (e.g., kernel 5.4.0-*-aws-fips):
cat /proc/sys/crypto/fips_enabled
# Output: 1

# MCR image fails:
docker run --rm -e ACCEPT_EULA=Y -e MSSQL_SA_PASSWORD='MyPass123!' \
  -e MSSQL_PID=developer mcr.microsoft.com/mssql/server:2025-CU3-ubuntu-24.04

# APT-installed mssql-server 17.0.4025.3-1 on same Ubuntu 24.04 base: works fine

Environment

  • Host kernel: 5.4.0-1154-aws-fips (FIPS enabled)
  • Image: mcr.microsoft.com/mssql/server:2025-CU3-ubuntu-24.04
  • Also tested 2025-latest -- same failure
  • SQL Server 2022 MCR image works fine on the same host
  • APT-installed mssql-server 17.0.4025.3-1 works fine on the same host

Root Cause Analysis

The MCR sqlservr binary reads /proc/sys/crypto/fips_enabled directly from the kernel. When it finds 1, it fails during TLS initialization. The following workarounds have no effect:

  • OPENSSL_FORCE_FIPS_MODE=0
  • GNUTLS_FORCE_FIPS_MODE=0
  • OPENSSL_CONF=/dev/null or custom openssl.cnf
  • --privileged (cannot write to /proc/sys/crypto/fips_enabled)

The FIPS provider module (fips.so) is not available in the image (only legacy.so), and no FIPS provider package exists in the Ubuntu 24.04 repos for the image.

Workaround

We created an LD_PRELOAD shim that intercepts open/openat/read syscalls and returns "0" when /proc/sys/crypto/fips_enabled is read. With this shim, SQL Server 2025 MCR starts successfully on FIPS hosts:

/* nofips.c - LD_PRELOAD shim to bypass FIPS check */
#define _GNU_SOURCE
#include <dlfcn.h>
#include <string.h>
#include <fcntl.h>
#include <stdarg.h>
#include <sys/types.h>
#include <unistd.h>

static const char FIPS_PATH[] = "/proc/sys/crypto/fips_enabled";
static __thread int fips_fd = -1;

static int check_fips(const char *pathname, int fd) {
    if (pathname && strcmp(pathname, FIPS_PATH) == 0) fips_fd = fd;
    return fd;
}

int open(const char *pathname, int flags, ...) {
    va_list args; mode_t mode = 0;
    if (flags & O_CREAT) { va_start(args, flags); mode = va_arg(args, int); va_end(args); }
    int (*real)(const char *, int, ...) = dlsym(RTLD_NEXT, "open");
    return check_fips(pathname, (flags & O_CREAT) ? real(pathname, flags, mode) : real(pathname, flags));
}

int openat(int dirfd, const char *pathname, int flags, ...) {
    va_list args; mode_t mode = 0;
    if (flags & O_CREAT) { va_start(args, flags); mode = va_arg(args, int); va_end(args); }
    int (*real)(int, const char *, int, ...) = dlsym(RTLD_NEXT, "openat");
    return check_fips(pathname, (flags & O_CREAT) ? real(dirfd, pathname, flags, mode) : real(dirfd, pathname, flags));
}

ssize_t read(int fd, void *buf, size_t count) {
    ssize_t (*real)(int, void *, size_t) = dlsym(RTLD_NEXT, "read");
    if (fd >= 0 && fd == fips_fd) {
        fips_fd = -1;
        if (count >= 2) { memcpy(buf, "0\n", 2); return 2; }
        if (count >= 1) { *(char *)buf = '0'; return 1; }
    }
    return real(fd, buf, count);
}

Compile and use:

gcc -shared -fPIC -o nofips.so nofips.c -ldl
LD_PRELOAD=/path/to/nofips.so /opt/mssql/bin/sqlservr

Request

Could the MCR image's sqlservr binary handle FIPS-enabled hosts gracefully (like the APT package binary does), or alternatively include the OpenSSL FIPS provider in the image?

Related issues:

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions