ipc/namespace.c

Source file repositories/reference/linux-study-clean/ipc/namespace.c

File Facts

System
Linux kernel
Corpus path
ipc/namespace.c
Extension
.c
Size
5911 bytes
Lines
258
Domain
Core OS
Bucket
IPC
Inferred role
Core OS: implementation source
Status
source implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0
/*
 * linux/ipc/namespace.c
 * Copyright (C) 2006 Pavel Emelyanov <xemul@openvz.org> OpenVZ, SWsoft Inc.
 */

#include <linux/ipc.h>
#include <linux/msg.h>
#include <linux/ipc_namespace.h>
#include <linux/rcupdate.h>
#include <linux/nsproxy.h>
#include <linux/slab.h>
#include <linux/cred.h>
#include <linux/fs.h>
#include <linux/mount.h>
#include <linux/user_namespace.h>
#include <linux/proc_ns.h>
#include <linux/nstree.h>
#include <linux/sched/task.h>

#include "util.h"

/*
 * The work queue is used to avoid the cost of synchronize_rcu in kern_unmount.
 */
static void free_ipc(struct work_struct *unused);
static DECLARE_WORK(free_ipc_work, free_ipc);

static struct ucounts *inc_ipc_namespaces(struct user_namespace *ns)
{
	return inc_ucount(ns, current_euid(), UCOUNT_IPC_NAMESPACES);
}

static void dec_ipc_namespaces(struct ucounts *ucounts)
{
	dec_ucount(ucounts, UCOUNT_IPC_NAMESPACES);
}

static struct ipc_namespace *create_ipc_ns(struct user_namespace *user_ns,
					   struct ipc_namespace *old_ns)
{
	struct ipc_namespace *ns;
	struct ucounts *ucounts;
	int err;

	err = -ENOSPC;
 again:
	ucounts = inc_ipc_namespaces(user_ns);
	if (!ucounts) {
		/*
		 * IPC namespaces are freed asynchronously, by free_ipc_work.
		 * If frees were pending, flush_work will wait, and
		 * return true. Fail the allocation if no frees are pending.
		 */
		if (flush_work(&free_ipc_work))
			goto again;
		goto fail;
	}

	err = -ENOMEM;
	ns = kzalloc_obj(struct ipc_namespace, GFP_KERNEL_ACCOUNT);
	if (ns == NULL)
		goto fail_dec;

	err = ns_common_init(ns);
	if (err)
		goto fail_free;

	ns_tree_gen_id(ns);
	ns->user_ns = get_user_ns(user_ns);
	ns->ucounts = ucounts;

	err = mq_init_ns(ns);
	if (err)
		goto fail_put;

	err = -ENOMEM;
	if (!setup_mq_sysctls(ns))
		goto fail_mq_mount;

	if (!setup_ipc_sysctls(ns))
		goto fail_mq_sysctls;

	err = msg_init_ns(ns);
	if (err)
		goto fail_ipc;

	sem_init_ns(ns);
	shm_init_ns(ns);
	ns_tree_add_raw(ns);

Annotation

Implementation Notes