Skip to content

lsns: show namespaces only kept alive by open file descriptors#2902

Merged
karelzak merged 2 commits into
util-linux:masterfrom
masatake:lsns--opened-ns
Apr 8, 2024
Merged

lsns: show namespaces only kept alive by open file descriptors#2902
karelzak merged 2 commits into
util-linux:masterfrom
masatake:lsns--opened-ns

Conversation

@masatake

@masatake masatake commented Apr 2, 2024

Copy link
Copy Markdown
Member

Close #1884.

# ip netns add foo
# ls -i /run/netns/foo
4026540683 /run/netns/foo
# sleep 999 4< /run/netns/foo & sleep 2
[1] 1187058

# ip netns delete foo
#  ./lsns -Q 'NPROCS == 0'
        NS TYPE NPROCS PID USER COMMAND
4026540683 net       0     root

Even after removing the nsfs file created by ip-netns-add, lsns successfully reports the namespace.

masatake added 2 commits April 2, 2024 22:38
Signed-off-by: Masatake YAMATO <yamato@redhat.com>
Close util-linux#1884.

Quoted from the original issue comment submitted by @hesch:

  It can happen, that a namespace is only kept alive by an open file
  descriptor of a program as ilustrated by A.B:

    1. 'ip netns add foo' - add a namespace
    2. 'sleep 999 4< /run/netns/foo & sleep 2' - open the fd to the
       namespace in a background job
    3. 'ip netns delete foo' - delete the namespace (only deletes
       the /run/netns/foo)

  Now there exists a namespace with no process running in it and it has
  no bind mount so it does not show up in /proc/mounts, but it is still
  there and could be mounted back.

Signed-off-by: Masatake YAMATO <yamato@redhat.com>
@karelzak

karelzak commented Apr 3, 2024

Copy link
Copy Markdown
Collaborator

Seems not related to the change:

diff-{{{
--- /home/runner/work/util-linux/util-linux/tests/expected/lslocks/lslocks-lease-w+HOLDERS	2024-04-02 15:01:29.920456549 +0000
+++ /home/runner/work/util-linux/util-linux/tests/output/lslocks/lslocks-lease-w+HOLDERS	2024-04-02 15:05:55.229715611 +0000
@@ -1,2 +1,3 @@
 test_mkfds LEASE  WRITE 0 0 1,test_mkfds,17\x0a1,test_mkfds,18
+test_mkfds LEASE  WRITE 0 0 1,test_mkfds,17\x0a1,test_mkfds,18
 # lease-w + COMMAND,TYPE,SIZE,MODE,START,END,HOLDERS + --raw --noheadings: 0
}}}-diff

@masatake

masatake commented Apr 3, 2024

Copy link
Copy Markdown
Member Author

A test case about the lsns lslocks command failed. Maybe we must add sleep N before reading /proc/locks. I will add a temporary commit to verify my idea.

@masatake

masatake commented Apr 4, 2024

Copy link
Copy Markdown
Member Author

About the failure of lslocks, a "SLEEP" was already added.
#2624

@karelzak karelzak merged commit 5ce970d into util-linux:master Apr 8, 2024
@axelkar

axelkar commented Sep 29, 2025

Copy link
Copy Markdown

Hi. This makes lsns require CONFIG_USER_NS. Is it within the scope of util-linux to support kernel configurations without it enabled?

@karelzak

karelzak commented Oct 1, 2025

Copy link
Copy Markdown
Collaborator

Hi. This makes lsns require CONFIG_USER_NS. Is it within the scope of util-linux to support kernel configurations without it enabled?

There are more places in util-linux where user namespaces are expected. The optimal solution is to detect the missing feature and continue without it if possible. From this point of view, I'm not sure if, for example:

	if (stat("/proc/self/ns/user", &st) < 0)
		err(EXIT_FAILURE, _("failed to do stat /proc/self/ns/user"));

is an optimal solution, maybe it would be better not to use err() but return -1 (or so), etc.

@masatake, what do you think?

@masatake

masatake commented Oct 1, 2025

Copy link
Copy Markdown
Member Author

@karelzak I agree with you; calling err() is too much.

The purpose of the function, including the line, is to get the st_dev of the device on which the "nsfs" file system is. Not only /proc/self/ns/user, but also the other dentries under /proc/self/ns, can be used as arguments for stat(2). Returning 0 or -1 is the last resort.
We can try other namespaces.

