1  /* Copyright (C) 2018-2023 Free Software Foundation, Inc.
       2     This file is part of the GNU C Library.
       3  
       4     The GNU C Library is free software; you can redistribute it and/or
       5     modify it under the terms of the GNU Lesser General Public
       6     License as published by the Free Software Foundation; either
       7     version 2.1 of the License, or (at your option) any later version.
       8  
       9     The GNU C Library is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12     Lesser General Public License for more details.
      13  
      14     You should have received a copy of the GNU Lesser General Public
      15     License along with the GNU C Library; if not, see
      16     <https://www.gnu.org/licenses/>.  */
      17  
      18  #include <errno.h>
      19  #include <stdio.h>
      20  #include <sys/resource.h>
      21  #include <support/check.h>
      22  
      23  static int resources[] = {
      24    /* The following 7 limits are part of POSIX and must exist.  */
      25    RLIMIT_CORE,
      26    RLIMIT_CPU,
      27    RLIMIT_DATA,
      28    RLIMIT_FSIZE,
      29    RLIMIT_NOFILE,
      30    RLIMIT_STACK,
      31    RLIMIT_AS
      32  };
      33  
      34  #define nresources (sizeof (resources) / sizeof (resources[0]))
      35  
      36  /* Assume that the prlimit64 function calls the prlimit64 syscall without
      37     mangling the arguments.  */
      38  #define PRLIMIT64_INFINITY	((rlim64_t) -1)
      39  
      40  /* As we don't know which limit will be modified, use a sufficiently high
      41     value to not shoot ourself in the foot.  Use a 32-bit value to test
      42     both the 32- and 64-bit versions, and keep the highest bit clear to
      43     avoid sign extension.  */
      44  #define PRLIMIT64_TESTVAL	((rlim64_t) 0x42420000)
      45  
      46  static void
      47  test_getrlimit (int resource, rlim_t exp_cur, rlim_t exp_max)
      48  {
      49    struct rlimit r;
      50    TEST_VERIFY_EXIT (getrlimit (resource, &r) == 0);
      51    TEST_COMPARE (r.rlim_cur, exp_cur);
      52    TEST_COMPARE (r.rlim_max, exp_max);
      53  }
      54  
      55  static void
      56  test_getrlimit64 (int resource, rlim64_t exp_cur, rlim64_t exp_max)
      57  {
      58    struct rlimit64 r;
      59    TEST_VERIFY_EXIT (getrlimit64 (resource, &r) == 0);
      60    TEST_COMPARE (r.rlim_cur, exp_cur);
      61    TEST_COMPARE (r.rlim_max, exp_max);
      62  }
      63  
      64  static void
      65  test_prlimit_get (int resource, rlim_t exp_cur, rlim_t exp_max)
      66  {
      67    struct rlimit r;
      68    TEST_VERIFY_EXIT (prlimit (0, resource, NULL, &r) == 0);
      69    TEST_COMPARE (r.rlim_cur, exp_cur);
      70    TEST_COMPARE (r.rlim_max, exp_max);
      71  }
      72  
      73  static void
      74  test_prlimit64_get (int resource, rlim64_t exp_cur, rlim64_t exp_max)
      75  {
      76    struct rlimit64 r;
      77    TEST_COMPARE (prlimit64 (0, resource, NULL, &r), 0);
      78    TEST_COMPARE (r.rlim_cur, exp_cur);
      79    TEST_COMPARE (r.rlim_max, exp_max);
      80  }
      81  
      82  static void
      83  test_setrlimit (int resource, rlim_t new_cur, rlim_t new_max)
      84  {
      85    struct rlimit r = { new_cur, new_max };
      86    TEST_COMPARE (setrlimit (resource, &r), 0);
      87  }
      88  
      89  static void
      90  test_setrlimit64 (int resource, rlim64_t new_cur, rlim64_t new_max)
      91  {
      92    struct rlimit64 r = { new_cur, new_max };
      93    TEST_COMPARE (setrlimit64 (resource, &r), 0);
      94  }
      95  
      96  static void
      97  test_prlimit_set (int resource, rlim_t new_cur, rlim_t new_max)
      98  {
      99    struct rlimit r = { new_cur, new_max };
     100    TEST_COMPARE (prlimit (0, resource, &r, NULL), 0);
     101  }
     102  
     103  static void
     104  test_prlimit64_set (int resource, rlim64_t new_cur, rlim64_t new_max)
     105  {
     106    struct rlimit64 r = { new_cur, new_max };
     107    TEST_COMPARE (prlimit64 (0, resource, &r, NULL), 0);
     108  }
     109  
     110  static int
     111  do_test (void)
     112  {
     113    int resource = -1;
     114  
     115    /* Find a resource with hard limit set to infinity, so that the soft limit
     116       can be manipulated to any value.  */
     117    for (int i = 0; i < nresources; ++i)
     118      {
     119        struct rlimit64 r64;
     120        int res = prlimit64 (0, resources[i], NULL, &r64);
     121        if ((res == 0) && (r64.rlim_max == PRLIMIT64_INFINITY))
     122  	{
     123  	  resource = resources[i];
     124  	  break;
     125  	}
     126      }
     127  
     128    if (resource == -1)
     129      FAIL_UNSUPPORTED
     130        ("Could not find and limit with hard limit set to infinity.");
     131  
     132    /* First check that the get functions work correctly with the test value.  */
     133    test_prlimit64_set (resource, PRLIMIT64_TESTVAL, PRLIMIT64_INFINITY);
     134    test_getrlimit (resource, PRLIMIT64_TESTVAL, RLIM_INFINITY);
     135    test_getrlimit64 (resource, PRLIMIT64_TESTVAL, RLIM64_INFINITY);
     136    test_prlimit_get (resource, PRLIMIT64_TESTVAL, RLIM_INFINITY);
     137    test_prlimit64_get (resource, PRLIMIT64_TESTVAL, RLIM64_INFINITY);
     138  
     139    /* Then check that the get functions work correctly with infinity.  */
     140    test_prlimit64_set (resource, PRLIMIT64_INFINITY, PRLIMIT64_INFINITY);
     141    test_getrlimit (resource, RLIM_INFINITY, RLIM_INFINITY);
     142    test_getrlimit64 (resource, RLIM64_INFINITY, RLIM64_INFINITY);
     143    test_prlimit_get (resource, RLIM_INFINITY, RLIM_INFINITY);
     144    test_prlimit64_get (resource, RLIM64_INFINITY, RLIM64_INFINITY);
     145  
     146    /* Then check that setrlimit works correctly with the test value.  */
     147    test_setrlimit (resource, PRLIMIT64_TESTVAL, RLIM_INFINITY);
     148    test_prlimit64_get (resource, PRLIMIT64_TESTVAL, PRLIMIT64_INFINITY);
     149  
     150    /* Then check that setrlimit works correctly with infinity.  */
     151    test_setrlimit (resource, RLIM_INFINITY, RLIM_INFINITY);
     152    test_prlimit64_get (resource, PRLIMIT64_INFINITY, PRLIMIT64_INFINITY);
     153  
     154    /* Then check that setrlimit64 works correctly with the test value.  */
     155    test_setrlimit64 (resource, PRLIMIT64_TESTVAL, RLIM64_INFINITY);
     156    test_prlimit64_get (resource, PRLIMIT64_TESTVAL, PRLIMIT64_INFINITY);
     157  
     158    /* Then check that setrlimit64 works correctly with infinity.  */
     159    test_setrlimit64 (resource, RLIM64_INFINITY, RLIM64_INFINITY);
     160    test_prlimit64_get (resource, PRLIMIT64_INFINITY, PRLIMIT64_INFINITY);
     161  
     162    /* Then check that prlimit works correctly with the test value.  */
     163    test_prlimit_set (resource, RLIM_INFINITY, RLIM_INFINITY);
     164    test_prlimit64_get (resource, PRLIMIT64_INFINITY, PRLIMIT64_INFINITY);
     165  
     166    /* Finally check that prlimit works correctly with infinity.  */
     167    test_prlimit_set (resource, PRLIMIT64_TESTVAL, RLIM_INFINITY);
     168    test_prlimit64_get (resource, PRLIMIT64_TESTVAL, PRLIMIT64_INFINITY);
     169  
     170    return 0;
     171  }
     172  
     173  #include <support/test-driver.c>