1f08c3bdfSopenharmony_ci/* 2f08c3bdfSopenharmony_ci * 3f08c3bdfSopenharmony_ci * Copyright (c) International Business Machines Corp., 2001 4f08c3bdfSopenharmony_ci * 5f08c3bdfSopenharmony_ci * This program is free software; you can redistribute it and/or modify 6f08c3bdfSopenharmony_ci * it under the terms of the GNU General Public License as published by 7f08c3bdfSopenharmony_ci * the Free Software Foundation; either version 2 of the License, or 8f08c3bdfSopenharmony_ci * (at your option) any later version. 9f08c3bdfSopenharmony_ci * 10f08c3bdfSopenharmony_ci * This program is distributed in the hope that it will be useful, 11f08c3bdfSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 12f08c3bdfSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 13f08c3bdfSopenharmony_ci * the GNU General Public License for more details. 14f08c3bdfSopenharmony_ci * 15f08c3bdfSopenharmony_ci * You should have received a copy of the GNU General Public License 16f08c3bdfSopenharmony_ci * along with this program; if not, write to the Free Software 17f08c3bdfSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18f08c3bdfSopenharmony_ci */ 19f08c3bdfSopenharmony_ci 20f08c3bdfSopenharmony_ci/* 21f08c3bdfSopenharmony_ci * Testcase to check the basic functionality of the setrlimit system call. 22f08c3bdfSopenharmony_ci * Use the different commands like RLIMIT_NOFILE, RLIMIT_CORE, 23f08c3bdfSopenharmony_ci * RLIMIT_FSIZE, and, RLIMIT_NOFILE, and test for different test 24f08c3bdfSopenharmony_ci * conditions. 25f08c3bdfSopenharmony_ci * 26f08c3bdfSopenharmony_ci * 07/2001 Ported by Wayne Boyer 27f08c3bdfSopenharmony_ci */ 28f08c3bdfSopenharmony_ci 29f08c3bdfSopenharmony_ci#include <sys/types.h> 30f08c3bdfSopenharmony_ci#include <sys/resource.h> 31f08c3bdfSopenharmony_ci#include <sys/stat.h> 32f08c3bdfSopenharmony_ci#include <sys/time.h> 33f08c3bdfSopenharmony_ci#include <sys/wait.h> 34f08c3bdfSopenharmony_ci#include <errno.h> 35f08c3bdfSopenharmony_ci#include <fcntl.h> 36f08c3bdfSopenharmony_ci#include <stdlib.h> 37f08c3bdfSopenharmony_ci#include <unistd.h> 38f08c3bdfSopenharmony_ci#include "test.h" 39f08c3bdfSopenharmony_ci#include "safe_macros.h" 40f08c3bdfSopenharmony_ci 41f08c3bdfSopenharmony_cichar *TCID = "setrlimit01"; 42f08c3bdfSopenharmony_ciint TST_TOTAL = 1; 43f08c3bdfSopenharmony_ci 44f08c3bdfSopenharmony_cistatic void setup(void); 45f08c3bdfSopenharmony_cistatic void cleanup(void); 46f08c3bdfSopenharmony_cistatic void test1(void); 47f08c3bdfSopenharmony_cistatic void test2(void); 48f08c3bdfSopenharmony_cistatic void test3(void); 49f08c3bdfSopenharmony_cistatic void test4(void); 50f08c3bdfSopenharmony_cistatic void sighandler(int); 51f08c3bdfSopenharmony_ci 52f08c3bdfSopenharmony_cistatic char filename[40] = ""; 53f08c3bdfSopenharmony_cistatic struct rlimit save_rlim, rlim, rlim1; 54f08c3bdfSopenharmony_cistatic int nofiles, fd, bytes, i, status; 55f08c3bdfSopenharmony_cistatic char *buf = "abcdefghijklmnopqrstuvwxyz"; 56f08c3bdfSopenharmony_cistatic pid_t pid; 57f08c3bdfSopenharmony_ci 58f08c3bdfSopenharmony_ciint main(int ac, char **av) 59f08c3bdfSopenharmony_ci{ 60f08c3bdfSopenharmony_ci int lc; 61f08c3bdfSopenharmony_ci 62f08c3bdfSopenharmony_ci tst_parse_opts(ac, av, NULL, NULL); 63f08c3bdfSopenharmony_ci 64f08c3bdfSopenharmony_ci setup(); 65f08c3bdfSopenharmony_ci 66f08c3bdfSopenharmony_ci for (lc = 0; TEST_LOOPING(lc); lc++) { 67f08c3bdfSopenharmony_ci tst_count = 0; 68f08c3bdfSopenharmony_ci 69f08c3bdfSopenharmony_ci test1(); 70f08c3bdfSopenharmony_ci test2(); 71f08c3bdfSopenharmony_ci test3(); 72f08c3bdfSopenharmony_ci /* reset saved conditions */ 73f08c3bdfSopenharmony_ci if ((setrlimit(RLIMIT_NPROC, &save_rlim)) == -1) { 74f08c3bdfSopenharmony_ci tst_brkm(TBROK, cleanup, "setrlimit failed to reset " 75f08c3bdfSopenharmony_ci "RLIMIT_NPROC, errno = %d", errno); 76f08c3bdfSopenharmony_ci } 77f08c3bdfSopenharmony_ci test4(); 78f08c3bdfSopenharmony_ci } 79f08c3bdfSopenharmony_ci 80f08c3bdfSopenharmony_ci cleanup(); 81f08c3bdfSopenharmony_ci tst_exit(); 82f08c3bdfSopenharmony_ci} 83f08c3bdfSopenharmony_ci 84f08c3bdfSopenharmony_ci/* 85f08c3bdfSopenharmony_ci * test1 - Test for RLIMIT_NOFILE 86f08c3bdfSopenharmony_ci */ 87f08c3bdfSopenharmony_cistatic void test1(void) 88f08c3bdfSopenharmony_ci{ 89f08c3bdfSopenharmony_ci rlim.rlim_cur = 100; 90f08c3bdfSopenharmony_ci rlim.rlim_max = 100; 91f08c3bdfSopenharmony_ci 92f08c3bdfSopenharmony_ci TEST(setrlimit(RLIMIT_NOFILE, &rlim)); 93f08c3bdfSopenharmony_ci 94f08c3bdfSopenharmony_ci if (TEST_RETURN == -1) { 95f08c3bdfSopenharmony_ci tst_resm(TFAIL, "setrlimit failed to set " 96f08c3bdfSopenharmony_ci "RLIMIT_NOFILE, errno = %d", errno); 97f08c3bdfSopenharmony_ci return; 98f08c3bdfSopenharmony_ci } 99f08c3bdfSopenharmony_ci 100f08c3bdfSopenharmony_ci nofiles = getdtablesize(); 101f08c3bdfSopenharmony_ci 102f08c3bdfSopenharmony_ci if (nofiles != 100) { 103f08c3bdfSopenharmony_ci tst_resm(TFAIL, "setrlimit failed, expected " 104f08c3bdfSopenharmony_ci "100, got %d", nofiles); 105f08c3bdfSopenharmony_ci return; 106f08c3bdfSopenharmony_ci } 107f08c3bdfSopenharmony_ci 108f08c3bdfSopenharmony_ci tst_resm(TPASS, "RLIMIT_NOFILE functionality is correct"); 109f08c3bdfSopenharmony_ci} 110f08c3bdfSopenharmony_ci 111f08c3bdfSopenharmony_ci/* 112f08c3bdfSopenharmony_ci * test2 - Test for RLIMIT_FSIZE 113f08c3bdfSopenharmony_ci */ 114f08c3bdfSopenharmony_cistatic void test2(void) 115f08c3bdfSopenharmony_ci{ 116f08c3bdfSopenharmony_ci /* 117f08c3bdfSopenharmony_ci * Since we would be altering the filesize in the child, 118f08c3bdfSopenharmony_ci * we need to "sync", ie. fflush the parent's write buffers 119f08c3bdfSopenharmony_ci * here. This is because the child will inherit the parent's 120f08c3bdfSopenharmony_ci * write buffer, and while exiting it would try to fflush it. 121f08c3bdfSopenharmony_ci * Since its filesize is truncated to only 10 bytes, the 122f08c3bdfSopenharmony_ci * fflush attempt would fail, and the child would exit with 123f08c3bdfSopenharmony_ci * an wired value! So, it is essential to fflush the parent's 124f08c3bdfSopenharmony_ci * write buffer HERE 125f08c3bdfSopenharmony_ci */ 126f08c3bdfSopenharmony_ci int pipefd[2]; 127f08c3bdfSopenharmony_ci fflush(stdout); 128f08c3bdfSopenharmony_ci SAFE_PIPE(NULL, pipefd); 129f08c3bdfSopenharmony_ci 130f08c3bdfSopenharmony_ci /* 131f08c3bdfSopenharmony_ci * Spawn a child process, and reduce the filesize to 132f08c3bdfSopenharmony_ci * 10 by calling setrlimit(). We can't do this in the 133f08c3bdfSopenharmony_ci * parent, because the parent needs a bigger filesize as its 134f08c3bdfSopenharmony_ci * output will be saved to the logfile (instead of stdout) 135f08c3bdfSopenharmony_ci * when the testcase (parent) is run from the driver. 136f08c3bdfSopenharmony_ci */ 137f08c3bdfSopenharmony_ci pid = FORK_OR_VFORK(); 138f08c3bdfSopenharmony_ci if (pid == -1) 139f08c3bdfSopenharmony_ci tst_brkm(TBROK, cleanup, "fork() failed"); 140f08c3bdfSopenharmony_ci 141f08c3bdfSopenharmony_ci if (pid == 0) { 142f08c3bdfSopenharmony_ci close(pipefd[0]); /* close unused read end */ 143f08c3bdfSopenharmony_ci rlim.rlim_cur = 10; 144f08c3bdfSopenharmony_ci rlim.rlim_max = 10; 145f08c3bdfSopenharmony_ci if ((setrlimit(RLIMIT_FSIZE, &rlim)) == -1) 146f08c3bdfSopenharmony_ci exit(1); 147f08c3bdfSopenharmony_ci 148f08c3bdfSopenharmony_ci fd = creat(filename, 0644); 149f08c3bdfSopenharmony_ci if (fd < 0) 150f08c3bdfSopenharmony_ci exit(2); 151f08c3bdfSopenharmony_ci 152f08c3bdfSopenharmony_ci bytes = write(fd, buf, 26); 153f08c3bdfSopenharmony_ci if (bytes != 10) { 154f08c3bdfSopenharmony_ci if (write(pipefd[1], &bytes, sizeof(bytes)) < (long)sizeof(bytes)) { 155f08c3bdfSopenharmony_ci perror("child: write to pipe failed"); 156f08c3bdfSopenharmony_ci } 157f08c3bdfSopenharmony_ci close(pipefd[1]); /* EOF */ 158f08c3bdfSopenharmony_ci exit(3); 159f08c3bdfSopenharmony_ci } 160f08c3bdfSopenharmony_ci exit(0); /* success */ 161f08c3bdfSopenharmony_ci } 162f08c3bdfSopenharmony_ci 163f08c3bdfSopenharmony_ci /* parent */ 164f08c3bdfSopenharmony_ci SAFE_WAITPID(cleanup, pid, &status, 0); 165f08c3bdfSopenharmony_ci 166f08c3bdfSopenharmony_ci switch (WEXITSTATUS(status)) { 167f08c3bdfSopenharmony_ci case 0: 168f08c3bdfSopenharmony_ci tst_resm(TPASS, "RLIMIT_FSIZE test PASSED"); 169f08c3bdfSopenharmony_ci break; 170f08c3bdfSopenharmony_ci case 1: 171f08c3bdfSopenharmony_ci tst_resm(TFAIL, "setrlimit failed to set " 172f08c3bdfSopenharmony_ci "RLIMIT_FSIZE, errno = %d", errno); 173f08c3bdfSopenharmony_ci break; 174f08c3bdfSopenharmony_ci case 2: 175f08c3bdfSopenharmony_ci tst_resm(TFAIL, "creating testfile failed"); 176f08c3bdfSopenharmony_ci break; 177f08c3bdfSopenharmony_ci case 3: 178f08c3bdfSopenharmony_ci close(pipefd[1]); /* close unused write end */ 179f08c3bdfSopenharmony_ci if (read(pipefd[0], &bytes, sizeof(bytes)) < (long)sizeof(bytes)) 180f08c3bdfSopenharmony_ci tst_resm(TFAIL, "parent: reading pipe failed"); 181f08c3bdfSopenharmony_ci 182f08c3bdfSopenharmony_ci close(pipefd[0]); 183f08c3bdfSopenharmony_ci tst_resm(TFAIL, "setrlimit failed, expected " 184f08c3bdfSopenharmony_ci "10 got %d", bytes); 185f08c3bdfSopenharmony_ci break; 186f08c3bdfSopenharmony_ci default: 187f08c3bdfSopenharmony_ci tst_resm(TFAIL, "child returned bad exit status"); 188f08c3bdfSopenharmony_ci } 189f08c3bdfSopenharmony_ci} 190f08c3bdfSopenharmony_ci 191f08c3bdfSopenharmony_ci/* 192f08c3bdfSopenharmony_ci * test3 - Test for RLIMIT_NPROC 193f08c3bdfSopenharmony_ci */ 194f08c3bdfSopenharmony_cistatic void test3(void) 195f08c3bdfSopenharmony_ci{ 196f08c3bdfSopenharmony_ci SAFE_GETRLIMIT(cleanup, RLIMIT_NPROC, &save_rlim); 197f08c3bdfSopenharmony_ci 198f08c3bdfSopenharmony_ci rlim.rlim_cur = 10; 199f08c3bdfSopenharmony_ci rlim.rlim_max = 10; 200f08c3bdfSopenharmony_ci 201f08c3bdfSopenharmony_ci TEST(setrlimit(RLIMIT_NPROC, &rlim)); 202f08c3bdfSopenharmony_ci 203f08c3bdfSopenharmony_ci if (TEST_RETURN == -1) { 204f08c3bdfSopenharmony_ci tst_resm(TFAIL, "setrlimit failed to set " 205f08c3bdfSopenharmony_ci "RLIMIT_NPROC, errno = %d", errno); 206f08c3bdfSopenharmony_ci return; 207f08c3bdfSopenharmony_ci } 208f08c3bdfSopenharmony_ci 209f08c3bdfSopenharmony_ci if ((getrlimit(RLIMIT_NPROC, &rlim1)) == -1) { 210f08c3bdfSopenharmony_ci tst_brkm(TBROK, cleanup, "getrlimit failed to get " 211f08c3bdfSopenharmony_ci "values for RLIMIT_NPROC, errno = %d", errno); 212f08c3bdfSopenharmony_ci } 213f08c3bdfSopenharmony_ci 214f08c3bdfSopenharmony_ci if ((rlim1.rlim_cur != 10) && (rlim1.rlim_max != 10)) { 215f08c3bdfSopenharmony_ci tst_resm(TFAIL, "setrlimit did not set the proc " 216f08c3bdfSopenharmony_ci "limit correctly"); 217f08c3bdfSopenharmony_ci return; 218f08c3bdfSopenharmony_ci } 219f08c3bdfSopenharmony_ci 220f08c3bdfSopenharmony_ci for (i = 0; i < 20; i++) { 221f08c3bdfSopenharmony_ci pid = FORK_OR_VFORK(); 222f08c3bdfSopenharmony_ci if (pid == -1) { 223f08c3bdfSopenharmony_ci if (errno != EAGAIN) { 224f08c3bdfSopenharmony_ci tst_resm(TWARN, "Expected EAGAIN got %d", 225f08c3bdfSopenharmony_ci errno); 226f08c3bdfSopenharmony_ci } 227f08c3bdfSopenharmony_ci } else if (pid == 0) { 228f08c3bdfSopenharmony_ci exit(0); 229f08c3bdfSopenharmony_ci } 230f08c3bdfSopenharmony_ci } 231f08c3bdfSopenharmony_ci waitpid(pid, &status, 0); 232f08c3bdfSopenharmony_ci if (WEXITSTATUS(status) != 0) 233f08c3bdfSopenharmony_ci tst_resm(TFAIL, "RLIMIT_NPROC functionality is not correct"); 234f08c3bdfSopenharmony_ci else 235f08c3bdfSopenharmony_ci tst_resm(TPASS, "RLIMIT_NPROC functionality is correct"); 236f08c3bdfSopenharmony_ci} 237f08c3bdfSopenharmony_ci 238f08c3bdfSopenharmony_ci/* 239f08c3bdfSopenharmony_ci * test4() - Test for RLIMIT_CORE by forking a child and 240f08c3bdfSopenharmony_ci * having it cause a segfault 241f08c3bdfSopenharmony_ci */ 242f08c3bdfSopenharmony_cistatic void test4(void) 243f08c3bdfSopenharmony_ci{ 244f08c3bdfSopenharmony_ci rlim.rlim_cur = 10; 245f08c3bdfSopenharmony_ci rlim.rlim_max = 10; 246f08c3bdfSopenharmony_ci 247f08c3bdfSopenharmony_ci TEST(setrlimit(RLIMIT_CORE, &rlim)); 248f08c3bdfSopenharmony_ci 249f08c3bdfSopenharmony_ci if (TEST_RETURN == -1) { 250f08c3bdfSopenharmony_ci tst_resm(TFAIL | TTERRNO, "setrlimit failed to set RLIMIT_CORE"); 251f08c3bdfSopenharmony_ci return; 252f08c3bdfSopenharmony_ci } 253f08c3bdfSopenharmony_ci 254f08c3bdfSopenharmony_ci pid = FORK_OR_VFORK(); 255f08c3bdfSopenharmony_ci if (pid == -1) 256f08c3bdfSopenharmony_ci tst_brkm(TBROK, cleanup, "fork() failed"); 257f08c3bdfSopenharmony_ci 258f08c3bdfSopenharmony_ci if (pid == 0) { /* child */ 259f08c3bdfSopenharmony_ci char *testbuf = NULL; 260f08c3bdfSopenharmony_ci strcpy(testbuf, "abcd"); 261f08c3bdfSopenharmony_ci exit(0); 262f08c3bdfSopenharmony_ci } 263f08c3bdfSopenharmony_ci wait(&status); 264f08c3bdfSopenharmony_ci 265f08c3bdfSopenharmony_ci if (access("core", F_OK) == 0) { 266f08c3bdfSopenharmony_ci tst_resm(TFAIL, "core dump dumped unexpectedly"); 267f08c3bdfSopenharmony_ci return; 268f08c3bdfSopenharmony_ci } else if (errno != ENOENT) { 269f08c3bdfSopenharmony_ci tst_resm(TFAIL | TERRNO, "access failed unexpectedly"); 270f08c3bdfSopenharmony_ci return; 271f08c3bdfSopenharmony_ci } 272f08c3bdfSopenharmony_ci 273f08c3bdfSopenharmony_ci tst_resm(TPASS, "RLIMIT_CORE functionality is correct"); 274f08c3bdfSopenharmony_ci} 275f08c3bdfSopenharmony_ci 276f08c3bdfSopenharmony_ci/* 277f08c3bdfSopenharmony_ci * sighandler() - catch sigsegv when generated by child in test #4 278f08c3bdfSopenharmony_ci */ 279f08c3bdfSopenharmony_cistatic void sighandler(int sig) 280f08c3bdfSopenharmony_ci{ 281f08c3bdfSopenharmony_ci if (sig != SIGSEGV && sig != SIGXFSZ && sig != SIGTERM) 282f08c3bdfSopenharmony_ci tst_brkm(TBROK, NULL, "caught unexpected signal: %d", sig); 283f08c3bdfSopenharmony_ci 284f08c3bdfSopenharmony_ci _exit(0); 285f08c3bdfSopenharmony_ci} 286f08c3bdfSopenharmony_ci 287f08c3bdfSopenharmony_cistatic void setup(void) 288f08c3bdfSopenharmony_ci{ 289f08c3bdfSopenharmony_ci tst_require_root(); 290f08c3bdfSopenharmony_ci 291f08c3bdfSopenharmony_ci umask(0); 292f08c3bdfSopenharmony_ci 293f08c3bdfSopenharmony_ci tst_sig(FORK, sighandler, cleanup); 294f08c3bdfSopenharmony_ci 295f08c3bdfSopenharmony_ci TEST_PAUSE; 296f08c3bdfSopenharmony_ci 297f08c3bdfSopenharmony_ci tst_tmpdir(); 298f08c3bdfSopenharmony_ci 299f08c3bdfSopenharmony_ci sprintf(filename, "setrlimit1.%d", getpid()); 300f08c3bdfSopenharmony_ci} 301f08c3bdfSopenharmony_ci 302f08c3bdfSopenharmony_cistatic void cleanup(void) 303f08c3bdfSopenharmony_ci{ 304f08c3bdfSopenharmony_ci unlink(filename); 305f08c3bdfSopenharmony_ci tst_rmdir(); 306f08c3bdfSopenharmony_ci} 307