Re: [PATCHv1 5/8] cgroup: introduce cgroup namespaces

2014-10-24 Thread Serge E. Hallyn
Quoting Aditya Kali (adityak...@google.com):
> >> +void free_cgroup_ns(struct cgroup_namespace *ns)
> >> +{
> >> + cgroup_put(ns->root_cgrp);
> >> + put_user_ns(ns->user_ns);
> >
> > This is a problem on error patch in copy_cgroup_ns.  The
> > alloc_cgroup_ns() doesn't initialize these values, so if
> > you should fail in proc_alloc_inum() you'll show up here
> > with fandom values in ns->*.
> >
> 
> I don't see the codepath that leads to calling free_cgroup_ns() with
> uninitialized members. We don't call free_cgroup_ns() on the error
> path in copy_cgroup_ns().

Hm, yeah, I'm not seeing it now, sorry.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCHv1 5/8] cgroup: introduce cgroup namespaces

2014-10-24 Thread Serge E. Hallyn
Quoting Aditya Kali (adityak...@google.com):
  +void free_cgroup_ns(struct cgroup_namespace *ns)
  +{
  + cgroup_put(ns-root_cgrp);
  + put_user_ns(ns-user_ns);
 
  This is a problem on error patch in copy_cgroup_ns.  The
  alloc_cgroup_ns() doesn't initialize these values, so if
  you should fail in proc_alloc_inum() you'll show up here
  with fandom values in ns-*.
 
 
 I don't see the codepath that leads to calling free_cgroup_ns() with
 uninitialized members. We don't call free_cgroup_ns() on the error
 path in copy_cgroup_ns().

Hm, yeah, I'm not seeing it now, sorry.
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCHv1 5/8] cgroup: introduce cgroup namespaces

2014-10-23 Thread Aditya Kali
I will include the suggested changes in the new patchset. Some comments inline.

On Thu, Oct 16, 2014 at 9:37 AM, Serge E. Hallyn  wrote:
> Quoting Aditya Kali (adityak...@google.com):
>> Introduce the ability to create new cgroup namespace. The newly created
>> cgroup namespace remembers the 'struct cgroup *root_cgrp' at the point
>> of creation of the cgroup namespace. The task that creates the new
>> cgroup namespace and all its future children will now be restricted only
>> to the cgroup hierarchy under this root_cgrp.
>> The main purpose of cgroup namespace is to virtualize the contents
>> of /proc/self/cgroup file. Processes inside a cgroup namespace
>> are only able to see paths relative to their namespace root.
>> This allows container-tools (like libcontainer, lxc, lmctfy, etc.)
>> to create completely virtualized containers without leaking system
>> level cgroup hierarchy to the task.
>> This patch only implements the 'unshare' part of the cgroupns.
>>
>> Signed-off-by: Aditya Kali 
>
> I'm not sure that the CONFIG_CGROUP_NS is worthwhile.  If you already
> have cgroups in the kernel this won't add much in the way of memory
> usage, right?  And I think the 'experimental' argument has long since
> been squashed.  So I'd argue for simplifying this patch by removing
> CONFIG_CGROUP_NS.
>

With no pinning involved, I think its safe to enable the feature
without needing a config option. Removed it from next version. This
feature is now implicitly available with CONFIG_CGROUPS.

> (more below)
>
>> ---
>>  fs/proc/namespaces.c |   3 +
>>  include/linux/cgroup.h   |  18 +-
>>  include/linux/cgroup_namespace.h |  62 +++
>>  include/linux/nsproxy.h  |   2 +
>>  include/linux/proc_ns.h  |   4 ++
>>  init/Kconfig |   9 +++
>>  kernel/Makefile  |   1 +
>>  kernel/cgroup.c  |  11 
>>  kernel/cgroup_namespace.c| 128 
>> +++
>>  kernel/fork.c|   2 +-
>>  kernel/nsproxy.c |  19 +-
>>  11 files changed, 255 insertions(+), 4 deletions(-)
>>
>> diff --git a/fs/proc/namespaces.c b/fs/proc/namespaces.c
>> index 8902609..e04ed4b 100644
>> --- a/fs/proc/namespaces.c
>> +++ b/fs/proc/namespaces.c
>> @@ -32,6 +32,9 @@ static const struct proc_ns_operations *ns_entries[] = {
>>   _operations,
>>  #endif
>>   _operations,
>> +#ifdef CONFIG_CGROUP_NS
>> + _operations,
>> +#endif
>>  };
>>
>>  static const struct file_operations ns_file_operations = {
>> diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
>> index 4a0eb2d..aa86495 100644
>> --- a/include/linux/cgroup.h
>> +++ b/include/linux/cgroup.h
>> @@ -22,6 +22,8 @@
>>  #include 
>>  #include 
>>  #include 
>> +#include 
>> +#include 
>>
>>  #ifdef CONFIG_CGROUPS
>>
>> @@ -460,6 +462,13 @@ struct cftype {
>>  #endif
>>  };
>>
>> +struct cgroup_namespace {
>> + atomic_tcount;
>> + unsigned intproc_inum;
>> + struct user_namespace   *user_ns;
>> + struct cgroup   *root_cgrp;
>> +};
>> +
>>  extern struct cgroup_root cgrp_dfl_root;
>>  extern struct css_set init_css_set;
>>
>> @@ -584,10 +593,17 @@ static inline int cgroup_name(struct cgroup *cgrp, 
>> char *buf, size_t buflen)
>>   return kernfs_name(cgrp->kn, buf, buflen);
>>  }
>>
>> +static inline char * __must_check cgroup_path_ns(struct cgroup_namespace 
>> *ns,
>> +  struct cgroup *cgrp, char 
>> *buf,
>> +  size_t buflen)
>> +{
>> + return kernfs_path_from_node(ns->root_cgrp->kn, cgrp->kn, buf, buflen);
>> +}
>> +
>>  static inline char * __must_check cgroup_path(struct cgroup *cgrp, char 
>> *buf,
>> size_t buflen)
>>  {
>> - return kernfs_path(cgrp->kn, buf, buflen);
>> + return cgroup_path_ns(current->nsproxy->cgroup_ns, cgrp, buf, buflen);
>>  }
>>
>>  static inline void pr_cont_cgroup_name(struct cgroup *cgrp)
>> diff --git a/include/linux/cgroup_namespace.h 
>> b/include/linux/cgroup_namespace.h
>> new file mode 100644
>> index 000..9f637fe
>> --- /dev/null
>> +++ b/include/linux/cgroup_namespace.h
>> @@ -0,0 +1,62 @@
>> +#ifndef _LINUX_CGROUP_NAMESPACE_H
>> +#define _LINUX_CGROUP_NAMESPACE_H
>> +
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +
>> +extern struct cgroup_namespace init_cgroup_ns;
>> +
>> +static inline struct cgroup *task_cgroupns_root(struct task_struct *tsk)
>> +{
>> + return tsk->nsproxy->cgroup_ns->root_cgrp;
>
> Per the rules in nsproxy.h, you should be taking the task_lock here.
>
> (If you are making assumptions about tsk then you need to state them
> here - I only looked quickly enough that you pass in 'leader')
>

In the new version of the patch, we call this function only for the
'current' task. As per nsproxy.h, no special precautions needed when

Re: [PATCHv1 5/8] cgroup: introduce cgroup namespaces

2014-10-23 Thread Aditya Kali
I will include the suggested changes in the new patchset. Some comments inline.

On Thu, Oct 16, 2014 at 9:37 AM, Serge E. Hallyn se...@hallyn.com wrote:
 Quoting Aditya Kali (adityak...@google.com):
 Introduce the ability to create new cgroup namespace. The newly created
 cgroup namespace remembers the 'struct cgroup *root_cgrp' at the point
 of creation of the cgroup namespace. The task that creates the new
 cgroup namespace and all its future children will now be restricted only
 to the cgroup hierarchy under this root_cgrp.
 The main purpose of cgroup namespace is to virtualize the contents
 of /proc/self/cgroup file. Processes inside a cgroup namespace
 are only able to see paths relative to their namespace root.
 This allows container-tools (like libcontainer, lxc, lmctfy, etc.)
 to create completely virtualized containers without leaking system
 level cgroup hierarchy to the task.
 This patch only implements the 'unshare' part of the cgroupns.

 Signed-off-by: Aditya Kali adityak...@google.com

 I'm not sure that the CONFIG_CGROUP_NS is worthwhile.  If you already
 have cgroups in the kernel this won't add much in the way of memory
 usage, right?  And I think the 'experimental' argument has long since
 been squashed.  So I'd argue for simplifying this patch by removing
 CONFIG_CGROUP_NS.


With no pinning involved, I think its safe to enable the feature
without needing a config option. Removed it from next version. This
feature is now implicitly available with CONFIG_CGROUPS.

 (more below)

 ---
  fs/proc/namespaces.c |   3 +
  include/linux/cgroup.h   |  18 +-
  include/linux/cgroup_namespace.h |  62 +++
  include/linux/nsproxy.h  |   2 +
  include/linux/proc_ns.h  |   4 ++
  init/Kconfig |   9 +++
  kernel/Makefile  |   1 +
  kernel/cgroup.c  |  11 
  kernel/cgroup_namespace.c| 128 
 +++
  kernel/fork.c|   2 +-
  kernel/nsproxy.c |  19 +-
  11 files changed, 255 insertions(+), 4 deletions(-)

 diff --git a/fs/proc/namespaces.c b/fs/proc/namespaces.c
 index 8902609..e04ed4b 100644
 --- a/fs/proc/namespaces.c
 +++ b/fs/proc/namespaces.c
 @@ -32,6 +32,9 @@ static const struct proc_ns_operations *ns_entries[] = {
   userns_operations,
  #endif
   mntns_operations,
 +#ifdef CONFIG_CGROUP_NS
 + cgroupns_operations,
 +#endif
  };

  static const struct file_operations ns_file_operations = {
 diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
 index 4a0eb2d..aa86495 100644
 --- a/include/linux/cgroup.h
 +++ b/include/linux/cgroup.h
 @@ -22,6 +22,8 @@
  #include linux/seq_file.h
  #include linux/kernfs.h
  #include linux/wait.h
 +#include linux/nsproxy.h
 +#include linux/types.h

  #ifdef CONFIG_CGROUPS

 @@ -460,6 +462,13 @@ struct cftype {
  #endif
  };

 +struct cgroup_namespace {
 + atomic_tcount;
 + unsigned intproc_inum;
 + struct user_namespace   *user_ns;
 + struct cgroup   *root_cgrp;
 +};
 +
  extern struct cgroup_root cgrp_dfl_root;
  extern struct css_set init_css_set;

 @@ -584,10 +593,17 @@ static inline int cgroup_name(struct cgroup *cgrp, 
 char *buf, size_t buflen)
   return kernfs_name(cgrp-kn, buf, buflen);
  }

 +static inline char * __must_check cgroup_path_ns(struct cgroup_namespace 
 *ns,
 +  struct cgroup *cgrp, char 
 *buf,
 +  size_t buflen)
 +{
 + return kernfs_path_from_node(ns-root_cgrp-kn, cgrp-kn, buf, buflen);
 +}
 +
  static inline char * __must_check cgroup_path(struct cgroup *cgrp, char 
 *buf,
 size_t buflen)
  {
 - return kernfs_path(cgrp-kn, buf, buflen);
 + return cgroup_path_ns(current-nsproxy-cgroup_ns, cgrp, buf, buflen);
  }

  static inline void pr_cont_cgroup_name(struct cgroup *cgrp)
 diff --git a/include/linux/cgroup_namespace.h 
 b/include/linux/cgroup_namespace.h
 new file mode 100644
 index 000..9f637fe
 --- /dev/null
 +++ b/include/linux/cgroup_namespace.h
 @@ -0,0 +1,62 @@
 +#ifndef _LINUX_CGROUP_NAMESPACE_H
 +#define _LINUX_CGROUP_NAMESPACE_H
 +
 +#include linux/nsproxy.h
 +#include linux/cgroup.h
 +#include linux/types.h
 +#include linux/user_namespace.h
 +
 +extern struct cgroup_namespace init_cgroup_ns;
 +
 +static inline struct cgroup *task_cgroupns_root(struct task_struct *tsk)
 +{
 + return tsk-nsproxy-cgroup_ns-root_cgrp;

 Per the rules in nsproxy.h, you should be taking the task_lock here.

 (If you are making assumptions about tsk then you need to state them
 here - I only looked quickly enough that you pass in 'leader')


In the new version of the patch, we call this function only for the
'current' task. As per nsproxy.h, no special precautions needed when
reading current task's nsproxy. So I just remodeled this function 

Re: [PATCHv1 5/8] cgroup: introduce cgroup namespaces

2014-10-16 Thread Serge E. Hallyn
Quoting Aditya Kali (adityak...@google.com):
> Introduce the ability to create new cgroup namespace. The newly created
> cgroup namespace remembers the 'struct cgroup *root_cgrp' at the point
> of creation of the cgroup namespace. The task that creates the new
> cgroup namespace and all its future children will now be restricted only
> to the cgroup hierarchy under this root_cgrp.
> The main purpose of cgroup namespace is to virtualize the contents
> of /proc/self/cgroup file. Processes inside a cgroup namespace
> are only able to see paths relative to their namespace root.
> This allows container-tools (like libcontainer, lxc, lmctfy, etc.)
> to create completely virtualized containers without leaking system
> level cgroup hierarchy to the task.
> This patch only implements the 'unshare' part of the cgroupns.
> 
> Signed-off-by: Aditya Kali 

I'm not sure that the CONFIG_CGROUP_NS is worthwhile.  If you already
have cgroups in the kernel this won't add much in the way of memory
usage, right?  And I think the 'experimental' argument has long since
been squashed.  So I'd argue for simplifying this patch by removing
CONFIG_CGROUP_NS.

(more below)

> ---
>  fs/proc/namespaces.c |   3 +
>  include/linux/cgroup.h   |  18 +-
>  include/linux/cgroup_namespace.h |  62 +++
>  include/linux/nsproxy.h  |   2 +
>  include/linux/proc_ns.h  |   4 ++
>  init/Kconfig |   9 +++
>  kernel/Makefile  |   1 +
>  kernel/cgroup.c  |  11 
>  kernel/cgroup_namespace.c| 128 
> +++
>  kernel/fork.c|   2 +-
>  kernel/nsproxy.c |  19 +-
>  11 files changed, 255 insertions(+), 4 deletions(-)
> 
> diff --git a/fs/proc/namespaces.c b/fs/proc/namespaces.c
> index 8902609..e04ed4b 100644
> --- a/fs/proc/namespaces.c
> +++ b/fs/proc/namespaces.c
> @@ -32,6 +32,9 @@ static const struct proc_ns_operations *ns_entries[] = {
>   _operations,
>  #endif
>   _operations,
> +#ifdef CONFIG_CGROUP_NS
> + _operations,
> +#endif
>  };
>  
>  static const struct file_operations ns_file_operations = {
> diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
> index 4a0eb2d..aa86495 100644
> --- a/include/linux/cgroup.h
> +++ b/include/linux/cgroup.h
> @@ -22,6 +22,8 @@
>  #include 
>  #include 
>  #include 
> +#include 
> +#include 
>  
>  #ifdef CONFIG_CGROUPS
>  
> @@ -460,6 +462,13 @@ struct cftype {
>  #endif
>  };
>  
> +struct cgroup_namespace {
> + atomic_tcount;
> + unsigned intproc_inum;
> + struct user_namespace   *user_ns;
> + struct cgroup   *root_cgrp;
> +};
> +
>  extern struct cgroup_root cgrp_dfl_root;
>  extern struct css_set init_css_set;
>  
> @@ -584,10 +593,17 @@ static inline int cgroup_name(struct cgroup *cgrp, char 
> *buf, size_t buflen)
>   return kernfs_name(cgrp->kn, buf, buflen);
>  }
>  
> +static inline char * __must_check cgroup_path_ns(struct cgroup_namespace *ns,
> +  struct cgroup *cgrp, char *buf,
> +  size_t buflen)
> +{
> + return kernfs_path_from_node(ns->root_cgrp->kn, cgrp->kn, buf, buflen);
> +}
> +
>  static inline char * __must_check cgroup_path(struct cgroup *cgrp, char *buf,
> size_t buflen)
>  {
> - return kernfs_path(cgrp->kn, buf, buflen);
> + return cgroup_path_ns(current->nsproxy->cgroup_ns, cgrp, buf, buflen);
>  }
>  
>  static inline void pr_cont_cgroup_name(struct cgroup *cgrp)
> diff --git a/include/linux/cgroup_namespace.h 
> b/include/linux/cgroup_namespace.h
> new file mode 100644
> index 000..9f637fe
> --- /dev/null
> +++ b/include/linux/cgroup_namespace.h
> @@ -0,0 +1,62 @@
> +#ifndef _LINUX_CGROUP_NAMESPACE_H
> +#define _LINUX_CGROUP_NAMESPACE_H
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +extern struct cgroup_namespace init_cgroup_ns;
> +
> +static inline struct cgroup *task_cgroupns_root(struct task_struct *tsk)
> +{
> + return tsk->nsproxy->cgroup_ns->root_cgrp;

Per the rules in nsproxy.h, you should be taking the task_lock here.

(If you are making assumptions about tsk then you need to state them
here - I only looked quickly enough that you pass in 'leader')

> +}
> +
> +#ifdef CONFIG_CGROUP_NS
> +
> +extern void free_cgroup_ns(struct cgroup_namespace *ns);
> +
> +static inline struct cgroup_namespace *get_cgroup_ns(
> + struct cgroup_namespace *ns)
> +{
> + if (ns)
> + atomic_inc(>count);
> + return ns;
> +}
> +
> +static inline void put_cgroup_ns(struct cgroup_namespace *ns)
> +{
> + if (ns && atomic_dec_and_test(>count))
> + free_cgroup_ns(ns);
> +}
> +
> +extern struct cgroup_namespace *copy_cgroup_ns(unsigned long flags,
> +struct user_namespace *user_ns,
> + 

Re: [PATCHv1 5/8] cgroup: introduce cgroup namespaces

2014-10-16 Thread Serge E. Hallyn
Quoting Aditya Kali (adityak...@google.com):
 Introduce the ability to create new cgroup namespace. The newly created
 cgroup namespace remembers the 'struct cgroup *root_cgrp' at the point
 of creation of the cgroup namespace. The task that creates the new
 cgroup namespace and all its future children will now be restricted only
 to the cgroup hierarchy under this root_cgrp.
 The main purpose of cgroup namespace is to virtualize the contents
 of /proc/self/cgroup file. Processes inside a cgroup namespace
 are only able to see paths relative to their namespace root.
 This allows container-tools (like libcontainer, lxc, lmctfy, etc.)
 to create completely virtualized containers without leaking system
 level cgroup hierarchy to the task.
 This patch only implements the 'unshare' part of the cgroupns.
 
 Signed-off-by: Aditya Kali adityak...@google.com

I'm not sure that the CONFIG_CGROUP_NS is worthwhile.  If you already
have cgroups in the kernel this won't add much in the way of memory
usage, right?  And I think the 'experimental' argument has long since
been squashed.  So I'd argue for simplifying this patch by removing
CONFIG_CGROUP_NS.

(more below)

 ---
  fs/proc/namespaces.c |   3 +
  include/linux/cgroup.h   |  18 +-
  include/linux/cgroup_namespace.h |  62 +++
  include/linux/nsproxy.h  |   2 +
  include/linux/proc_ns.h  |   4 ++
  init/Kconfig |   9 +++
  kernel/Makefile  |   1 +
  kernel/cgroup.c  |  11 
  kernel/cgroup_namespace.c| 128 
 +++
  kernel/fork.c|   2 +-
  kernel/nsproxy.c |  19 +-
  11 files changed, 255 insertions(+), 4 deletions(-)
 
 diff --git a/fs/proc/namespaces.c b/fs/proc/namespaces.c
 index 8902609..e04ed4b 100644
 --- a/fs/proc/namespaces.c
 +++ b/fs/proc/namespaces.c
 @@ -32,6 +32,9 @@ static const struct proc_ns_operations *ns_entries[] = {
   userns_operations,
  #endif
   mntns_operations,
 +#ifdef CONFIG_CGROUP_NS
 + cgroupns_operations,
 +#endif
  };
  
  static const struct file_operations ns_file_operations = {
 diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
 index 4a0eb2d..aa86495 100644
 --- a/include/linux/cgroup.h
 +++ b/include/linux/cgroup.h
 @@ -22,6 +22,8 @@
  #include linux/seq_file.h
  #include linux/kernfs.h
  #include linux/wait.h
 +#include linux/nsproxy.h
 +#include linux/types.h
  
  #ifdef CONFIG_CGROUPS
  
 @@ -460,6 +462,13 @@ struct cftype {
  #endif
  };
  
 +struct cgroup_namespace {
 + atomic_tcount;
 + unsigned intproc_inum;
 + struct user_namespace   *user_ns;
 + struct cgroup   *root_cgrp;
 +};
 +
  extern struct cgroup_root cgrp_dfl_root;
  extern struct css_set init_css_set;
  
 @@ -584,10 +593,17 @@ static inline int cgroup_name(struct cgroup *cgrp, char 
 *buf, size_t buflen)
   return kernfs_name(cgrp-kn, buf, buflen);
  }
  
 +static inline char * __must_check cgroup_path_ns(struct cgroup_namespace *ns,
 +  struct cgroup *cgrp, char *buf,
 +  size_t buflen)
 +{
 + return kernfs_path_from_node(ns-root_cgrp-kn, cgrp-kn, buf, buflen);
 +}
 +
  static inline char * __must_check cgroup_path(struct cgroup *cgrp, char *buf,
 size_t buflen)
  {
 - return kernfs_path(cgrp-kn, buf, buflen);
 + return cgroup_path_ns(current-nsproxy-cgroup_ns, cgrp, buf, buflen);
  }
  
  static inline void pr_cont_cgroup_name(struct cgroup *cgrp)
 diff --git a/include/linux/cgroup_namespace.h 
 b/include/linux/cgroup_namespace.h
 new file mode 100644
 index 000..9f637fe
 --- /dev/null
 +++ b/include/linux/cgroup_namespace.h
 @@ -0,0 +1,62 @@
 +#ifndef _LINUX_CGROUP_NAMESPACE_H
 +#define _LINUX_CGROUP_NAMESPACE_H
 +
 +#include linux/nsproxy.h
 +#include linux/cgroup.h
 +#include linux/types.h
 +#include linux/user_namespace.h
 +
 +extern struct cgroup_namespace init_cgroup_ns;
 +
 +static inline struct cgroup *task_cgroupns_root(struct task_struct *tsk)
 +{
 + return tsk-nsproxy-cgroup_ns-root_cgrp;

Per the rules in nsproxy.h, you should be taking the task_lock here.

(If you are making assumptions about tsk then you need to state them
here - I only looked quickly enough that you pass in 'leader')

 +}
 +
 +#ifdef CONFIG_CGROUP_NS
 +
 +extern void free_cgroup_ns(struct cgroup_namespace *ns);
 +
 +static inline struct cgroup_namespace *get_cgroup_ns(
 + struct cgroup_namespace *ns)
 +{
 + if (ns)
 + atomic_inc(ns-count);
 + return ns;
 +}
 +
 +static inline void put_cgroup_ns(struct cgroup_namespace *ns)
 +{
 + if (ns  atomic_dec_and_test(ns-count))
 + free_cgroup_ns(ns);
 +}
 +
 +extern struct cgroup_namespace *copy_cgroup_ns(unsigned long flags,
 +

[PATCHv1 5/8] cgroup: introduce cgroup namespaces

2014-10-13 Thread Aditya Kali
Introduce the ability to create new cgroup namespace. The newly created
cgroup namespace remembers the 'struct cgroup *root_cgrp' at the point
of creation of the cgroup namespace. The task that creates the new
cgroup namespace and all its future children will now be restricted only
to the cgroup hierarchy under this root_cgrp.
The main purpose of cgroup namespace is to virtualize the contents
of /proc/self/cgroup file. Processes inside a cgroup namespace
are only able to see paths relative to their namespace root.
This allows container-tools (like libcontainer, lxc, lmctfy, etc.)
to create completely virtualized containers without leaking system
level cgroup hierarchy to the task.
This patch only implements the 'unshare' part of the cgroupns.

Signed-off-by: Aditya Kali 
---
 fs/proc/namespaces.c |   3 +
 include/linux/cgroup.h   |  18 +-
 include/linux/cgroup_namespace.h |  62 +++
 include/linux/nsproxy.h  |   2 +
 include/linux/proc_ns.h  |   4 ++
 init/Kconfig |   9 +++
 kernel/Makefile  |   1 +
 kernel/cgroup.c  |  11 
 kernel/cgroup_namespace.c| 128 +++
 kernel/fork.c|   2 +-
 kernel/nsproxy.c |  19 +-
 11 files changed, 255 insertions(+), 4 deletions(-)

diff --git a/fs/proc/namespaces.c b/fs/proc/namespaces.c
index 8902609..e04ed4b 100644
--- a/fs/proc/namespaces.c
+++ b/fs/proc/namespaces.c
@@ -32,6 +32,9 @@ static const struct proc_ns_operations *ns_entries[] = {
_operations,
 #endif
_operations,
+#ifdef CONFIG_CGROUP_NS
+   _operations,
+#endif
 };
 
 static const struct file_operations ns_file_operations = {
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index 4a0eb2d..aa86495 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -22,6 +22,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 
 #ifdef CONFIG_CGROUPS
 
@@ -460,6 +462,13 @@ struct cftype {
 #endif
 };
 
+struct cgroup_namespace {
+   atomic_tcount;
+   unsigned intproc_inum;
+   struct user_namespace   *user_ns;
+   struct cgroup   *root_cgrp;
+};
+
 extern struct cgroup_root cgrp_dfl_root;
 extern struct css_set init_css_set;
 
@@ -584,10 +593,17 @@ static inline int cgroup_name(struct cgroup *cgrp, char 
*buf, size_t buflen)
return kernfs_name(cgrp->kn, buf, buflen);
 }
 
+static inline char * __must_check cgroup_path_ns(struct cgroup_namespace *ns,
+struct cgroup *cgrp, char *buf,
+size_t buflen)
+{
+   return kernfs_path_from_node(ns->root_cgrp->kn, cgrp->kn, buf, buflen);
+}
+
 static inline char * __must_check cgroup_path(struct cgroup *cgrp, char *buf,
  size_t buflen)
 {
-   return kernfs_path(cgrp->kn, buf, buflen);
+   return cgroup_path_ns(current->nsproxy->cgroup_ns, cgrp, buf, buflen);
 }
 
 static inline void pr_cont_cgroup_name(struct cgroup *cgrp)
diff --git a/include/linux/cgroup_namespace.h b/include/linux/cgroup_namespace.h
new file mode 100644
index 000..9f637fe
--- /dev/null
+++ b/include/linux/cgroup_namespace.h
@@ -0,0 +1,62 @@
+#ifndef _LINUX_CGROUP_NAMESPACE_H
+#define _LINUX_CGROUP_NAMESPACE_H
+
+#include 
+#include 
+#include 
+#include 
+
+extern struct cgroup_namespace init_cgroup_ns;
+
+static inline struct cgroup *task_cgroupns_root(struct task_struct *tsk)
+{
+   return tsk->nsproxy->cgroup_ns->root_cgrp;
+}
+
+#ifdef CONFIG_CGROUP_NS
+
+extern void free_cgroup_ns(struct cgroup_namespace *ns);
+
+static inline struct cgroup_namespace *get_cgroup_ns(
+   struct cgroup_namespace *ns)
+{
+   if (ns)
+   atomic_inc(>count);
+   return ns;
+}
+
+static inline void put_cgroup_ns(struct cgroup_namespace *ns)
+{
+   if (ns && atomic_dec_and_test(>count))
+   free_cgroup_ns(ns);
+}
+
+extern struct cgroup_namespace *copy_cgroup_ns(unsigned long flags,
+  struct user_namespace *user_ns,
+  struct cgroup_namespace *old_ns);
+
+#else  /* CONFIG_CGROUP_NS */
+
+static inline struct cgroup_namespace *get_cgroup_ns(
+   struct cgroup_namespace *ns)
+{
+   return _cgroup_ns;
+}
+
+static inline void put_cgroup_ns(struct cgroup_namespace *ns)
+{
+}
+
+static inline struct cgroup_namespace *copy_cgroup_ns(
+   unsigned long flags,
+   struct user_namespace *user_ns,
+   struct cgroup_namespace *old_ns) {
+   if (flags & CLONE_NEWCGROUP)
+   return ERR_PTR(-EINVAL);
+
+   return old_ns;
+}
+
+#endif  /* CONFIG_CGROUP_NS */
+
+#endif  /* _LINUX_CGROUP_NAMESPACE_H */
diff --git a/include/linux/nsproxy.h b/include/linux/nsproxy.h
index 35fa08f..ac0d65b 

[PATCHv1 5/8] cgroup: introduce cgroup namespaces

2014-10-13 Thread Aditya Kali
Introduce the ability to create new cgroup namespace. The newly created
cgroup namespace remembers the 'struct cgroup *root_cgrp' at the point
of creation of the cgroup namespace. The task that creates the new
cgroup namespace and all its future children will now be restricted only
to the cgroup hierarchy under this root_cgrp.
The main purpose of cgroup namespace is to virtualize the contents
of /proc/self/cgroup file. Processes inside a cgroup namespace
are only able to see paths relative to their namespace root.
This allows container-tools (like libcontainer, lxc, lmctfy, etc.)
to create completely virtualized containers without leaking system
level cgroup hierarchy to the task.
This patch only implements the 'unshare' part of the cgroupns.

Signed-off-by: Aditya Kali adityak...@google.com
---
 fs/proc/namespaces.c |   3 +
 include/linux/cgroup.h   |  18 +-
 include/linux/cgroup_namespace.h |  62 +++
 include/linux/nsproxy.h  |   2 +
 include/linux/proc_ns.h  |   4 ++
 init/Kconfig |   9 +++
 kernel/Makefile  |   1 +
 kernel/cgroup.c  |  11 
 kernel/cgroup_namespace.c| 128 +++
 kernel/fork.c|   2 +-
 kernel/nsproxy.c |  19 +-
 11 files changed, 255 insertions(+), 4 deletions(-)

diff --git a/fs/proc/namespaces.c b/fs/proc/namespaces.c
index 8902609..e04ed4b 100644
--- a/fs/proc/namespaces.c
+++ b/fs/proc/namespaces.c
@@ -32,6 +32,9 @@ static const struct proc_ns_operations *ns_entries[] = {
userns_operations,
 #endif
mntns_operations,
+#ifdef CONFIG_CGROUP_NS
+   cgroupns_operations,
+#endif
 };
 
 static const struct file_operations ns_file_operations = {
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index 4a0eb2d..aa86495 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -22,6 +22,8 @@
 #include linux/seq_file.h
 #include linux/kernfs.h
 #include linux/wait.h
+#include linux/nsproxy.h
+#include linux/types.h
 
 #ifdef CONFIG_CGROUPS
 
@@ -460,6 +462,13 @@ struct cftype {
 #endif
 };
 
+struct cgroup_namespace {
+   atomic_tcount;
+   unsigned intproc_inum;
+   struct user_namespace   *user_ns;
+   struct cgroup   *root_cgrp;
+};
+
 extern struct cgroup_root cgrp_dfl_root;
 extern struct css_set init_css_set;
 
@@ -584,10 +593,17 @@ static inline int cgroup_name(struct cgroup *cgrp, char 
*buf, size_t buflen)
return kernfs_name(cgrp-kn, buf, buflen);
 }
 
+static inline char * __must_check cgroup_path_ns(struct cgroup_namespace *ns,
+struct cgroup *cgrp, char *buf,
+size_t buflen)
+{
+   return kernfs_path_from_node(ns-root_cgrp-kn, cgrp-kn, buf, buflen);
+}
+
 static inline char * __must_check cgroup_path(struct cgroup *cgrp, char *buf,
  size_t buflen)
 {
-   return kernfs_path(cgrp-kn, buf, buflen);
+   return cgroup_path_ns(current-nsproxy-cgroup_ns, cgrp, buf, buflen);
 }
 
 static inline void pr_cont_cgroup_name(struct cgroup *cgrp)
diff --git a/include/linux/cgroup_namespace.h b/include/linux/cgroup_namespace.h
new file mode 100644
index 000..9f637fe
--- /dev/null
+++ b/include/linux/cgroup_namespace.h
@@ -0,0 +1,62 @@
+#ifndef _LINUX_CGROUP_NAMESPACE_H
+#define _LINUX_CGROUP_NAMESPACE_H
+
+#include linux/nsproxy.h
+#include linux/cgroup.h
+#include linux/types.h
+#include linux/user_namespace.h
+
+extern struct cgroup_namespace init_cgroup_ns;
+
+static inline struct cgroup *task_cgroupns_root(struct task_struct *tsk)
+{
+   return tsk-nsproxy-cgroup_ns-root_cgrp;
+}
+
+#ifdef CONFIG_CGROUP_NS
+
+extern void free_cgroup_ns(struct cgroup_namespace *ns);
+
+static inline struct cgroup_namespace *get_cgroup_ns(
+   struct cgroup_namespace *ns)
+{
+   if (ns)
+   atomic_inc(ns-count);
+   return ns;
+}
+
+static inline void put_cgroup_ns(struct cgroup_namespace *ns)
+{
+   if (ns  atomic_dec_and_test(ns-count))
+   free_cgroup_ns(ns);
+}
+
+extern struct cgroup_namespace *copy_cgroup_ns(unsigned long flags,
+  struct user_namespace *user_ns,
+  struct cgroup_namespace *old_ns);
+
+#else  /* CONFIG_CGROUP_NS */
+
+static inline struct cgroup_namespace *get_cgroup_ns(
+   struct cgroup_namespace *ns)
+{
+   return init_cgroup_ns;
+}
+
+static inline void put_cgroup_ns(struct cgroup_namespace *ns)
+{
+}
+
+static inline struct cgroup_namespace *copy_cgroup_ns(
+   unsigned long flags,
+   struct user_namespace *user_ns,
+   struct cgroup_namespace *old_ns) {
+   if (flags  CLONE_NEWCGROUP)
+   return ERR_PTR(-EINVAL);
+
+   return