[v2,09/57] kerndat: Check that "/proc/[pid]/status" file has NS{pid, ..} lines

Submitted by Kirill Tkhai on March 28, 2017, 3:35 p.m.

Details

Message ID 149071533277.12770.13517903519635204087.stgit@localhost.localdomain
State New
Series "Nested pid namespaces support"
Headers show

Commit Message

Kirill Tkhai March 28, 2017, 3:35 p.m.
If there is nested pid_ns, we need to be able to get pid in
the whole pid hierarhy. This may be taken from "/proc/[pid]/status"
file only. Check, that kernel has support for it.

Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
---
 criu/include/kerndat.h |    1 +
 criu/kerndat.c         |   28 ++++++++++++++++++++++++++++
 criu/namespaces.c      |    5 +++++
 3 files changed, 34 insertions(+)

Patch hide | download patch | download mbox

diff --git a/criu/include/kerndat.h b/criu/include/kerndat.h
index 60c69c3e..2e8c3309 100644
--- a/criu/include/kerndat.h
+++ b/criu/include/kerndat.h
@@ -43,6 +43,7 @@  struct kerndat_s {
 	unsigned long uffd_features;
 	bool has_nsid;
 	bool has_link_nsid;
+	bool has_nspid;
 };
 
 extern struct kerndat_s kdat;
diff --git a/criu/kerndat.c b/criu/kerndat.c
index 354c2a5f..df388c56 100644
--- a/criu/kerndat.c
+++ b/criu/kerndat.c
@@ -630,6 +630,32 @@  int kerndat_uffd(bool need_uffd)
 	return 0;
 }
 
+int kerndat_has_nspid(void)
+{
+	struct bfd f;
+	int ret = -1;
+	char *str;
+
+	f.fd = open("/proc/self/status", O_RDONLY);
+	if (f.fd < 0) {
+		pr_perror("Can't open /proc/self/status");
+		return -1;
+	}
+	if (bfdopenr(&f))
+		return -1;
+	while ((str = breadline(&f)) != NULL) {
+		if (IS_ERR(str))
+			goto close;
+		if (!strncmp(str, "NSpid:", 6)) {
+			kdat.has_nspid = true;
+			break;
+		}
+	}
+	ret = 0;
+close:
+	bclose(&f);
+	return ret;
+}
 int kerndat_init(void)
 {
 	int ret;
@@ -661,6 +687,8 @@  int kerndat_init(void)
 		ret = kerndat_socket_netns();
 	if (!ret)
 		ret = kerndat_nsid();
+	if (!ret)
+		ret = kerndat_has_nspid();
 
 	kerndat_lsm();
 	kerndat_mmap_min_addr();
diff --git a/criu/namespaces.c b/criu/namespaces.c
index 4ecd6e36..1dab7656 100644
--- a/criu/namespaces.c
+++ b/criu/namespaces.c
@@ -26,6 +26,7 @@ 
 #include "namespaces.h"
 #include "net.h"
 #include "cgroup.h"
+#include "kerndat.h"
 
 #include "protobuf.h"
 #include "util.h"
@@ -792,6 +793,10 @@  static int set_ns_hookups(struct ns_id *ns)
 			pr_err("Wrong determined NS_ROOT, or root_item has NS_OTHER user_ns\n");
 			goto out;
 		}
+		if (nd == &pid_ns_desc && !kdat.has_nspid) {
+			pr_err("Can't dump nested pid ns\n");
+			goto out;
+		}
 		list_add(&ns->siblings, &ns->parent->children);
 	}
 

Comments

Andrey Vagin April 7, 2017, 12:21 a.m.
On Tue, Mar 28, 2017 at 06:35:32PM +0300, Kirill Tkhai wrote:
> If there is nested pid_ns, we need to be able to get pid in
> the whole pid hierarhy. This may be taken from "/proc/[pid]/status"
> file only. Check, that kernel has support for it.

Do we need to add a proper feature check

criu check --feature nspid



