Skip to content

Syscall fchmodat2 allows to create suid binaries  #10424

@Ma27

Description

@Ma27

Describe the bug

To quote from NixOS/nixpkgs#300635 (comment):

With kernel ≥6.6 and glibc 2.39, lxc's install phase uses fchmodat2, which slips through

/* Prevent builders from creating setuid/setgid binaries. */
for (int perm : { S_ISUID, S_ISGID }) {
if (seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(chmod), 1,
SCMP_A1(SCMP_CMP_MASKED_EQ, (scmp_datum_t) perm, (scmp_datum_t) perm)) != 0)
throw SysError("unable to add seccomp rule");
if (seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(fchmod), 1,
SCMP_A1(SCMP_CMP_MASKED_EQ, (scmp_datum_t) perm, (scmp_datum_t) perm)) != 0)
throw SysError("unable to add seccomp rule");
if (seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(fchmodat), 1,
SCMP_A2(SCMP_CMP_MASKED_EQ, (scmp_datum_t) perm, (scmp_datum_t) perm)) != 0)
throw SysError("unable to add seccomp rule");
}
. The fixupPhase then uses fchmodat, which fails.
With older kernel or glibc, setting the suid bit fails in the install phase, which is not treated as fatal, and then the fixup phase does not try to set it again.

As @lf- points out, the use of the seccomp sandbox against creating suid binaries is questionable (NixOS/nixpkgs#300635 (comment)) since the restriction can be bypassed easily by using the open(2) syscall for the exact same purpose and the permissions will be wiped later on.

What I'd like to achieve is that we get a fix for that scenario to make sure people aren't running into the problem when upgrading to 24.05. The builds from nixpkgs appear fixed (or actually, worked around), but a lot of people will also build custom stuff.

If you agree on removing the chmod restriction, that's one way forward.
If that requires further discussion, I'll file a patch to add fchmodat2 to

/* Prevent builders from creating setuid/setgid binaries. */
for (int perm : { S_ISUID, S_ISGID }) {
if (seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(chmod), 1,
SCMP_A1(SCMP_CMP_MASKED_EQ, (scmp_datum_t) perm, (scmp_datum_t) perm)) != 0)
throw SysError("unable to add seccomp rule");
if (seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(fchmod), 1,
SCMP_A1(SCMP_CMP_MASKED_EQ, (scmp_datum_t) perm, (scmp_datum_t) perm)) != 0)
throw SysError("unable to add seccomp rule");
if (seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(fchmodat), 1,
SCMP_A2(SCMP_CMP_MASKED_EQ, (scmp_datum_t) perm, (scmp_datum_t) perm)) != 0)
throw SysError("unable to add seccomp rule");
}
to have a short-term resolution.

cc @NixOS/nix-team
cc @vcunat
cc @lf-

Priorities

Add 👍 to issues you find important.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions