Skip to content

Commit 9b3e150

Browse files
committed
pidfs: handle kernels without namespaces cleanly
The nsproxy structure contains nearly all of the namespaces associated with a task. When a given namespace type is not supported by this kernel the rules whether the corresponding pointer in struct nsproxy is NULL or always init_<ns_type>_ns differ per namespace. Ideally, that wouldn't be the case and for all namespace types we'd always set it to init_<ns_type>_ns when the corresponding namespace type isn't supported. Make sure we handle all namespaces where the pointer in struct nsproxy can be NULL when the namespace type isn't supported. Link: https://lore.kernel.org/r/20240722-work-pidfs-e6a83030f63e@brauner Fixes: 5b08bd4 ("pidfs: allow retrieval of namespace file descriptors") # mainline only Signed-off-by: Christian Brauner <[email protected]>
1 parent f60d38c commit 9b3e150

File tree

1 file changed

+42
-23
lines changed

1 file changed

+42
-23
lines changed

fs/pidfs.c

Lines changed: 42 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ static long pidfd_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
119119
struct task_struct *task __free(put_task) = NULL;
120120
struct nsproxy *nsp __free(put_nsproxy) = NULL;
121121
struct pid *pid = pidfd_pid(file);
122-
struct ns_common *ns_common;
122+
struct ns_common *ns_common = NULL;
123123

124124
if (arg)
125125
return -EINVAL;
@@ -146,54 +146,73 @@ static long pidfd_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
146146
switch (cmd) {
147147
/* Namespaces that hang of nsproxy. */
148148
case PIDFD_GET_CGROUP_NAMESPACE:
149-
get_cgroup_ns(nsp->cgroup_ns);
150-
ns_common = to_ns_common(nsp->cgroup_ns);
149+
if (IS_ENABLED(CONFIG_CGROUPS)) {
150+
get_cgroup_ns(nsp->cgroup_ns);
151+
ns_common = to_ns_common(nsp->cgroup_ns);
152+
}
151153
break;
152154
case PIDFD_GET_IPC_NAMESPACE:
153-
get_ipc_ns(nsp->ipc_ns);
154-
ns_common = to_ns_common(nsp->ipc_ns);
155+
if (IS_ENABLED(CONFIG_IPC_NS)) {
156+
get_ipc_ns(nsp->ipc_ns);
157+
ns_common = to_ns_common(nsp->ipc_ns);
158+
}
155159
break;
156160
case PIDFD_GET_MNT_NAMESPACE:
157161
get_mnt_ns(nsp->mnt_ns);
158162
ns_common = to_ns_common(nsp->mnt_ns);
159163
break;
160164
case PIDFD_GET_NET_NAMESPACE:
161-
ns_common = to_ns_common(nsp->net_ns);
162-
get_net_ns(ns_common);
165+
if (IS_ENABLED(CONFIG_NET_NS)) {
166+
ns_common = to_ns_common(nsp->net_ns);
167+
get_net_ns(ns_common);
168+
}
163169
break;
164170
case PIDFD_GET_PID_FOR_CHILDREN_NAMESPACE:
165-
get_pid_ns(nsp->pid_ns_for_children);
166-
ns_common = to_ns_common(nsp->pid_ns_for_children);
171+
if (IS_ENABLED(CONFIG_PID_NS)) {
172+
get_pid_ns(nsp->pid_ns_for_children);
173+
ns_common = to_ns_common(nsp->pid_ns_for_children);
174+
}
167175
break;
168176
case PIDFD_GET_TIME_NAMESPACE:
169-
get_time_ns(nsp->time_ns);
170-
ns_common = to_ns_common(nsp->time_ns);
171-
if (!nsp->time_ns)
172-
return -EINVAL;
177+
if (IS_ENABLED(CONFIG_TIME_NS)) {
178+
get_time_ns(nsp->time_ns);
179+
ns_common = to_ns_common(nsp->time_ns);
180+
}
173181
break;
174182
case PIDFD_GET_TIME_FOR_CHILDREN_NAMESPACE:
175-
get_time_ns(nsp->time_ns_for_children);
176-
ns_common = to_ns_common(nsp->time_ns_for_children);
183+
if (IS_ENABLED(CONFIG_TIME_NS)) {
184+
get_time_ns(nsp->time_ns_for_children);
185+
ns_common = to_ns_common(nsp->time_ns_for_children);
186+
}
177187
break;
178188
case PIDFD_GET_UTS_NAMESPACE:
179-
get_uts_ns(nsp->uts_ns);
180-
ns_common = to_ns_common(nsp->uts_ns);
189+
if (IS_ENABLED(CONFIG_UTS_NS)) {
190+
get_uts_ns(nsp->uts_ns);
191+
ns_common = to_ns_common(nsp->uts_ns);
192+
}
181193
break;
182194
/* Namespaces that don't hang of nsproxy. */
183195
case PIDFD_GET_USER_NAMESPACE:
184-
rcu_read_lock();
185-
ns_common = to_ns_common(get_user_ns(task_cred_xxx(task, user_ns)));
186-
rcu_read_unlock();
196+
if (IS_ENABLED(CONFIG_USER_NS)) {
197+
rcu_read_lock();
198+
ns_common = to_ns_common(get_user_ns(task_cred_xxx(task, user_ns)));
199+
rcu_read_unlock();
200+
}
187201
break;
188202
case PIDFD_GET_PID_NAMESPACE:
189-
rcu_read_lock();
190-
ns_common = to_ns_common(get_pid_ns(task_active_pid_ns(task)));
191-
rcu_read_unlock();
203+
if (IS_ENABLED(CONFIG_PID_NS)) {
204+
rcu_read_lock();
205+
ns_common = to_ns_common( get_pid_ns(task_active_pid_ns(task)));
206+
rcu_read_unlock();
207+
}
192208
break;
193209
default:
194210
return -ENOIOCTLCMD;
195211
}
196212

213+
if (!ns_common)
214+
return -EOPNOTSUPP;
215+
197216
/* open_namespace() unconditionally consumes the reference */
198217
return open_namespace(ns_common);
199218
}

0 commit comments

Comments
 (0)