Skip to content

mkdir creates child directories with setuid+sticky bits (mode 05775) when parent has default POSIX ACLs #11036

@DeadBranches

Description

@DeadBranches

Hello, I encountered unexpected permission bits behavior (mkdir sets sticky/suid bits unexpectedly) when creating directories under default POSIX ACLs using uutils-coreutils mkdir. I'm sharing minimal reproduction steps and relevant logs (strace, ACL xattrs, etc.) below.

I wasn't able to extensively search the repository issue history. My apologies if this duplicates an existing report.

Summary

When a parent directory has default POSIX ACLs (system.posix_acl_default), creating a subdirectory using uutils mkdir can result in the new directory getting setuid + sticky bits set (example mode 05775, shown as drwsrwxr-t). The same creation using GNU coreutils /bin/mkdir does not show this behavior.

This came up for me via nushell, where mkdir is a built-in (and ^mkdir calls the external tool). The external mkdir behaves normally; the built-in one produces the unexpected mode bits.

Expected Behavior

Creating a directory under a parent with default ACLs should not introduce setuid or sticky bits unless explicitly requested. At minimum, I would expect behavior consistent with GNU /bin/mkdir under the same parent.

Actual behavior

uutils mkdir creates the directory and then runs fchmodat(..., 0155775), leaving the new directory with mode 05775 (drwsrwxr-t).

Reproduction

I've only tested this issue on my specific setup. For that reason, I'm including relevant lines from /etc/passwd and /etc/group

/etc/passwd

muffin:x:1001:1001::/home/muffin:/usr/local/bin/nu
svc-atuin:x:749:749::/opt/atuin:/usr/sbin/nologin

/etc/group

svc-atuin:x:749:muffin,svc-restic
muffin:x:1001:

1. Create a parent directory with normal permissions

sudo mkdir -p /srv/test
sudo chown svc-atuin:svc-atuin /srv/test

2. Control case: create a child directory using the external mkdir (works as expected)

# in nushell: external mkdir
^mkdir /srv/test/test-1
stat -c '%n  %A  %a' /srv/test/test-1

On my system this results in a normal mode (no sticky / no setuid). Example expectation from strace:

umask(000) = 022
umask(022) = 000
mkdirat(..., "/srv/test/test-1", 0777) = 0
fchmodat(..., "/srv/test/test-1", 0755) = 0

3. Add default ACLs to the parent (this is representative of the kind of ACL setup I use for service data)

sudo setfacl -m \
  u::rwx,u:svc-atuin:rwx,u:muffin:rwx, \
  g::rwx,g:svc-atuin:r-x, \
  m::rwx,o::--- \
  /srv/test

sudo setfacl -m \
  d:u::rwx,d:u:svc-atuin:rwx,d:u:muffin:rwx, \
  d:g::r-x,d:g:svc-atuin:r-x, \
  d:m::rwx,d:o::--- \
  /srv/test

4. Reproduce: create a child directory using uutils mkdir (in my case via Nushell built-in)

# in nushell: built-in mkdir
mkdir /srv/test/test-2
stat -c '%n  %A  %a' /srv/test/test-2

Actual result (example):

/srv/test/test-2  drwsrwxr-t  5775

So the child directory ends up with setuid + setgid + sticky, plus 775.

The key strace snippet (capturing the built-in mkdir call path) shows a post-create chmod with an unexpected mode:

umask(000)                      = 022
umask(022)                      = 000
mkdirat(AT_FDCWD, "/srv/test/test-2", 0777) = 0
fchmodat(AT_FDCWD, "/srv/test/test-2", 0155775) = 0

The 0155775 / 05775 is what introduces setuid+sticky.

ACL/xattr info
After applying default ACLs, the parent has these xattrs:

getfattr -d -m - /srv/test | sed -n '1,200p'

Example output (same structure as my real directory):

# file: srv/test
system.posix_acl_access=0sAgAAAAEABwD/////AgAHAO0CAAACAAcA6QMAAAQABQD/////CAAFAO0CAAAQAAcA/////yAAAAD/////
system.posix_acl_default=0sAgAAAAEABwD/////AgAHAO0CAAACAAcA6QMAAAQABQD/////CAAFAO0CAAAQAAcA/////yAAAAD/////

Hex view:

getfattr -n system.posix_acl_default -e hex /srv/test

Example:

system.posix_acl_default=0x0200000001000700ffffffff02000700ed02000002000700e903000004000500ffffffff08000500ed02000010000700ffffffff20000000ffffffff

Workaround

Using GNU coreutils mkdir avoids the issue. In Nushell this is ^mkdir ... (external command), or explicitly /bin/mkdir ....

Environment

OS/Distro version:
PRETTY_NAME="Debian GNU/Linux 11 (bullseye)"
NAME="Debian GNU/Linux"
VERSION_ID="11"
VERSION="11 (bullseye)"
VERSION_CODENAME=bullseye
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"

Kernel version:
6.1.21-v8+

Filesystem type:
ext2/ext3

Nushell version:
0.110.0

ACL-related package version:
getfacl 2.2.53

Current umask:
0022

Notes

I’m not sure if this is a uutils ACL handling bug or an intentional attempt to merge ACL-derived bits into the final mode that’s going wrong. The important symptom is that the computed chmod mode includes sticky/setuid bits even though the parent directory mode does not.

I'm experiencing this via Nushell, which uses the uutils-coreutils mkdir implementation internally. I don't have standalone uutils installed, so I can't directly provide its version.

Unfortunately, I am not available to respond to followups directed towards me on this issue, but thank you for receiving the bug report. I hope this helps.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions