162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * This application is Copyright 2012 Red Hat, Inc. 362306a36Sopenharmony_ci * Doug Ledford <dledford@redhat.com> 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * mq_open_tests is free software: you can redistribute it and/or modify 662306a36Sopenharmony_ci * it under the terms of the GNU General Public License as published by 762306a36Sopenharmony_ci * the Free Software Foundation, version 3. 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * mq_open_tests is distributed in the hope that it will be useful, 1062306a36Sopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 1162306a36Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1262306a36Sopenharmony_ci * GNU General Public License for more details. 1362306a36Sopenharmony_ci * 1462306a36Sopenharmony_ci * For the full text of the license, see <http://www.gnu.org/licenses/>. 1562306a36Sopenharmony_ci * 1662306a36Sopenharmony_ci * mq_open_tests.c 1762306a36Sopenharmony_ci * Tests the various situations that should either succeed or fail to 1862306a36Sopenharmony_ci * open a posix message queue and then reports whether or not they 1962306a36Sopenharmony_ci * did as they were supposed to. 2062306a36Sopenharmony_ci * 2162306a36Sopenharmony_ci */ 2262306a36Sopenharmony_ci#include <stdio.h> 2362306a36Sopenharmony_ci#include <stdlib.h> 2462306a36Sopenharmony_ci#include <unistd.h> 2562306a36Sopenharmony_ci#include <fcntl.h> 2662306a36Sopenharmony_ci#include <string.h> 2762306a36Sopenharmony_ci#include <limits.h> 2862306a36Sopenharmony_ci#include <errno.h> 2962306a36Sopenharmony_ci#include <sys/types.h> 3062306a36Sopenharmony_ci#include <sys/time.h> 3162306a36Sopenharmony_ci#include <sys/resource.h> 3262306a36Sopenharmony_ci#include <sys/stat.h> 3362306a36Sopenharmony_ci#include <mqueue.h> 3462306a36Sopenharmony_ci#include <error.h> 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci#include "../kselftest.h" 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_cistatic char *usage = 3962306a36Sopenharmony_ci"Usage:\n" 4062306a36Sopenharmony_ci" %s path\n" 4162306a36Sopenharmony_ci"\n" 4262306a36Sopenharmony_ci" path Path name of the message queue to create\n" 4362306a36Sopenharmony_ci"\n" 4462306a36Sopenharmony_ci" Note: this program must be run as root in order to enable all tests\n" 4562306a36Sopenharmony_ci"\n"; 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_cichar *DEF_MSGS = "/proc/sys/fs/mqueue/msg_default"; 4862306a36Sopenharmony_cichar *DEF_MSGSIZE = "/proc/sys/fs/mqueue/msgsize_default"; 4962306a36Sopenharmony_cichar *MAX_MSGS = "/proc/sys/fs/mqueue/msg_max"; 5062306a36Sopenharmony_cichar *MAX_MSGSIZE = "/proc/sys/fs/mqueue/msgsize_max"; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ciint default_settings; 5362306a36Sopenharmony_cistruct rlimit saved_limits, cur_limits; 5462306a36Sopenharmony_ciint saved_def_msgs, saved_def_msgsize, saved_max_msgs, saved_max_msgsize; 5562306a36Sopenharmony_ciint cur_def_msgs, cur_def_msgsize, cur_max_msgs, cur_max_msgsize; 5662306a36Sopenharmony_ciFILE *def_msgs, *def_msgsize, *max_msgs, *max_msgsize; 5762306a36Sopenharmony_cichar *queue_path; 5862306a36Sopenharmony_cichar *default_queue_path = "/test1"; 5962306a36Sopenharmony_cimqd_t queue = -1; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_cistatic inline void __set(FILE *stream, int value, char *err_msg); 6262306a36Sopenharmony_civoid shutdown(int exit_val, char *err_cause, int line_no); 6362306a36Sopenharmony_cistatic inline int get(FILE *stream); 6462306a36Sopenharmony_cistatic inline void set(FILE *stream, int value); 6562306a36Sopenharmony_cistatic inline void getr(int type, struct rlimit *rlim); 6662306a36Sopenharmony_cistatic inline void setr(int type, struct rlimit *rlim); 6762306a36Sopenharmony_civoid validate_current_settings(); 6862306a36Sopenharmony_cistatic inline void test_queue(struct mq_attr *attr, struct mq_attr *result); 6962306a36Sopenharmony_cistatic inline int test_queue_fail(struct mq_attr *attr, struct mq_attr *result); 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_cistatic inline void __set(FILE *stream, int value, char *err_msg) 7262306a36Sopenharmony_ci{ 7362306a36Sopenharmony_ci rewind(stream); 7462306a36Sopenharmony_ci if (fprintf(stream, "%d", value) < 0) 7562306a36Sopenharmony_ci perror(err_msg); 7662306a36Sopenharmony_ci} 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_civoid shutdown(int exit_val, char *err_cause, int line_no) 8062306a36Sopenharmony_ci{ 8162306a36Sopenharmony_ci static int in_shutdown = 0; 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci /* In case we get called recursively by a set() call below */ 8462306a36Sopenharmony_ci if (in_shutdown++) 8562306a36Sopenharmony_ci return; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci if (seteuid(0) == -1) 8862306a36Sopenharmony_ci perror("seteuid() failed"); 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci if (queue != -1) 9162306a36Sopenharmony_ci if (mq_close(queue)) 9262306a36Sopenharmony_ci perror("mq_close() during shutdown"); 9362306a36Sopenharmony_ci if (queue_path) 9462306a36Sopenharmony_ci /* 9562306a36Sopenharmony_ci * Be silent if this fails, if we cleaned up already it's 9662306a36Sopenharmony_ci * expected to fail 9762306a36Sopenharmony_ci */ 9862306a36Sopenharmony_ci mq_unlink(queue_path); 9962306a36Sopenharmony_ci if (default_settings) { 10062306a36Sopenharmony_ci if (saved_def_msgs) 10162306a36Sopenharmony_ci __set(def_msgs, saved_def_msgs, 10262306a36Sopenharmony_ci "failed to restore saved_def_msgs"); 10362306a36Sopenharmony_ci if (saved_def_msgsize) 10462306a36Sopenharmony_ci __set(def_msgsize, saved_def_msgsize, 10562306a36Sopenharmony_ci "failed to restore saved_def_msgsize"); 10662306a36Sopenharmony_ci } 10762306a36Sopenharmony_ci if (saved_max_msgs) 10862306a36Sopenharmony_ci __set(max_msgs, saved_max_msgs, 10962306a36Sopenharmony_ci "failed to restore saved_max_msgs"); 11062306a36Sopenharmony_ci if (saved_max_msgsize) 11162306a36Sopenharmony_ci __set(max_msgsize, saved_max_msgsize, 11262306a36Sopenharmony_ci "failed to restore saved_max_msgsize"); 11362306a36Sopenharmony_ci if (exit_val) 11462306a36Sopenharmony_ci error(exit_val, errno, "%s at %d", err_cause, line_no); 11562306a36Sopenharmony_ci exit(0); 11662306a36Sopenharmony_ci} 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_cistatic inline int get(FILE *stream) 11962306a36Sopenharmony_ci{ 12062306a36Sopenharmony_ci int value; 12162306a36Sopenharmony_ci rewind(stream); 12262306a36Sopenharmony_ci if (fscanf(stream, "%d", &value) != 1) 12362306a36Sopenharmony_ci shutdown(4, "Error reading /proc entry", __LINE__ - 1); 12462306a36Sopenharmony_ci return value; 12562306a36Sopenharmony_ci} 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_cistatic inline void set(FILE *stream, int value) 12862306a36Sopenharmony_ci{ 12962306a36Sopenharmony_ci int new_value; 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci rewind(stream); 13262306a36Sopenharmony_ci if (fprintf(stream, "%d", value) < 0) 13362306a36Sopenharmony_ci return shutdown(5, "Failed writing to /proc file", 13462306a36Sopenharmony_ci __LINE__ - 1); 13562306a36Sopenharmony_ci new_value = get(stream); 13662306a36Sopenharmony_ci if (new_value != value) 13762306a36Sopenharmony_ci return shutdown(5, "We didn't get what we wrote to /proc back", 13862306a36Sopenharmony_ci __LINE__ - 1); 13962306a36Sopenharmony_ci} 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_cistatic inline void getr(int type, struct rlimit *rlim) 14262306a36Sopenharmony_ci{ 14362306a36Sopenharmony_ci if (getrlimit(type, rlim)) 14462306a36Sopenharmony_ci shutdown(6, "getrlimit()", __LINE__ - 1); 14562306a36Sopenharmony_ci} 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_cistatic inline void setr(int type, struct rlimit *rlim) 14862306a36Sopenharmony_ci{ 14962306a36Sopenharmony_ci if (setrlimit(type, rlim)) 15062306a36Sopenharmony_ci shutdown(7, "setrlimit()", __LINE__ - 1); 15162306a36Sopenharmony_ci} 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_civoid validate_current_settings() 15462306a36Sopenharmony_ci{ 15562306a36Sopenharmony_ci int rlim_needed; 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci if (cur_limits.rlim_cur < 4096) { 15862306a36Sopenharmony_ci printf("Current rlimit value for POSIX message queue bytes is " 15962306a36Sopenharmony_ci "unreasonably low,\nincreasing.\n\n"); 16062306a36Sopenharmony_ci cur_limits.rlim_cur = 8192; 16162306a36Sopenharmony_ci cur_limits.rlim_max = 16384; 16262306a36Sopenharmony_ci setr(RLIMIT_MSGQUEUE, &cur_limits); 16362306a36Sopenharmony_ci } 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci if (default_settings) { 16662306a36Sopenharmony_ci rlim_needed = (cur_def_msgs + 1) * (cur_def_msgsize + 1 + 16762306a36Sopenharmony_ci 2 * sizeof(void *)); 16862306a36Sopenharmony_ci if (rlim_needed > cur_limits.rlim_cur) { 16962306a36Sopenharmony_ci printf("Temporarily lowering default queue parameters " 17062306a36Sopenharmony_ci "to something that will work\n" 17162306a36Sopenharmony_ci "with the current rlimit values.\n\n"); 17262306a36Sopenharmony_ci set(def_msgs, 10); 17362306a36Sopenharmony_ci cur_def_msgs = 10; 17462306a36Sopenharmony_ci set(def_msgsize, 128); 17562306a36Sopenharmony_ci cur_def_msgsize = 128; 17662306a36Sopenharmony_ci } 17762306a36Sopenharmony_ci } else { 17862306a36Sopenharmony_ci rlim_needed = (cur_max_msgs + 1) * (cur_max_msgsize + 1 + 17962306a36Sopenharmony_ci 2 * sizeof(void *)); 18062306a36Sopenharmony_ci if (rlim_needed > cur_limits.rlim_cur) { 18162306a36Sopenharmony_ci printf("Temporarily lowering maximum queue parameters " 18262306a36Sopenharmony_ci "to something that will work\n" 18362306a36Sopenharmony_ci "with the current rlimit values in case this is " 18462306a36Sopenharmony_ci "a kernel that ties the default\n" 18562306a36Sopenharmony_ci "queue parameters to the maximum queue " 18662306a36Sopenharmony_ci "parameters.\n\n"); 18762306a36Sopenharmony_ci set(max_msgs, 10); 18862306a36Sopenharmony_ci cur_max_msgs = 10; 18962306a36Sopenharmony_ci set(max_msgsize, 128); 19062306a36Sopenharmony_ci cur_max_msgsize = 128; 19162306a36Sopenharmony_ci } 19262306a36Sopenharmony_ci } 19362306a36Sopenharmony_ci} 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci/* 19662306a36Sopenharmony_ci * test_queue - Test opening a queue, shutdown if we fail. This should 19762306a36Sopenharmony_ci * only be called in situations that should never fail. We clean up 19862306a36Sopenharmony_ci * after ourselves and return the queue attributes in *result. 19962306a36Sopenharmony_ci */ 20062306a36Sopenharmony_cistatic inline void test_queue(struct mq_attr *attr, struct mq_attr *result) 20162306a36Sopenharmony_ci{ 20262306a36Sopenharmony_ci int flags = O_RDWR | O_EXCL | O_CREAT; 20362306a36Sopenharmony_ci int perms = DEFFILEMODE; 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci if ((queue = mq_open(queue_path, flags, perms, attr)) == -1) 20662306a36Sopenharmony_ci shutdown(1, "mq_open()", __LINE__); 20762306a36Sopenharmony_ci if (mq_getattr(queue, result)) 20862306a36Sopenharmony_ci shutdown(1, "mq_getattr()", __LINE__); 20962306a36Sopenharmony_ci if (mq_close(queue)) 21062306a36Sopenharmony_ci shutdown(1, "mq_close()", __LINE__); 21162306a36Sopenharmony_ci queue = -1; 21262306a36Sopenharmony_ci if (mq_unlink(queue_path)) 21362306a36Sopenharmony_ci shutdown(1, "mq_unlink()", __LINE__); 21462306a36Sopenharmony_ci} 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci/* 21762306a36Sopenharmony_ci * Same as test_queue above, but failure is not fatal. 21862306a36Sopenharmony_ci * Returns: 21962306a36Sopenharmony_ci * 0 - Failed to create a queue 22062306a36Sopenharmony_ci * 1 - Created a queue, attributes in *result 22162306a36Sopenharmony_ci */ 22262306a36Sopenharmony_cistatic inline int test_queue_fail(struct mq_attr *attr, struct mq_attr *result) 22362306a36Sopenharmony_ci{ 22462306a36Sopenharmony_ci int flags = O_RDWR | O_EXCL | O_CREAT; 22562306a36Sopenharmony_ci int perms = DEFFILEMODE; 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci if ((queue = mq_open(queue_path, flags, perms, attr)) == -1) 22862306a36Sopenharmony_ci return 0; 22962306a36Sopenharmony_ci if (mq_getattr(queue, result)) 23062306a36Sopenharmony_ci shutdown(1, "mq_getattr()", __LINE__); 23162306a36Sopenharmony_ci if (mq_close(queue)) 23262306a36Sopenharmony_ci shutdown(1, "mq_close()", __LINE__); 23362306a36Sopenharmony_ci queue = -1; 23462306a36Sopenharmony_ci if (mq_unlink(queue_path)) 23562306a36Sopenharmony_ci shutdown(1, "mq_unlink()", __LINE__); 23662306a36Sopenharmony_ci return 1; 23762306a36Sopenharmony_ci} 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ciint main(int argc, char *argv[]) 24062306a36Sopenharmony_ci{ 24162306a36Sopenharmony_ci struct mq_attr attr, result; 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci if (argc != 2) { 24462306a36Sopenharmony_ci printf("Using Default queue path - %s\n", default_queue_path); 24562306a36Sopenharmony_ci queue_path = default_queue_path; 24662306a36Sopenharmony_ci } else { 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci /* 24962306a36Sopenharmony_ci * Although we can create a msg queue with a non-absolute path name, 25062306a36Sopenharmony_ci * unlink will fail. So, if the name doesn't start with a /, add one 25162306a36Sopenharmony_ci * when we save it. 25262306a36Sopenharmony_ci */ 25362306a36Sopenharmony_ci if (*argv[1] == '/') 25462306a36Sopenharmony_ci queue_path = strdup(argv[1]); 25562306a36Sopenharmony_ci else { 25662306a36Sopenharmony_ci queue_path = malloc(strlen(argv[1]) + 2); 25762306a36Sopenharmony_ci if (!queue_path) { 25862306a36Sopenharmony_ci perror("malloc()"); 25962306a36Sopenharmony_ci exit(1); 26062306a36Sopenharmony_ci } 26162306a36Sopenharmony_ci queue_path[0] = '/'; 26262306a36Sopenharmony_ci queue_path[1] = 0; 26362306a36Sopenharmony_ci strcat(queue_path, argv[1]); 26462306a36Sopenharmony_ci } 26562306a36Sopenharmony_ci } 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci if (getuid() != 0) 26862306a36Sopenharmony_ci ksft_exit_skip("Not running as root, but almost all tests " 26962306a36Sopenharmony_ci "require root in order to modify\nsystem settings. " 27062306a36Sopenharmony_ci "Exiting.\n"); 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci /* Find out what files there are for us to make tweaks in */ 27362306a36Sopenharmony_ci def_msgs = fopen(DEF_MSGS, "r+"); 27462306a36Sopenharmony_ci def_msgsize = fopen(DEF_MSGSIZE, "r+"); 27562306a36Sopenharmony_ci max_msgs = fopen(MAX_MSGS, "r+"); 27662306a36Sopenharmony_ci max_msgsize = fopen(MAX_MSGSIZE, "r+"); 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci if (!max_msgs) 27962306a36Sopenharmony_ci shutdown(2, "Failed to open msg_max", __LINE__); 28062306a36Sopenharmony_ci if (!max_msgsize) 28162306a36Sopenharmony_ci shutdown(2, "Failed to open msgsize_max", __LINE__); 28262306a36Sopenharmony_ci if (def_msgs || def_msgsize) 28362306a36Sopenharmony_ci default_settings = 1; 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci /* Load up the current system values for everything we can */ 28662306a36Sopenharmony_ci getr(RLIMIT_MSGQUEUE, &saved_limits); 28762306a36Sopenharmony_ci cur_limits = saved_limits; 28862306a36Sopenharmony_ci if (default_settings) { 28962306a36Sopenharmony_ci saved_def_msgs = cur_def_msgs = get(def_msgs); 29062306a36Sopenharmony_ci saved_def_msgsize = cur_def_msgsize = get(def_msgsize); 29162306a36Sopenharmony_ci } 29262306a36Sopenharmony_ci saved_max_msgs = cur_max_msgs = get(max_msgs); 29362306a36Sopenharmony_ci saved_max_msgsize = cur_max_msgsize = get(max_msgsize); 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci /* Tell the user our initial state */ 29662306a36Sopenharmony_ci printf("\nInitial system state:\n"); 29762306a36Sopenharmony_ci printf("\tUsing queue path:\t\t%s\n", queue_path); 29862306a36Sopenharmony_ci printf("\tRLIMIT_MSGQUEUE(soft):\t\t%ld\n", 29962306a36Sopenharmony_ci (long) saved_limits.rlim_cur); 30062306a36Sopenharmony_ci printf("\tRLIMIT_MSGQUEUE(hard):\t\t%ld\n", 30162306a36Sopenharmony_ci (long) saved_limits.rlim_max); 30262306a36Sopenharmony_ci printf("\tMaximum Message Size:\t\t%d\n", saved_max_msgsize); 30362306a36Sopenharmony_ci printf("\tMaximum Queue Size:\t\t%d\n", saved_max_msgs); 30462306a36Sopenharmony_ci if (default_settings) { 30562306a36Sopenharmony_ci printf("\tDefault Message Size:\t\t%d\n", saved_def_msgsize); 30662306a36Sopenharmony_ci printf("\tDefault Queue Size:\t\t%d\n", saved_def_msgs); 30762306a36Sopenharmony_ci } else { 30862306a36Sopenharmony_ci printf("\tDefault Message Size:\t\tNot Supported\n"); 30962306a36Sopenharmony_ci printf("\tDefault Queue Size:\t\tNot Supported\n"); 31062306a36Sopenharmony_ci } 31162306a36Sopenharmony_ci printf("\n"); 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci validate_current_settings(); 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci printf("Adjusted system state for testing:\n"); 31662306a36Sopenharmony_ci printf("\tRLIMIT_MSGQUEUE(soft):\t\t%ld\n", (long) cur_limits.rlim_cur); 31762306a36Sopenharmony_ci printf("\tRLIMIT_MSGQUEUE(hard):\t\t%ld\n", (long) cur_limits.rlim_max); 31862306a36Sopenharmony_ci printf("\tMaximum Message Size:\t\t%d\n", cur_max_msgsize); 31962306a36Sopenharmony_ci printf("\tMaximum Queue Size:\t\t%d\n", cur_max_msgs); 32062306a36Sopenharmony_ci if (default_settings) { 32162306a36Sopenharmony_ci printf("\tDefault Message Size:\t\t%d\n", cur_def_msgsize); 32262306a36Sopenharmony_ci printf("\tDefault Queue Size:\t\t%d\n", cur_def_msgs); 32362306a36Sopenharmony_ci } 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci printf("\n\nTest series 1, behavior when no attr struct " 32662306a36Sopenharmony_ci "passed to mq_open:\n"); 32762306a36Sopenharmony_ci if (!default_settings) { 32862306a36Sopenharmony_ci test_queue(NULL, &result); 32962306a36Sopenharmony_ci printf("Given sane system settings, mq_open without an attr " 33062306a36Sopenharmony_ci "struct succeeds:\tPASS\n"); 33162306a36Sopenharmony_ci if (result.mq_maxmsg != cur_max_msgs || 33262306a36Sopenharmony_ci result.mq_msgsize != cur_max_msgsize) { 33362306a36Sopenharmony_ci printf("Kernel does not support setting the default " 33462306a36Sopenharmony_ci "mq attributes,\nbut also doesn't tie the " 33562306a36Sopenharmony_ci "defaults to the maximums:\t\t\tPASS\n"); 33662306a36Sopenharmony_ci } else { 33762306a36Sopenharmony_ci set(max_msgs, ++cur_max_msgs); 33862306a36Sopenharmony_ci set(max_msgsize, ++cur_max_msgsize); 33962306a36Sopenharmony_ci test_queue(NULL, &result); 34062306a36Sopenharmony_ci if (result.mq_maxmsg == cur_max_msgs && 34162306a36Sopenharmony_ci result.mq_msgsize == cur_max_msgsize) 34262306a36Sopenharmony_ci printf("Kernel does not support setting the " 34362306a36Sopenharmony_ci "default mq attributes and\n" 34462306a36Sopenharmony_ci "also ties system wide defaults to " 34562306a36Sopenharmony_ci "the system wide maximums:\t\t" 34662306a36Sopenharmony_ci "FAIL\n"); 34762306a36Sopenharmony_ci else 34862306a36Sopenharmony_ci printf("Kernel does not support setting the " 34962306a36Sopenharmony_ci "default mq attributes,\n" 35062306a36Sopenharmony_ci "but also doesn't tie the defaults to " 35162306a36Sopenharmony_ci "the maximums:\t\t\tPASS\n"); 35262306a36Sopenharmony_ci } 35362306a36Sopenharmony_ci } else { 35462306a36Sopenharmony_ci printf("Kernel supports setting defaults separately from " 35562306a36Sopenharmony_ci "maximums:\t\tPASS\n"); 35662306a36Sopenharmony_ci /* 35762306a36Sopenharmony_ci * While we are here, go ahead and test that the kernel 35862306a36Sopenharmony_ci * properly follows the default settings 35962306a36Sopenharmony_ci */ 36062306a36Sopenharmony_ci test_queue(NULL, &result); 36162306a36Sopenharmony_ci printf("Given sane values, mq_open without an attr struct " 36262306a36Sopenharmony_ci "succeeds:\t\tPASS\n"); 36362306a36Sopenharmony_ci if (result.mq_maxmsg != cur_def_msgs || 36462306a36Sopenharmony_ci result.mq_msgsize != cur_def_msgsize) 36562306a36Sopenharmony_ci printf("Kernel supports setting defaults, but does " 36662306a36Sopenharmony_ci "not actually honor them:\tFAIL\n\n"); 36762306a36Sopenharmony_ci else { 36862306a36Sopenharmony_ci set(def_msgs, ++cur_def_msgs); 36962306a36Sopenharmony_ci set(def_msgsize, ++cur_def_msgsize); 37062306a36Sopenharmony_ci /* In case max was the same as the default */ 37162306a36Sopenharmony_ci set(max_msgs, ++cur_max_msgs); 37262306a36Sopenharmony_ci set(max_msgsize, ++cur_max_msgsize); 37362306a36Sopenharmony_ci test_queue(NULL, &result); 37462306a36Sopenharmony_ci if (result.mq_maxmsg != cur_def_msgs || 37562306a36Sopenharmony_ci result.mq_msgsize != cur_def_msgsize) 37662306a36Sopenharmony_ci printf("Kernel supports setting defaults, but " 37762306a36Sopenharmony_ci "does not actually honor them:\t" 37862306a36Sopenharmony_ci "FAIL\n"); 37962306a36Sopenharmony_ci else 38062306a36Sopenharmony_ci printf("Kernel properly honors default setting " 38162306a36Sopenharmony_ci "knobs:\t\t\t\tPASS\n"); 38262306a36Sopenharmony_ci } 38362306a36Sopenharmony_ci set(def_msgs, cur_max_msgs + 1); 38462306a36Sopenharmony_ci cur_def_msgs = cur_max_msgs + 1; 38562306a36Sopenharmony_ci set(def_msgsize, cur_max_msgsize + 1); 38662306a36Sopenharmony_ci cur_def_msgsize = cur_max_msgsize + 1; 38762306a36Sopenharmony_ci if (cur_def_msgs * (cur_def_msgsize + 2 * sizeof(void *)) >= 38862306a36Sopenharmony_ci cur_limits.rlim_cur) { 38962306a36Sopenharmony_ci cur_limits.rlim_cur = (cur_def_msgs + 2) * 39062306a36Sopenharmony_ci (cur_def_msgsize + 2 * sizeof(void *)); 39162306a36Sopenharmony_ci cur_limits.rlim_max = 2 * cur_limits.rlim_cur; 39262306a36Sopenharmony_ci setr(RLIMIT_MSGQUEUE, &cur_limits); 39362306a36Sopenharmony_ci } 39462306a36Sopenharmony_ci if (test_queue_fail(NULL, &result)) { 39562306a36Sopenharmony_ci if (result.mq_maxmsg == cur_max_msgs && 39662306a36Sopenharmony_ci result.mq_msgsize == cur_max_msgsize) 39762306a36Sopenharmony_ci printf("Kernel properly limits default values " 39862306a36Sopenharmony_ci "to lesser of default/max:\t\tPASS\n"); 39962306a36Sopenharmony_ci else 40062306a36Sopenharmony_ci printf("Kernel does not properly set default " 40162306a36Sopenharmony_ci "queue parameters when\ndefaults > " 40262306a36Sopenharmony_ci "max:\t\t\t\t\t\t\t\tFAIL\n"); 40362306a36Sopenharmony_ci } else 40462306a36Sopenharmony_ci printf("Kernel fails to open mq because defaults are " 40562306a36Sopenharmony_ci "greater than maximums:\tFAIL\n"); 40662306a36Sopenharmony_ci set(def_msgs, --cur_def_msgs); 40762306a36Sopenharmony_ci set(def_msgsize, --cur_def_msgsize); 40862306a36Sopenharmony_ci cur_limits.rlim_cur = cur_limits.rlim_max = cur_def_msgs * 40962306a36Sopenharmony_ci cur_def_msgsize; 41062306a36Sopenharmony_ci setr(RLIMIT_MSGQUEUE, &cur_limits); 41162306a36Sopenharmony_ci if (test_queue_fail(NULL, &result)) 41262306a36Sopenharmony_ci printf("Kernel creates queue even though defaults " 41362306a36Sopenharmony_ci "would exceed\nrlimit setting:" 41462306a36Sopenharmony_ci "\t\t\t\t\t\t\t\tFAIL\n"); 41562306a36Sopenharmony_ci else 41662306a36Sopenharmony_ci printf("Kernel properly fails to create queue when " 41762306a36Sopenharmony_ci "defaults would\nexceed rlimit:" 41862306a36Sopenharmony_ci "\t\t\t\t\t\t\t\tPASS\n"); 41962306a36Sopenharmony_ci } 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_ci /* 42262306a36Sopenharmony_ci * Test #2 - open with an attr struct that exceeds rlimit 42362306a36Sopenharmony_ci */ 42462306a36Sopenharmony_ci printf("\n\nTest series 2, behavior when attr struct is " 42562306a36Sopenharmony_ci "passed to mq_open:\n"); 42662306a36Sopenharmony_ci cur_max_msgs = 32; 42762306a36Sopenharmony_ci cur_max_msgsize = cur_limits.rlim_max >> 4; 42862306a36Sopenharmony_ci set(max_msgs, cur_max_msgs); 42962306a36Sopenharmony_ci set(max_msgsize, cur_max_msgsize); 43062306a36Sopenharmony_ci attr.mq_maxmsg = cur_max_msgs; 43162306a36Sopenharmony_ci attr.mq_msgsize = cur_max_msgsize; 43262306a36Sopenharmony_ci if (test_queue_fail(&attr, &result)) 43362306a36Sopenharmony_ci printf("Queue open in excess of rlimit max when euid = 0 " 43462306a36Sopenharmony_ci "succeeded:\t\tFAIL\n"); 43562306a36Sopenharmony_ci else 43662306a36Sopenharmony_ci printf("Queue open in excess of rlimit max when euid = 0 " 43762306a36Sopenharmony_ci "failed:\t\tPASS\n"); 43862306a36Sopenharmony_ci attr.mq_maxmsg = cur_max_msgs + 1; 43962306a36Sopenharmony_ci attr.mq_msgsize = 10; 44062306a36Sopenharmony_ci if (test_queue_fail(&attr, &result)) 44162306a36Sopenharmony_ci printf("Queue open with mq_maxmsg > limit when euid = 0 " 44262306a36Sopenharmony_ci "succeeded:\t\tPASS\n"); 44362306a36Sopenharmony_ci else 44462306a36Sopenharmony_ci printf("Queue open with mq_maxmsg > limit when euid = 0 " 44562306a36Sopenharmony_ci "failed:\t\tFAIL\n"); 44662306a36Sopenharmony_ci attr.mq_maxmsg = 1; 44762306a36Sopenharmony_ci attr.mq_msgsize = cur_max_msgsize + 1; 44862306a36Sopenharmony_ci if (test_queue_fail(&attr, &result)) 44962306a36Sopenharmony_ci printf("Queue open with mq_msgsize > limit when euid = 0 " 45062306a36Sopenharmony_ci "succeeded:\t\tPASS\n"); 45162306a36Sopenharmony_ci else 45262306a36Sopenharmony_ci printf("Queue open with mq_msgsize > limit when euid = 0 " 45362306a36Sopenharmony_ci "failed:\t\tFAIL\n"); 45462306a36Sopenharmony_ci attr.mq_maxmsg = 65536; 45562306a36Sopenharmony_ci attr.mq_msgsize = 65536; 45662306a36Sopenharmony_ci if (test_queue_fail(&attr, &result)) 45762306a36Sopenharmony_ci printf("Queue open with total size > 2GB when euid = 0 " 45862306a36Sopenharmony_ci "succeeded:\t\tFAIL\n"); 45962306a36Sopenharmony_ci else 46062306a36Sopenharmony_ci printf("Queue open with total size > 2GB when euid = 0 " 46162306a36Sopenharmony_ci "failed:\t\t\tPASS\n"); 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci if (seteuid(99) == -1) { 46462306a36Sopenharmony_ci perror("seteuid() failed"); 46562306a36Sopenharmony_ci exit(1); 46662306a36Sopenharmony_ci } 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci attr.mq_maxmsg = cur_max_msgs; 46962306a36Sopenharmony_ci attr.mq_msgsize = cur_max_msgsize; 47062306a36Sopenharmony_ci if (test_queue_fail(&attr, &result)) 47162306a36Sopenharmony_ci printf("Queue open in excess of rlimit max when euid = 99 " 47262306a36Sopenharmony_ci "succeeded:\t\tFAIL\n"); 47362306a36Sopenharmony_ci else 47462306a36Sopenharmony_ci printf("Queue open in excess of rlimit max when euid = 99 " 47562306a36Sopenharmony_ci "failed:\t\tPASS\n"); 47662306a36Sopenharmony_ci attr.mq_maxmsg = cur_max_msgs + 1; 47762306a36Sopenharmony_ci attr.mq_msgsize = 10; 47862306a36Sopenharmony_ci if (test_queue_fail(&attr, &result)) 47962306a36Sopenharmony_ci printf("Queue open with mq_maxmsg > limit when euid = 99 " 48062306a36Sopenharmony_ci "succeeded:\t\tFAIL\n"); 48162306a36Sopenharmony_ci else 48262306a36Sopenharmony_ci printf("Queue open with mq_maxmsg > limit when euid = 99 " 48362306a36Sopenharmony_ci "failed:\t\tPASS\n"); 48462306a36Sopenharmony_ci attr.mq_maxmsg = 1; 48562306a36Sopenharmony_ci attr.mq_msgsize = cur_max_msgsize + 1; 48662306a36Sopenharmony_ci if (test_queue_fail(&attr, &result)) 48762306a36Sopenharmony_ci printf("Queue open with mq_msgsize > limit when euid = 99 " 48862306a36Sopenharmony_ci "succeeded:\t\tFAIL\n"); 48962306a36Sopenharmony_ci else 49062306a36Sopenharmony_ci printf("Queue open with mq_msgsize > limit when euid = 99 " 49162306a36Sopenharmony_ci "failed:\t\tPASS\n"); 49262306a36Sopenharmony_ci attr.mq_maxmsg = 65536; 49362306a36Sopenharmony_ci attr.mq_msgsize = 65536; 49462306a36Sopenharmony_ci if (test_queue_fail(&attr, &result)) 49562306a36Sopenharmony_ci printf("Queue open with total size > 2GB when euid = 99 " 49662306a36Sopenharmony_ci "succeeded:\t\tFAIL\n"); 49762306a36Sopenharmony_ci else 49862306a36Sopenharmony_ci printf("Queue open with total size > 2GB when euid = 99 " 49962306a36Sopenharmony_ci "failed:\t\t\tPASS\n"); 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci shutdown(0,"",0); 50262306a36Sopenharmony_ci} 503