On 2015/8/11 21:58, Jan Stancek wrote:
>
> ----- Original Message -----
>> From: "Yuan Sun" <sunyu...@huawei.com>
>> To: "Jan Stancek" <jstan...@redhat.com>
>> Cc: ltp-list@lists.sourceforge.net
>> Sent: Tuesday, 11 August, 2015 10:43:02 AM
>> Subject: Re: [PATCH V2] container: new testcase pidns32
>>
>> Hi Jan,
>>       See in-line comments.
>> On 2015/8/11 16:05, Jan Stancek wrote:
>>> ----- Original Message -----
>>>> From: "Yuan Sun" <sunyu...@huawei.com>
>>>> To: jstan...@redhat.com
>>>> Cc: ltp-list@lists.sourceforge.net
>>>> Sent: Friday, 7 August, 2015 6:55:08 AM
>>>> Subject: [PATCH V2] container: new testcase pidns32
>>>>
>>>> Kernel imposes a limit of 32 nested levels of pid namespaces.
>>>>
>>>> Signed-off-by: Yuan Sun <sunyu...@huawei.com>
>>>> ---
>>>>    runtest/containers                           |  1 +
>>>>    testcases/kernel/containers/pidns/.gitignore |  1 +
>>>>    testcases/kernel/containers/pidns/pidns32.c  | 96
>>>>    ++++++++++++++++++++++++++++
>>>>    3 files changed, 98 insertions(+)
>>>>    create mode 100644 testcases/kernel/containers/pidns/pidns32.c
>>>>
>>>> diff --git a/runtest/containers b/runtest/containers
>>>> index 9dc44bc..ac37ab2 100644
>>>> --- a/runtest/containers
>>>> +++ b/runtest/containers
>>>> @@ -13,6 +13,7 @@ pidns17 pidns17
>>>>    pidns20 pidns20
>>>>    pidns30 pidns30
>>>>    pidns31 pidns31
>>>> +pidns32 pidns32
>>>>    
>>>>    mqns_01 mqns_01
>>>>    mqns_01_clone mqns_01 -clone
>>>> diff --git a/testcases/kernel/containers/pidns/.gitignore
>>>> b/testcases/kernel/containers/pidns/.gitignore
>>>> index e56c1f9..488b045 100644
>>>> --- a/testcases/kernel/containers/pidns/.gitignore
>>>> +++ b/testcases/kernel/containers/pidns/.gitignore
>>>> @@ -12,3 +12,4 @@
>>>>    /pidns20
>>>>    /pidns30
>>>>    /pidns31
>>>> +/pidns32
>>>> diff --git a/testcases/kernel/containers/pidns/pidns32.c
>>>> b/testcases/kernel/containers/pidns/pidns32.c
>>>> new file mode 100644
>>>> index 0000000..d0d3e1e
>>>> --- /dev/null
>>>> +++ b/testcases/kernel/containers/pidns/pidns32.c
>>>> @@ -0,0 +1,96 @@
>>>> +/*
>>>> + * Copyright (c) Huawei Technologies Co., Ltd., 2015
>>>> + * 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; either version 2 of the License, or
>>>> + *  (at your option) any later version.
>>>> + *
>>>> + * This program is distributed in the hope that it will be useful,
>>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
>>>> + * the GNU General Public License for more details.
>>>> + */
>>>> +
>>>> +/*
>>> Hi,
>>>
>>> I'm still not entirely convinced about this test.
>>>
>>>> + * Verify that:
>>>> + * The kernel imposes a limit of 32 nested levels of pid namespaces.
>>> If it doesn't, is that a bad thing? Are there some adverse effects, when
>>> such limitation is lacking?
>> It is a kernel feature.
> My concern is that it's not documented, and can be changed at any time.
> There's no way to learn what that value is, unless you look at source code.
>
> As suggested by Cyril, test could verify that we can create at least 
> MAXNEST-1 pid
> namespaces and stop there. What do you think?
>
> Regards,
> Jan
I understand your concern. Ok. I agree with you.
I will update the code.
Thank you.
     Yuan
>
>> The following information is from
>> http://www.serverphorums.com/read.php?12,580615
>>
>> 'struct pid' is a "variable sized struct" - a header with an array
>> of upids at the end.
>>
>> A size of the array depends on a level (depth) of pid namespaces. Now
>> a level of pidns is not limited, so 'struct pid' can be more than one
>> page.
>>
>> Looks reasonable, that it should be less than a page. MAX_PIS_NS_LEVEL
>> is not calculated from PAGE_SIZE, because in this case it depends on
>> architectures, config options and it will be reduced, if someone adds a
>> new fields in struct pid or struct upid.
>>
>> I suggest to set MAX_PID_NS_LEVEL = 32, because it saves ability to
>> expand "struct pid" and it's more than enough for all known for me
>> use-cases. When someone finds a reasonable use case, we can add a
>> config option or a sysctl parameter.
>>
>> In addition it will reduce effect of another problem, when we have many
>> nested namespaces and the oldest one starts dying. zap_pid_ns_processe
>> will be called for each namespace and find_vpid will be called for each
>> process in a namespace. find_vpid will be called minimum max_level^2 / 2
>> times. The reason of that is that when we found a bit in pidmap, we
>> can't determine this pidns is top for this process or it isn't.
>>
>> vpid is a heavy operation, so a fork bomb, which create many nested
>> namespace, can do a system inaccessible for a long time.
>>>> + */
>>>> +
>>>> +#define _GNU_SOURCE
>>>> +#include <sys/wait.h>
>>>> +#include <assert.h>
>>>> +#include <stdio.h>
>>>> +#include <stdlib.h>
>>>> +#include <unistd.h>
>>>> +#include <string.h>
>>>> +#include <errno.h>
>>>> +#include "test.h"
>>>> +#include "pidns_helper.h"
>>>> +
>>>> +#define MAXNEST 32
>>>> +
>>>> +char *TCID = "pidns32";
>>>> +int TST_TOTAL = 1;
>>>> +
>>>> +static void setup(void)
>>>> +{
>>>> +  if (tst_kvercmp(3, 7, 0) < 0)
>>>> +          tst_brkm(TCONF, NULL, "nest depth limitation not supported");
>>>> +  tst_require_root();
>>>> +  check_newpid();
>>>> +  tst_tmpdir();
>>>> +}
>>>> +
>>>> +static void cleanup(void)
>>>> +{
>>>> +  tst_rmdir();
>>>> +}
>>>> +
>>>> +static int child_fn1(void *arg)
>>>> +{
>>>> +  pid_t cpid1;
>>>> +  long level = (long)arg;
>>>> +
>>>> +  cpid1 = ltp_clone_quick(CLONE_NEWPID | SIGCHLD,
>>>> +          (void *)child_fn1, (void *)(level + 1));
>>> You are relying on fact that clone will fail at MAXNEST levels.
>>> If it doesn't then this keeps making child processes presumably
>>> until you hit OOM.
>>>
>>> First action of new child should be to check current level. If it's
>>> over, test can end there.
>> Yes, you are right. I will update the code.
>>>> +  if (cpid1 < 0) {
>>>> +          if (level == MAXNEST)
>>>> +                  return 0;
>>>> +          return 1;
>>>> +  }
>>>> +  if (waitpid(cpid1, NULL, 0) == -1)
>>>> +          return 1;
>>> If you ignore status in waitpid() call, how do you know that child at
>>> MAXNEXT level failed test condition?
>>    79 /* MAX_PID_NS_LEVEL is needed for limiting size of 'struct pid' */
>>    80 #define MAX_PID_NS_LEVEL 32
>>    81
>>    82 static struct pid_namespace *create_pid_namespace(struct
>> user_namespace *user_ns,
>>    83         struct pid_namespace *parent_pid_ns)
>>    84 {
>>    85         struct pid_namespace *ns;
>>    86         unsigned int level = parent_pid_ns->level + 1;
>>    87         int i;
>>    88         int err;
>>    89
>>    90         if (level > MAX_PID_NS_LEVEL) {
>>    91                 err = -EINVAL;
>>    92                 goto out;
>>    93         }
>> http://lxr.free-electrons.com/source/kernel/pid_namespace.c
>>
>> I need to update the code to judge if the error is EINVAL.
>>> Regards,
>>> Jan
>>>
>>>> +  if (level > MAXNEST) {
>>>> +          printf("MAX_PIS_NS_LEVEL doestn't take effect\n");
>>>> +          return 1;
>>>> +  }
>>>> +  return 0;
>>>> +}
>>>> +
>>>> +static void test_max_nest(void)
>>>> +{
>>>> +  pid_t cpid1;
>>>> +
>>>> +  cpid1 = ltp_clone_quick(CLONE_NEWPID | SIGCHLD,
>>>> +          (void *)child_fn1, (void *)1);
>>>> +  if (cpid1 < 0)
>>>> +          tst_brkm(TBROK | TERRNO, cleanup, "clone failed");
>>>> +
>>>> +  tst_record_childstatus(cleanup, cpid1);
>>>> +}
>>>> +
>>>> +int main(int argc, char *argv[])
>>>> +{
>>>> +  int lc;
>>>> +
>>>> +  setup();
>>>> +  tst_parse_opts(argc, argv, NULL, NULL);
>>>> +
>>>> +  for (lc = 0; TEST_LOOPING(lc); lc++) {
>>>> +          tst_count = 0;
>>>> +          test_max_nest();
>>>> +  }
>>>> +
>>>> +  cleanup();
>>>> +  tst_exit();
>>>> +}
>>>> --
>>>> 1.9.1
>>>>
>>>>
>>> .
>>>
>>
> .
>


------------------------------------------------------------------------------
_______________________________________________
Ltp-list mailing list
Ltp-list@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ltp-list

Reply via email to