> 
> Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
> ---
>  criu/include/kerndat.h |    1 +
>  criu/kerndat.c         |   28 ++++++++++++++++++++++++++++
>  criu/namespaces.c      |    5 +++++
>  3 files changed, 34 insertions(+)
> 
> diff --git a/criu/include/kerndat.h b/criu/include/kerndat.h
> index 60c69c3e..2e8c3309 100644
> --- a/criu/include/kerndat.h
> +++ b/criu/include/kerndat.h
> @@ -43,6 +43,7 @@ struct kerndat_s {
>  	unsigned long uffd_features;
>  	bool has_nsid;
>  	bool has_link_nsid;
> +	bool has_nspid;
>  };
>  
>  extern struct kerndat_s kdat;
> diff --git a/criu/kerndat.c b/criu/kerndat.c
> index 354c2a5f..df388c56 100644
> --- a/criu/kerndat.c
> +++ b/criu/kerndat.c
> @@ -630,6 +630,32 @@ int kerndat_uffd(bool need_uffd)
>  	return 0;
>  }
>  
> +int kerndat_has_nspid(void)
> +{
> +	struct bfd f;
> +	int ret = -1;
> +	char *str;
> +
> +	f.fd = open("/proc/self/status", O_RDONLY);
> +	if (f.fd < 0) {
> +		pr_perror("Can't open /proc/self/status");
> +		return -1;
> +	}
> +	if (bfdopenr(&f))
> +		return -1;
> +	while ((str = breadline(&f)) != NULL) {
> +		if (IS_ERR(str))
> +			goto close;
> +		if (!strncmp(str, "NSpid:", 6)) {
> +			kdat.has_nspid = true;
> +			break;
> +		}
> +	}
> +	ret = 0;
> +close:
> +	bclose(&f);
> +	return ret;
> +}
>  int kerndat_init(void)
>  {
>  	int ret;
> @@ -661,6 +687,8 @@ int kerndat_init(void)
>  		ret = kerndat_socket_netns();
>  	if (!ret)
>  		ret = kerndat_nsid();
> +	if (!ret)
> +		ret = kerndat_has_nspid();
>  
>  	kerndat_lsm();
>  	kerndat_mmap_min_addr();
> diff --git a/criu/namespaces.c b/criu/namespaces.c
> index 4ecd6e36..1dab7656 100644
> --- a/criu/namespaces.c
> +++ b/criu/namespaces.c
> @@ -26,6 +26,7 @@
>  #include "namespaces.h"
>  #include "net.h"
>  #include "cgroup.h"
> +#include "kerndat.h"
>  
>  #include "protobuf.h"
>  #include "util.h"
> @@ -792,6 +793,10 @@ static int set_ns_hookups(struct ns_id *ns)
>  			pr_err("Wrong determined NS_ROOT, or root_item has NS_OTHER user_ns\n");
>  			goto out;
>  		}
> +		if (nd == &pid_ns_desc && !kdat.has_nspid) {
> +			pr_err("Can't dump nested pid ns\n");
> +			goto out;
> +		}
>  		list_add(&ns->siblings, &ns->parent->children);
>  	}
>  
>
Kirill Tkhai April 7, 2017, 9:51 a.m.
On 07.04.2017 03:21, Andrei Vagin wrote:
> On Tue, Mar 28, 2017 at 06:35:32PM +0300, Kirill Tkhai wrote:
>> If there is nested pid_ns, we need to be able to get pid in
>> the whole pid hierarhy. This may be taken from "/proc/[pid]/status"
>> file only. Check, that kernel has support for it.
> 
> Do we need to add a proper feature check
> 
> criu check --feature nspid

Maybe, so let it be

>>
>> Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
>> ---
>>  criu/include/kerndat.h |    1 +
>>  criu/kerndat.c         |   28 ++++++++++++++++++++++++++++
>>  criu/namespaces.c      |    5 +++++
>>  3 files changed, 34 insertions(+)
>>
>> diff --git a/criu/include/kerndat.h b/criu/include/kerndat.h
>> index 60c69c3e..2e8c3309 100644
>> --- a/criu/include/kerndat.h
>> +++ b/criu/include/kerndat.h
>> @@ -43,6 +43,7 @@ struct kerndat_s {
>>  	unsigned long uffd_features;
>>  	bool has_nsid;
>>  	bool has_link_nsid;
>> +	bool has_nspid;
>>  };
>>  
>>  extern struct kerndat_s kdat;
>> diff --git a/criu/kerndat.c b/criu/kerndat.c
>> index 354c2a5f..df388c56 100644
>> --- a/criu/kerndat.c
>> +++ b/criu/kerndat.c
>> @@ -630,6 +630,32 @@ int kerndat_uffd(bool need_uffd)
>>  	return 0;
>>  }
>>  
>> +int kerndat_has_nspid(void)
>> +{
>> +	struct bfd f;
>> +	int ret = -1;
>> +	char *str;
>> +
>> +	f.fd = open("/proc/self/status", O_RDONLY);
>> +	if (f.fd < 0) {
>> +		pr_perror("Can't open /proc/self/status");
>> +		return -1;
>> +	}
>> +	if (bfdopenr(&f))
>> +		return -1;
>> +	while ((str = breadline(&f)) != NULL) {
>> +		if (IS_ERR(str))
>> +			goto close;
>> +		if (!strncmp(str, "NSpid:", 6)) {
>> +			kdat.has_nspid = true;
>> +			break;
>> +		}
>> +	}
>> +	ret = 0;
>> +close:
>> +	bclose(&f);
>> +	return ret;
>> +}
>>  int kerndat_init(void)
>>  {
>>  	int ret;
>> @@ -661,6 +687,8 @@ int kerndat_init(void)
>>  		ret = kerndat_socket_netns();
>>  	if (!ret)
>>  		ret = kerndat_nsid();
>> +	if (!ret)
>> +		ret = kerndat_has_nspid();
>>  
>>  	kerndat_lsm();
>>  	kerndat_mmap_min_addr();
>> diff --git a/criu/namespaces.c b/criu/namespaces.c
>> index 4ecd6e36..1dab7656 100644
>> --- a/criu/namespaces.c
>> +++ b/criu/namespaces.c
>> @@ -26,6 +26,7 @@
>>  #include "namespaces.h"
>>  #include "net.h"
>>  #include "cgroup.h"
>> +#include "kerndat.h"
>>  
>>  #include "protobuf.h"
>>  #include "util.h"
>> @@ -792,6 +793,10 @@ static int set_ns_hookups(struct ns_id *ns)
>>  			pr_err("Wrong determined NS_ROOT, or root_item has NS_OTHER user_ns\n");
>>  			goto out;
>>  		}
>> +		if (nd == &pid_ns_desc && !kdat.has_nspid) {
>> +			pr_err("Can't dump nested pid ns\n");
>> +			goto out;
>> +		}
>>  		list_add(&ns->siblings, &ns->parent->children);
>>  	}
>>  
>>