From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.9 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id AF3B9C3A59B for ; Thu, 15 Aug 2019 16:39:33 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 7A8292184B for ; Thu, 15 Aug 2019 16:39:33 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=arista.com header.i=@arista.com header.b="Re/ccRVj" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732669AbfHOQjc (ORCPT ); Thu, 15 Aug 2019 12:39:32 -0400 Received: from mail-wr1-f65.google.com ([209.85.221.65]:32903 "EHLO mail-wr1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1732603AbfHOQj2 (ORCPT ); Thu, 15 Aug 2019 12:39:28 -0400 Received: by mail-wr1-f65.google.com with SMTP id u16so2797159wrr.0 for ; Thu, 15 Aug 2019 09:39:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=arista.com; s=googlenew; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=PNJxm2QMtZcp14624QbakT+mhmccQwYHPQgZhw4FCC0=; b=Re/ccRVj6uveaZFzmN7SNBWwJ4tAjTCz8vLPc8plMX10YUl5P5m9FP1ONkuI7LkpPm 1+w6PSOH80umvi+inVFHF1zT0uTEJZFEPF3/MJNEub112F2QziqYo0q9BXrNxfB8L/ma tzANJGEACqjB10xHHus/015CP0mmJ8XutOpGYMH8YU81PA5SnVphSdSIgdtNryBV+DQJ b87K9cbSpiasACxRjJJQ6IoDoS+WgvhPAJNxgaqYLulT7WtEJ3sfdb03RjhBQ384HZ46 4GaXUSCaty9ucAV3kQ4XovF3CaeDNtIQehBfzOtlX/PLz7Fkf4sSFDJw54ITzHiI8fnH aq5g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=PNJxm2QMtZcp14624QbakT+mhmccQwYHPQgZhw4FCC0=; b=ECG8fa9NLcB6uNXIba/ve1Y/TZSRMLWfu4aL0nl/QwedgJt/xZWWesk/iZSKmd+FxN my0MJHfkGWbBebA2XvjmsBaPKfLTM4QvGLwBjCcAH8R9wxrQBxvSrrXcNLGkPOpB5ZkJ Ha2fhXHYTQVBaG+/E90YU6yMNU03HSzJjgUZ4YVFx//yevNLKCo3lKSd5hT8VlV9lf2f z23KM+eiVjUiv7eORBatYsWEAw4hljm7BelYp/0fnEmzwOWmtEtgUktM0/3rWywCTb9x ia9lusfRoDeiO4mBVCcpyIUSSLY4YfU3R6V3n41fS5Mvaj9NWrWzfhLm3lmJTdWt3Zk4 ZEsw== X-Gm-Message-State: APjAAAUT1st/4jIsu6PIHiVOb+imtkUoItyTnvoHXTi9Cow7nfQEml83 0UGIMhKAXr/k2v4l36RQWShJNqor8NQ= X-Google-Smtp-Source: APXvYqw3fZJ3iyUouHJ8nFwyilGjr1T2hb1aa+sQleUr6TTLPfUpz6FgB0H4htJUIadaJKqKU/hRgg== X-Received: by 2002:adf:e790:: with SMTP id n16mr6226156wrm.120.1565887166646; Thu, 15 Aug 2019 09:39:26 -0700 (PDT) Received: from Mindolluin.ire.aristanetworks.com ([217.173.96.166]) by smtp.gmail.com with ESMTPSA id f7sm5755046wrf.8.2019.08.15.09.39.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Aug 2019 09:39:26 -0700 (PDT) From: Dmitry Safonov To: linux-kernel@vger.kernel.org Cc: Dmitry Safonov <0x7f454c46@gmail.com>, Dmitry Safonov , Adrian Reber , Andrei Vagin , Andy Lutomirski , Arnd Bergmann , Christian Brauner , Cyrill Gorcunov , "Eric W. Biederman" , "H. Peter Anvin" , Ingo Molnar , Jann Horn , Jeff Dike , Oleg Nesterov , Pavel Emelyanov , Shuah Khan , Thomas Gleixner , Vincenzo Frascino , containers@lists.linux-foundation.org, criu@openvz.org, linux-api@vger.kernel.org, x86@kernel.org, Andrei Vagin Subject: [PATCHv6 33/36] selftest/timens: Add procfs selftest Date: Thu, 15 Aug 2019 17:38:33 +0100 Message-Id: <20190815163836.2927-34-dima@arista.com> X-Mailer: git-send-email 2.22.0 In-Reply-To: <20190815163836.2927-1-dima@arista.com> References: <20190815163836.2927-1-dima@arista.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Check that /proc/uptime is correct inside a new time namespace. Co-developed-by: Andrei Vagin Signed-off-by: Andrei Vagin Signed-off-by: Dmitry Safonov --- tools/testing/selftests/timens/.gitignore | 1 + tools/testing/selftests/timens/Makefile | 2 +- tools/testing/selftests/timens/procfs.c | 144 ++++++++++++++++++++++ 3 files changed, 146 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/timens/procfs.c diff --git a/tools/testing/selftests/timens/.gitignore b/tools/testing/selftests/timens/.gitignore index 9b6c8ddac2c8..94ffdd9cead7 100644 --- a/tools/testing/selftests/timens/.gitignore +++ b/tools/testing/selftests/timens/.gitignore @@ -1,3 +1,4 @@ clock_nanosleep +procfs timens timerfd diff --git a/tools/testing/selftests/timens/Makefile b/tools/testing/selftests/timens/Makefile index 76a1dc891184..f96f50d1fef8 100644 --- a/tools/testing/selftests/timens/Makefile +++ b/tools/testing/selftests/timens/Makefile @@ -1,4 +1,4 @@ -TEST_GEN_PROGS := timens timerfd clock_nanosleep +TEST_GEN_PROGS := timens timerfd clock_nanosleep procfs CFLAGS := -Wall -Werror diff --git a/tools/testing/selftests/timens/procfs.c b/tools/testing/selftests/timens/procfs.c new file mode 100644 index 000000000000..3c3c6e634d50 --- /dev/null +++ b/tools/testing/selftests/timens/procfs.c @@ -0,0 +1,144 @@ +// SPDX-License-Identifier: GPL-2.0 +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "log.h" +#include "timens.h" + +/* + * Test shouldn't be run for a day, so add 10 days to child + * time and check parent's time to be in the same day. + */ +#define MAX_TEST_TIME_SEC (60*5) +#define DAY_IN_SEC (60*60*24) +#define TEN_DAYS_IN_SEC (10*DAY_IN_SEC) + +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) + +static int child_ns, parent_ns; + +static int switch_ns(int fd) +{ + if (setns(fd, CLONE_NEWTIME)) + return pr_perror("setns()"); + + return 0; +} + +static int init_namespaces(void) +{ + char path[] = "/proc/self/ns/time_for_children"; + struct stat st1, st2; + + parent_ns = open(path, O_RDONLY); + if (parent_ns <= 0) + return pr_perror("Unable to open %s", path); + + if (fstat(parent_ns, &st1)) + return pr_perror("Unable to stat the parent timens"); + + if (unshare(CLONE_NEWTIME)) + return pr_perror("Can't unshare() timens"); + + child_ns = open(path, O_RDONLY); + if (child_ns <= 0) + return pr_perror("Unable to open %s", path); + + if (fstat(child_ns, &st2)) + return pr_perror("Unable to stat the timens"); + + if (st1.st_ino == st2.st_ino) + return pr_err("The same child_ns after CLONE_NEWTIME"); + + if (_settime(CLOCK_BOOTTIME, TEN_DAYS_IN_SEC)) + return -1; + + return 0; +} + +static int read_proc_uptime(struct timespec *uptime) +{ + unsigned long up_sec, up_nsec; + FILE *proc; + + proc = fopen("/proc/uptime", "r"); + if (proc == NULL) { + pr_perror("Unable to open /proc/uptime"); + return -1; + } + + if (fscanf(proc, "%lu.%02lu", &up_sec, &up_nsec) != 2) { + if (errno) { + pr_perror("fscanf"); + return -errno; + } + pr_err("failed to parse /proc/uptime"); + return -1; + } + fclose(proc); + + uptime->tv_sec = up_sec; + uptime->tv_nsec = up_nsec; + return 0; +} + +static int check_uptime(void) +{ + struct timespec uptime_new, uptime_old; + time_t uptime_expected; + double prec = MAX_TEST_TIME_SEC; + + if (switch_ns(parent_ns)) + return pr_err("switch_ns(%d)", parent_ns); + + if (read_proc_uptime(&uptime_old)) + return 1; + + if (switch_ns(child_ns)) + return pr_err("switch_ns(%d)", child_ns); + + if (read_proc_uptime(&uptime_new)) + return 1; + + uptime_expected = uptime_old.tv_sec + TEN_DAYS_IN_SEC; + if (fabs(difftime(uptime_new.tv_sec, uptime_expected)) > prec) { + pr_fail("uptime in /proc/uptime: old %ld, new %ld [%ld]", + uptime_old.tv_sec, uptime_new.tv_sec, + uptime_old.tv_sec + TEN_DAYS_IN_SEC); + return 1; + } + + ksft_test_result_pass("Passed for /proc/uptime\n"); + return 0; +} + +int main(int argc, char *argv[]) +{ + int ret = 0; + + nscheck(); + + ksft_set_plan(1); + + if (init_namespaces()) + return 1; + + ret |= check_uptime(); + + if (ret) + ksft_exit_fail(); + ksft_exit_pass(); + return ret; +} -- 2.22.0