/*
 *  Copyright (C) 2006 IBM Corporation
 *
 *  Author: Serge Hallyn <serue@us.ibm.com>
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU General Public License as
 *  published by the Free Software Foundation, version 2 of the
 *  License.
 *
 *  Jun 2006 - namespaces support
 *             OpenVZ, SWsoft Inc.
 *             Pavel Emelianov <xemul@openvz.org>
 */

#include <linux/module.h>
#include <linux/version.h>
#include <linux/nsproxy.h>
#include <linux/init_task.h>
#include <linux/mnt_namespace.h>
#include <linux/utsname.h>
#include <linux/pid_namespace.h>

struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy);

static inline void get_nsproxy(struct nsproxy *ns)
{
	atomic_inc(&ns->count);
}

void get_task_namespaces(struct task_struct *tsk)
{
	struct nsproxy *ns = tsk->nsproxy;
	if (ns) {
		get_nsproxy(ns);
	}
}

/*
 * creates a copy of "orig" with refcount 1.
 * This does not grab references to the contained namespaces,
 * so that needs to be done by dup_namespaces.
 */
static inline struct nsproxy *clone_namespaces(struct nsproxy *orig)
{
	struct nsproxy *ns;

	ns = kmemdup(orig, sizeof(struct nsproxy), GFP_KERNEL);
	if (ns)
		atomic_set(&ns->count, 1);
	return ns;
}

/*
 * copies the nsproxy, setting refcount to 1, and grabbing a
 * reference to all contained namespaces.  Called from
 * sys_unshare()
 */
struct nsproxy *dup_namespaces(struct nsproxy *orig)
{
	struct nsproxy *ns = clone_namespaces(orig);

	if (ns) {
		if (ns->mnt_ns)
			get_mnt_ns(ns->mnt_ns);
		if (ns->uts_ns)
			get_uts_ns(ns->uts_ns);
		if (ns->ipc_ns)
			get_ipc_ns(ns->ipc_ns);
		if (ns->pid_ns)
			get_pid_ns(ns->pid_ns);
	}

	return ns;
}

/*
 * called from clone.  This now handles copy for nsproxy and all
 * namespaces therein.
 */
int copy_namespaces(int flags, struct task_struct *tsk)
{
	struct nsproxy *old_ns = tsk->nsproxy;
	struct nsproxy *new_ns;
	int err = 0;

	if (!old_ns)
		return 0;

	get_nsproxy(old_ns);

	if (!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC)))
		return 0;

	new_ns = clone_namespaces(old_ns);
	if (!new_ns) {
		err = -ENOMEM;
		goto out;
	}

	tsk->nsproxy = new_ns;

	err = copy_mnt_ns(flags, tsk);
	if (err)
		goto out_ns;

	err = copy_utsname(flags, tsk);
	if (err)
		goto out_uts;

	err = copy_ipcs(flags, tsk);
	if (err)
		goto out_ipc;

	err = copy_pid_ns(flags, tsk);
	if (err)
		goto out_pid;

out:
	put_and_finalize_nsproxy(old_ns);
	return err;

out_pid:
	if (new_ns->ipc_ns)
		put_ipc_ns(new_ns->ipc_ns);
out_ipc:
	if (new_ns->uts_ns)
		put_uts_ns(new_ns->uts_ns);
out_uts:
	if (new_ns->mnt_ns)
		put_mnt_ns(new_ns->mnt_ns);
out_ns:
	tsk->nsproxy = old_ns;
	kfree(new_ns);
	goto out;
}

struct nsproxy *put_nsproxy(struct nsproxy *ns)
{
	if (ns) {
		if (atomic_dec_and_test(&ns->count)) {
			if (ns->mnt_ns) {
				put_mnt_ns(ns->mnt_ns);
				ns->mnt_ns = NULL;
			}
			return ns;
		}
	}
	return NULL;
}

void free_nsproxy(struct nsproxy *ns)
{
	if (ns->mnt_ns)
		put_mnt_ns(ns->mnt_ns);
	if (ns->uts_ns)
		put_uts_ns(ns->uts_ns);
	if (ns->ipc_ns)
		put_ipc_ns(ns->ipc_ns);
	if (ns->pid_ns)
		put_pid_ns(ns->pid_ns);
	kfree(ns);
}