I will make a pull request implementing the fallbacks.

@axelkar, how can I quickly test lsns on a non-CONFIG_USER_NS kernel?
Do I have to configure and build a kernel by myself?

@axelkar

axelkar commented Oct 1, 2025

Copy link
Copy Markdown

how can I quickly test lsns on a non-CONFIG_USER_NS kernel? Do I have to configure and build a kernel by myself?

You either have to somehow mask out /proc/self/ns/user or build and build a kernel yourself. I actually have no idea why my device's OEM disabled CONFIG_USER_NS, since AOSP seems to have it enabled in defconfigs.

Here is a guide on how to create a userspace:
https://github.com/google/syzkaller/blob/d4d447cd780753901f9e00aa246cc835458a8f06/docs/linux/setup_ubuntu-host_qemu-vm_x86-64-kernel.md#create-debian-bullseye-linux-image

Though I'd do it with NixOS (refs: VM, easy kernel config modification)

$ nix-build '<nixpkgs/nixos>' -A vm -I nixos-config=./configuration.nix
$ QEMU_KERNEL_PARAMS=console=ttyS0 ./result/bin/run-nixos-vm -nographic; reset
# configuration.nix
{ pkgs, ... }:
{
  boot.loader.systemd-boot.enable = true;
  boot.loader.efi.canTouchEfiVariables = true;

  users.users.root.initialPassword = "root";

  boot.kernelPatches = [
    {
      name = "disable CONFIG_USER_NS";
      patch = null;
      extraConfig = ''
        USER_NS n
      '';
    }
  ];

  environment.systemPackages = [
    (pkgs.util-linux.overrideAttrs (previousAttrs: {
      patches = previousAttrs.patches ++ [
        ./0001-fix-lsns.patch
      ];
    }))
    # or
    (pkgs.util-linux.overrideAttrs {
      src = ./util-linux;
    })
  ];

  system.stateVersion = "25.05";
}

masatake added a commit to masatake/util-linux that referenced this pull request Oct 2, 2025
…ries

In 7d5036f ("lsns: show namespaces only kept alive by open file
descriptors"), I added a code that calls stat(2) on /proc/self/ns/user
and made lsns exit after reporting an error if the call failed. I
assumed /proc/self/ns/user would be available on all platforms.

As Axel Karjalainen reported (link below), that assumption was
wrong: on some platforms the file is absent. Exiting for this reason
is undesirable.

The stat(2) call is used to obtain the dev_t of the backing device of
nsfs. However, /proc/self/ns/user is not the only source; calling
stat(2) on other namespace files under /proc/self/ns yields the same
dev_t. This change iterates over entries under /proc/self/ns and uses
the first one whose stat(2) succeeds.

Reported-by: Axel Karjalainen <axel@axka.fi>
Link: util-linux#2902 (comment)
Fixes: 7d5036f ("lsns: show namespaces only kept alive by open file descriptors")
Signed-off-by: Masatake YAMATO <yamato@redhat.com>
masatake added a commit to masatake/util-linux that referenced this pull request Oct 2, 2025
…ries

In 7d5036f ("lsns: show namespaces only kept alive by open file
descriptors"), I added code that calls stat(2) on /proc/self/ns/user
and made lsns exit after reporting an error if the call failed. I
assumed /proc/self/ns/user would be available on all platforms.

As Axel Karjalainen reported (link below), that assumption was
wrong: on some platforms, the file is absent. Exiting for this reason
is undesirable.

The stat(2) call is used to obtain the dev_t of the backing device of
nsfs. However, /proc/self/ns/user is not the only source; calling
stat(2) on other namespace files under /proc/self/ns yields the same
dev_t. This change iterates over entries under /proc/self/ns and uses
the first one whose stat(2) succeeds.

Reported-by: Axel Karjalainen <axel@axka.fi>
Link: util-linux#2902 (comment)
Fixes: 7d5036f ("lsns: show namespaces only kept alive by open file descriptors")
Signed-off-by: Masatake YAMATO <yamato@redhat.com>
@masatake

masatake commented Oct 2, 2025

Copy link
Copy Markdown
Member Author

@axelkar Could you try #3772 ?

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.

lsns: show namespaces only kept alive by open file descriptors

3 participants