18b6e0414e
The user_ns is moved from nsproxy to user_struct, so that a struct cred by itself is sufficient to determine access (which it otherwise would not be). Corresponding ecryptfs fixes (by David Howells) are here as well. Fix refcounting. The following rules now apply: 1. The task pins the user struct. 2. The user struct pins its user namespace. 3. The user namespace pins the struct user which created it. User namespaces are cloned during copy_creds(). Unsharing a new user_ns is no longer possible. (We could re-add that, but it'll cause code duplication and doesn't seem useful if PAM doesn't need to clone user namespaces). When a user namespace is created, its first user (uid 0) gets empty keyrings and a clean group_info. This incorporates a previous patch by David Howells. Here is his original patch description: >I suggest adding the attached incremental patch. It makes the following >changes: > > (1) Provides a current_user_ns() macro to wrap accesses to current's user > namespace. > > (2) Fixes eCryptFS. > > (3) Renames create_new_userns() to create_user_ns() to be more consistent > with the other associated functions and because the 'new' in the name is > superfluous. > > (4) Moves the argument and permission checks made for CLONE_NEWUSER to the > beginning of do_fork() so that they're done prior to making any attempts > at allocation. > > (5) Calls create_user_ns() after prepare_creds(), and gives it the new creds > to fill in rather than have it return the new root user. I don't imagine > the new root user being used for anything other than filling in a cred > struct. > > This also permits me to get rid of a get_uid() and a free_uid(), as the > reference the creds were holding on the old user_struct can just be > transferred to the new namespace's creator pointer. > > (6) Makes create_user_ns() reset the UIDs and GIDs of the creds under > preparation rather than doing it in copy_creds(). > >David >Signed-off-by: David Howells <dhowells@redhat.com> Changelog: Oct 20: integrate dhowells comments 1. leave thread_keyring alone 2. use current_user_ns() in set_user() Signed-off-by: Serge Hallyn <serue@us.ibm.com>
93 lines
2.4 KiB
C
93 lines
2.4 KiB
C
#ifndef _LINUX_NSPROXY_H
|
|
#define _LINUX_NSPROXY_H
|
|
|
|
#include <linux/spinlock.h>
|
|
#include <linux/sched.h>
|
|
|
|
struct mnt_namespace;
|
|
struct uts_namespace;
|
|
struct ipc_namespace;
|
|
struct pid_namespace;
|
|
|
|
/*
|
|
* A structure to contain pointers to all per-process
|
|
* namespaces - fs (mount), uts, network, sysvipc, etc.
|
|
*
|
|
* 'count' is the number of tasks holding a reference.
|
|
* The count for each namespace, then, will be the number
|
|
* of nsproxies pointing to it, not the number of tasks.
|
|
*
|
|
* The nsproxy is shared by tasks which share all namespaces.
|
|
* As soon as a single namespace is cloned or unshared, the
|
|
* nsproxy is copied.
|
|
*/
|
|
struct nsproxy {
|
|
atomic_t count;
|
|
struct uts_namespace *uts_ns;
|
|
struct ipc_namespace *ipc_ns;
|
|
struct mnt_namespace *mnt_ns;
|
|
struct pid_namespace *pid_ns;
|
|
struct net *net_ns;
|
|
};
|
|
extern struct nsproxy init_nsproxy;
|
|
|
|
/*
|
|
* the namespaces access rules are:
|
|
*
|
|
* 1. only current task is allowed to change tsk->nsproxy pointer or
|
|
* any pointer on the nsproxy itself
|
|
*
|
|
* 2. when accessing (i.e. reading) current task's namespaces - no
|
|
* precautions should be taken - just dereference the pointers
|
|
*
|
|
* 3. the access to other task namespaces is performed like this
|
|
* rcu_read_lock();
|
|
* nsproxy = task_nsproxy(tsk);
|
|
* if (nsproxy != NULL) {
|
|
* / *
|
|
* * work with the namespaces here
|
|
* * e.g. get the reference on one of them
|
|
* * /
|
|
* } / *
|
|
* * NULL task_nsproxy() means that this task is
|
|
* * almost dead (zombie)
|
|
* * /
|
|
* rcu_read_unlock();
|
|
*
|
|
*/
|
|
|
|
static inline struct nsproxy *task_nsproxy(struct task_struct *tsk)
|
|
{
|
|
return rcu_dereference(tsk->nsproxy);
|
|
}
|
|
|
|
int copy_namespaces(unsigned long flags, struct task_struct *tsk);
|
|
void exit_task_namespaces(struct task_struct *tsk);
|
|
void switch_task_namespaces(struct task_struct *tsk, struct nsproxy *new);
|
|
void free_nsproxy(struct nsproxy *ns);
|
|
int unshare_nsproxy_namespaces(unsigned long, struct nsproxy **,
|
|
struct fs_struct *);
|
|
|
|
static inline void put_nsproxy(struct nsproxy *ns)
|
|
{
|
|
if (atomic_dec_and_test(&ns->count)) {
|
|
free_nsproxy(ns);
|
|
}
|
|
}
|
|
|
|
static inline void get_nsproxy(struct nsproxy *ns)
|
|
{
|
|
atomic_inc(&ns->count);
|
|
}
|
|
|
|
#ifdef CONFIG_CGROUP_NS
|
|
int ns_cgroup_clone(struct task_struct *tsk, struct pid *pid);
|
|
#else
|
|
static inline int ns_cgroup_clone(struct task_struct *tsk, struct pid *pid)
|
|
{
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
#endif
|