From patchwork Wed Nov 7 21:22:13 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greg Hackmann X-Patchwork-Id: 994500 X-Patchwork-Delegate: petr.vorel@gmail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=lists.linux.it (client-ip=2001:1418:10:5::2; helo=picard.linux.it; envelope-from=ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=google.com header.i=@google.com header.b="Kzye8c94"; dkim-atps=neutral Received: from picard.linux.it (picard.linux.it [IPv6:2001:1418:10:5::2]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 42qzrz6zm4z9s9G for ; Thu, 8 Nov 2018 08:22:27 +1100 (AEDT) Received: from picard.linux.it (localhost [IPv6:::1]) by picard.linux.it (Postfix) with ESMTP id 4C5613E78D1 for ; Wed, 7 Nov 2018 22:22:25 +0100 (CET) X-Original-To: ltp@lists.linux.it Delivered-To: ltp@picard.linux.it Received: from in-6.smtp.seeweb.it (in-6.smtp.seeweb.it [217.194.8.6]) by picard.linux.it (Postfix) with ESMTP id 72C0F3E6090 for ; Wed, 7 Nov 2018 22:22:23 +0100 (CET) Received: from mail-it1-x149.google.com (mail-it1-x149.google.com [IPv6:2607:f8b0:4864:20::149]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by in-6.smtp.seeweb.it (Postfix) with ESMTPS id 7BE4E1401130 for ; Wed, 7 Nov 2018 22:22:22 +0100 (CET) Received: by mail-it1-x149.google.com with SMTP id m137-v6so20333732ita.9 for ; Wed, 07 Nov 2018 13:22:22 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=19r1ksC0PuTgGq5x0pFRuPDIOlNAnLCuBsbZtTl1MhE=; b=Kzye8c94k7l2TrY2slOoUG6wQfEFycADsiU3gCdlbc/R+7arL/MtFwDF3rV0F9UQ6H UZ8sYvs891gjDWwhjshiYhBBBvK9CbtW8KG9ytzV/V1obCQ6rIlteYoLFBppZcSL5nug ndN47h/odhmxN3BN2RWUru6hH/9OH+835eBYlBI4sW8rMiYR+HO3F4eWoW9vA9nzHSZ7 XiuYsbhrS2ehurbyLzNqglgJHVoKl9dRyDbE2b7xnuS2RP+IZ9jV9vQnhy40ibH3G5og Ab8QzDbIcJFwd5KVg2+sMOjPuWLYmSFnkRnXGRdqCr7JXzBOJKssbT3p59LjwrwOmZes teGA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=19r1ksC0PuTgGq5x0pFRuPDIOlNAnLCuBsbZtTl1MhE=; b=ftEXpf+ELMN6Ek3Mfvdnk+lcgWpEoTa9vJ/kQwE/O5Dm98fgrJvQSktnNvZx28xerj BbYJFK4RkKcG1+97hxX00hc8uSqjZMOd4YYbfxeDwccfAh52TdR/BgJ27eVzUyatoltV PF97eU68jl34WSSAe64NA98x5iA8x5d9jy5KqeFCwtwLrlKKkLrJRQcjyZSndbdfi0nC 4ML/Oaq7R/9VIZasMpbxmXKP7L7a8e6FkdF4wwT+GTvo4nl8ohTUBnRdh+y6OOhYy2bj ajpPyBVFzd+MW7E1xYZxKtWrEkIjUkKoysFmX+RYBNLErpdd1DQdEvQLxXVG1KKChSVr NWxw== X-Gm-Message-State: AGRZ1gI7jAMhStvc1cSzQ5dTFSOFRPgyWJR2z/2xpdQ4cUeqoVYEWIPc unIl29fGNbKbWzG7kEeuQ0OBpZ8ZDz2FbB7ngohBPr1qJONL40cuUFsyPdPOnQuMVd1JgcPOyNY cTtgkk/LQLskmHx3yKj7VFgtlMeE88WvzLMH011ddo8iR9XMXGmWp3R5FlhtYbvXY X-Google-Smtp-Source: AJdET5fjhKtaCRVnM28WzjwPqE0qzMfXE2xdg1uWKu1sYA0u0prDEqXkelDHTtNQUOFQaqKOntEuThgaHDqgmEw= X-Received: by 2002:a24:3303:: with SMTP id k3-v6mr1521423itk.2.1541625741102; Wed, 07 Nov 2018 13:22:21 -0800 (PST) Date: Wed, 7 Nov 2018 13:22:13 -0800 In-Reply-To: <20181106194725.GA11344@rei.lan> Message-Id: <20181107212213.129534-1-ghackmann@google.com> Mime-Version: 1.0 References: <20181106194725.GA11344@rei.lan> X-Mailer: git-send-email 2.19.1.930.g4563a0d9d0-goog From: Greg Hackmann To: ltp@lists.linux.it X-Virus-Scanned: clamav-milter 0.99.2 at in-6.smtp.seeweb.it X-Virus-Status: Clean X-Spam-Status: No, score=-7.4 required=7.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU, SPF_PASS, USER_IN_DEF_DKIM_WL autolearn=disabled version=3.4.0 X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on in-6.smtp.seeweb.it Cc: kernel-team@android.com Subject: [LTP] [PATCH v2] getrlimit/getrlimit03: new test for underlying syscall variants X-BeenThere: ltp@lists.linux.it X-Mailman-Version: 2.1.18 Precedence: list List-Id: Linux Test Project List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it Sender: "ltp" Depending on the architecture, Linux provides up to three syscalls that have been used to implement getrlimit(2) in different libc implementations. These syscalls differ in the size and signedness of rlim_t. This test compares the results returned by all three syscalls, confirming that they either match or were appropriately capped at the respective RLIM_INFINITY constant. Signed-off-by: Greg Hackmann --- v2: use tst_syscall() to correctly handle kernels that don't have the prlimit64 syscall .../kernel/syscalls/getrlimit/getrlimit03.c | 195 ++++++++++++++++++ 1 file changed, 195 insertions(+) create mode 100644 testcases/kernel/syscalls/getrlimit/getrlimit03.c diff --git a/testcases/kernel/syscalls/getrlimit/getrlimit03.c b/testcases/kernel/syscalls/getrlimit/getrlimit03.c new file mode 100644 index 000000000..2f08e14b7 --- /dev/null +++ b/testcases/kernel/syscalls/getrlimit/getrlimit03.c @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2018 Google, Inc. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program, if not, see . + */ + +/** + * Architectures may provide up to three syscalls that have been used to + * implement getrlimit(2) in different libc implementations. These syscalls + * differ in the size and signedness of rlim_t: + * + * - __NR_getrlimit uses long or unsigned long, depending on the + * architecture + * + * - __NR_ugetrlimit uses unsigned long, and only exists on + * architectures where __NR_getrlimit is signed + * + * - __NR_prlimit64 uses uint64_t + * + * This test compares the results returned by all three syscalls, confirming + * that they either match or were appropriately capped at the respective + * RLIM_INFINITY constant. + */ + +#include +#include +#include +#include + +#include "tst_test.h" +#include "lapi/syscalls.h" + +/** + * Linux provides an "old" getrlimit syscall handler that uses signed long, + * and a "new" getrlimit syscall handler that uses unsigned long. + * + * The underlying syscall names vary across architectures, depending on whether + * the architecture predates the "new" handler. For clarity, this test + * will call them getrlimit_long and getlimit_ulong internally. + */ +#define SIGNED_GETRLIMIT (__NR_ugetrlimit != __LTP__NR_INVALID_SYSCALL) +#if SIGNED_GETRLIMIT +#define __NR_getrlimit_ulong __NR_ugetrlimit +#define __NR_getrlimit_ulong_str "__NR_ugetrlimit" +#else +#define __NR_getrlimit_ulong __NR_getrlimit +#define __NR_getrlimit_ulong_str "__NR_getrlimit" +#endif + +struct rlimit64 { + uint64_t rlim_cur; + uint64_t rlim_max; +}; +const uint64_t RLIM_INFINITY_U64 = UINT64_MAX; + +static int getrlimit_u64(int resource, struct rlimit64 *rlim) +{ + return tst_syscall(__NR_prlimit64, 0, resource, NULL, rlim); +} + +struct rlimit_ulong { + unsigned long rlim_cur; + unsigned long rlim_max; +}; +const unsigned long RLIM_INFINITY_UL = ULONG_MAX; + +static int getrlimit_ulong(int resource, struct rlimit_ulong *rlim) +{ + return syscall(__NR_getrlimit_ulong, resource, rlim); +} + +#if SIGNED_GETRLIMIT +struct rlimit_long { + long rlim_cur; + long rlim_max; +}; +const long RLIM_INFINITY_L = LONG_MAX; + +static int getrlimit_long(int resource, struct rlimit_long *rlim) +{ + return syscall(__NR_getrlimit, resource, rlim); +} +#endif + +static int compare_retval(int resource, int ret_u64, int errno_u64, + int ret_other, int errno_other, + const char *other_syscall) +{ + if (ret_u64 != ret_other || errno_u64 != errno_other) { + tst_res(TFAIL, "__NR_prlimit64(%d) returned %d (%s) but %s(%d) returned %d (%s)", + resource, ret_u64, tst_strerrno(errno_u64), + other_syscall, resource, ret_other, + tst_strerrno(errno_other)); + return -1; + } + + return 0; +} + +static int compare_u64_ulong(int resource, uint64_t val_u64, + unsigned long val_ul, const char *kind) +{ + if ((val_u64 > RLIM_INFINITY_UL && val_ul != RLIM_INFINITY_UL) || + (val_u64 <= RLIM_INFINITY_UL && val_ul != val_u64)) { + tst_res(TFAIL, "__NR_prlimit64(%d) had %s = %" PRIx64 " but " __NR_getrlimit_ulong_str "(%d) had %s = %lx", + resource, kind, val_u64, + resource, kind, val_ul); + return -1; + } + + return 0; +} + +#if SIGNED_GETRLIMIT +static int compare_u64_long(int resource, uint64_t val_u64, long val_l, + const char *kind) +{ + if ((val_u64 > (uint64_t)RLIM_INFINITY_L && val_l != RLIM_INFINITY_L) || + (val_u64 <= (uint64_t)RLIM_INFINITY_L && val_l != (long)val_u64)) { + tst_res(TFAIL, "__NR_prlimit64(%d) had %s = %" PRIx64 " but __NR_getrlimit(%d) had %s = %lx", + resource, kind, val_u64, + resource, kind, val_l); + return -1; + } + + return 0; +} +#endif + +static void run(unsigned int resource) +{ + struct rlimit64 rlim_u64; + int ret_u64; + int errno_u64; + + struct rlimit_ulong rlim_ul; + int ret_ul; + int errno_ul; + +#if SIGNED_GETRLIMIT + struct rlimit_long rlim_l; + int ret_l; + int errno_l; +#endif + + errno = 0; + ret_u64 = getrlimit_u64(resource, &rlim_u64); + errno_u64 = errno; + + errno = 0; + ret_ul = getrlimit_ulong(resource, &rlim_ul); + errno_ul = errno; + + if (compare_retval(resource, ret_u64, errno_u64, ret_ul, errno_ul, + __NR_getrlimit_ulong_str) || + compare_u64_ulong(resource, rlim_u64.rlim_cur, rlim_ul.rlim_cur, + "rlim_cur") || + compare_u64_ulong(resource, rlim_u64.rlim_max, rlim_ul.rlim_max, + "rlim_max")) + return; + +#if SIGNED_GETRLIMIT + errno = 0; + ret_l = getrlimit_long(resource, &rlim_l); + errno_l = errno; + + if (compare_retval(resource, ret_u64, errno_u64, ret_l, errno_l, + "__NR_getrlimit") || + compare_u64_long(resource, rlim_u64.rlim_cur, rlim_l.rlim_cur, + "rlim_cur") || + compare_u64_long(resource, rlim_u64.rlim_max, rlim_l.rlim_max, + "rlim_max")) + return; +#endif + + tst_res(TPASS, "getrlimit(%u) was consistent during all syscalls", + resource); +} + +static struct tst_test test = { + .tcnt = RLIM_NLIMITS, + .test = run, +}; +