From: Masatake YAMATO Date: Thu, 6 Mar 2025 23:44:30 +0000 (+0900) Subject: lsns: show NETNSID for namespaces with no process running X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fdf3008b692271889248f8b077f3a5a7cad77661;p=thirdparty%2Futil-linux.git lsns: show NETNSID for namespaces with no process running Fixes #3445 The original code doesn't collect NETNSID for netns namespaces with no process running. A way to reproduce this issue: # ip netns delete X # ip netns add X # ip netns set X 117 # ip netns show X (id: 117) netns-813c699f-4651-e5e9-6af4-cca568bf2c3a (id: 0) # stat /var/run/netns/X File: /var/run/netns/X Size: 0 Blocks: 0 IO Block: 4096 regular empty file Device: 0,4 Inode: 4026533679 Links: 1 Access: (0444/-r--r--r--) Uid: ( 0/ root) Gid: ( 0/ root) Context: system_u:object_r:nsfs_t:s0 Access: 2025-03-06 00:29:58.598605182 +0900 Modify: 2025-03-06 00:29:58.598605182 +0900 Change: 2025-03-06 00:29:58.598605182 +0900 Birth: - # ./lsns -P -o+NETNSID NS TYPE NPROCS PID USER COMMAND NETNSID 4026533679 net 0 root 4026534230 user 0 yamato NS 4026533679 should have "117" as the value of NETNSID. Though the original code defined netnsid member in struct lsns_namespace, the member wasn't used at all. struct lsns_process had a member having the same name. The original code used only the one in struct lsns_process. This change utilizes the netnsid member in struct lsns_namespace. I found another bug, so I will provide a test case for this fix in a subsequent commit. Signed-off-by: Masatake YAMATO --- diff --git a/sys-utils/lsns.c b/sys-utils/lsns.c index e4e714c6b..1cf9640b3 100644 --- a/sys-utils/lsns.c +++ b/sys-utils/lsns.c @@ -541,6 +541,18 @@ static int get_netnsid_via_netlink(int target_fd) return netnsid; } +static int get_netnsid_for_fd(int target_fd, ino_t netino) +{ + int netnsid; + + if (!netnsid_cache_find(netino, &netnsid)) { + netnsid = get_netnsid_via_netlink(target_fd); + netnsid_cache_add(netino, netnsid); + } + + return netnsid; +} + static int get_netnsid_for_pc_via_netlink(struct path_cxt *pc, const char *path) { int netnsid; @@ -772,7 +784,7 @@ static int namespace_has_process(struct lsns_namespace *ns, pid_t pid) } static struct lsns_namespace *add_namespace(struct lsns *ls, enum lsns_type type, ino_t ino, - ino_t parent_ino, ino_t owner_ino) + ino_t parent_ino, ino_t owner_ino, int netnsid) { struct lsns_namespace *ns = xcalloc(1, sizeof(*ns)); @@ -788,6 +800,7 @@ static struct lsns_namespace *add_namespace(struct lsns *ls, enum lsns_type type ns->id = ino; ns->related_id[RELA_PARENT] = parent_ino; ns->related_id[RELA_OWNER] = owner_ino; + ns->netnsid = netnsid; list_add_tail(&ns->namespaces, &ls->namespaces); return ns; @@ -872,6 +885,7 @@ static struct lsns_namespace *add_namespace_for_nsfd(struct lsns *ls, int fd, in struct lsns_namespace *ns; int clone_type; enum lsns_type lsns_type; + int netnsid; clone_type = lsns_ioctl(fd, NS_GET_NSTYPE); if (clone_type < 0) @@ -883,7 +897,11 @@ static struct lsns_namespace *add_namespace_for_nsfd(struct lsns *ls, int fd, in get_parent_ns_ino(fd, lsns_type, &ino_parent, &fd_parent); get_owner_ns_ino(fd, &ino_owner, &fd_owner); - ns = add_namespace(ls, lsns_type, ino, ino_parent, ino_owner); + netnsid = (lsns_type == LSNS_TYPE_NET) + ? get_netnsid_for_fd(fd, ino) + : LSNS_NETNS_UNUSABLE; + + ns = add_namespace(ls, lsns_type, ino, ino_parent, ino_owner, netnsid); lsns_ioctl(fd, NS_GET_OWNER_UID, &ns->uid_fallback); add_uid(uid_cache, ns->uid_fallback); @@ -1057,8 +1075,12 @@ static int read_assigned_namespaces(struct lsns *ls) if (proc->ns_ids[i] == 0) continue; if (!(ns = get_namespace(ls, proc->ns_ids[i]))) { + int netnsid = (i == LSNS_TYPE_NET) + ? proc->netnsid + : LSNS_NETNS_UNUSABLE; ns = add_namespace(ls, i, proc->ns_ids[i], - proc->ns_pids[i], proc->ns_oids[i]); + proc->ns_pids[i], proc->ns_oids[i], + netnsid); if (!ns) return -ENOMEM; } @@ -1210,10 +1232,8 @@ static void fill_column(struct lsns *ls, xasprintf(&str, "%s", get_id(uid_cache, proc? proc->uid: ns->uid_fallback)->name); break; case COL_NETNSID: - if (!proc) - break; if (ns->type == LSNS_TYPE_NET) - netnsid_xasputs(&str, proc->netnsid); + netnsid_xasputs(&str, ns->netnsid); break; case COL_NSFS: nsfs_xasputs(&str, ns, ls->tab, ls->no_wrap ? ',' : '\n');